AWS Parameter Store Kullanımı: Uygulama Yapılandırmalarını Güvenli Yönetin

Uygulamalarınızın konfigürasyon yönetimi her zaman baş ağrısı olmuştur. Ortam değişkenlerini .env dosyalarına gömmek, şifreleri kod içinde bırakmak veya konfigürasyon değerlerini doğrudan uygulama içine hardcode etmek… Bunların hepsini bir noktada yaptık ve hepsinin acısını çektik. AWS Systems Manager Parameter Store tam da bu sorunu çözmek için var ve bir kez alışınca bir daha eski yöntemlere dönmek istemiyorsunuz.

Parameter Store Nedir ve Neden Kullanmalısınız?

AWS Systems Manager’ın bir parçası olan Parameter Store, konfigürasyon verilerinizi ve gizli bilgilerinizi merkezi bir yerde güvenli biçimde saklamanızı sağlar. Database bağlantı string’leri, API anahtarları, uygulama konfigürasyonları, feature flag’ler… Bunların hepsi Parameter Store’a gidebilir.

Secrets Manager ile karıştırılmamalı. İkisi de gizli bilgi saklayabilir ama aralarında temel farklar var. Parameter Store ücretsiz katmanı çok daha geniş, basit konfigürasyon değerleri için idealdir. Secrets Manager ise otomatik rotasyon ve çok daha gelişmiş gizli bilgi yönetimi sunar ama her secret için ücret ödersiniz. Çoğu senaryoda Parameter Store yeterlidir ve maliyetinizi ciddi ölçüde düşürür.

Parameter Store’un sunduğu temel avantajlar şunlardır:

  • Merkezi yönetim: Tüm ortamların konfigürasyonları tek yerden yönetilir
  • Versiyon takibi: Her değişiklik otomatik olarak versiyonlanır, geri dönmek kolaydır
  • KMS entegrasyonu: SecureString tipiyle değerler KMS ile şifrelenir
  • IAM ile ince taneli erişim kontrolü: Hangi servis hangi parametreye erişebilir, tam kontrol sizde
  • CloudFormation ve CDK entegrasyonu: Deployment süreçlerinizle doğal entegrasyon
  • Ücretsiz standart tier: 10.000 parametreye kadar ücretsiz, saatte 1000 API çağrısına kadar bedava

Parameter Tipleri

Parameter Store’da üç farklı parametre tipi bulunur:

  • String: Düz metin değerler. Uygulama adı, region, endpoint URL gibi hassas olmayan bilgiler için.
  • StringList: Virgülle ayrılmış değerler listesi. Birden fazla değeri tek parametrede tutmak için kullanışlı.
  • SecureString: KMS ile şifrelenmiş değerler. Şifreler, API anahtarları, database bağlantı string’leri için zorunlu.

Standard ve Advanced tier farkı da önemli. Standard tier’da parametre boyutu 4 KB ile sınırlı, Advanced’da 8 KB’a çıkıyor. Ayrıca Advanced tier’da parametre politikaları (TTL, bildirim gibi) kullanabiliyorsunuz. Maliyeti ise parametre başına aylık 0.05 dolar.

AWS CLI ile Parameter Store Kullanımı

Önce temel CLI komutlarına bakalım. Bunlar günlük operasyonlarda çok işinize yarayacak.

Parametre Oluşturma

# Basit string parametre oluşturma
aws ssm put-parameter 
  --name "/myapp/production/database/host" 
  --value "db.example.com" 
  --type String 
  --description "Production database host"

# SecureString ile şifreli parametre
aws ssm put-parameter 
  --name "/myapp/production/database/password" 
  --value "super-secret-password-123" 
  --type SecureString 
  --key-id "alias/myapp-key" 
  --description "Production database password"

# StringList örneği
aws ssm put-parameter 
  --name "/myapp/production/allowed-origins" 
  --value "https://example.com,https://www.example.com,https://api.example.com" 
  --type StringList

Parametre isimlendirmesinde hiyerarşik yapı kullanmak altın kural. /uygulama/ortam/kategori/isim formatı karmaşıklığı yönetmeyi çok kolaylaştırır.

Parametre Okuma

# Tek parametre okuma
aws ssm get-parameter 
  --name "/myapp/production/database/host" 
  --query "Parameter.Value" 
  --output text

# SecureString çözme (--with-decryption olmadan şifreli gelir)
aws ssm get-parameter 
  --name "/myapp/production/database/password" 
  --with-decryption 
  --query "Parameter.Value" 
  --output text

# Bir path altındaki tüm parametreleri çekme
aws ssm get-parameters-by-path 
  --path "/myapp/production/" 
  --recursive 
  --with-decryption 
  --query "Parameters[*].{Name:Name,Value:Value}"

Parametre Güncelleme ve Silme

# Mevcut parametreyi güncelleme (--overwrite zorunlu)
aws ssm put-parameter 
  --name "/myapp/production/database/host" 
  --value "new-db.example.com" 
  --type String 
  --overwrite

# Parametre silme
aws ssm delete-parameter 
  --name "/myapp/production/database/host"

# Birden fazla parametre silme
aws ssm delete-parameters 
  --names "/myapp/staging/db/host" "/myapp/staging/db/port" "/myapp/staging/db/name"

Gerçek Dünya Senaryosu: Node.js Uygulaması Entegrasyonu

Bir e-ticaret uygulaması geliştiriyorsunuz ve deployment sırasında ortam değişkenlerini Parameter Store’dan çekmek istiyorsunuz. İşte tam olarak böyle bir senaryo:

#!/bin/bash
# deploy-env.sh - Deployment sırasında environment değişkenlerini yükle

set -euo pipefail

ENVIRONMENT=${1:-staging}
APP_NAME="ecommerce"
REGION="eu-west-1"

echo "[$ENVIRONMENT] ortamı için parametreler yükleniyor..."

# Path altındaki tüm parametreleri çek ve export et
while IFS=$'t' read -r name value; do
  # /myapp/production/DATABASE_HOST -> DATABASE_HOST
  env_var=$(basename "$name")
  export "$env_var"="$value"
  echo "  Yüklendi: $env_var"
done < <(aws ssm get-parameters-by-path 
  --path "/${APP_NAME}/${ENVIRONMENT}/" 
  --recursive 
  --with-decryption 
  --region "$REGION" 
  --query "Parameters[*].[Name,Value]" 
  --output text)

echo "Tüm parametreler başarıyla yüklendi."

# Uygulamayı başlat
exec node server.js

Bu script’i Docker entrypoint olarak kullanabilirsiniz. Konteyner başladığında parametreleri çeker, ortam değişkenlerine atar ve uygulamayı başlatır. .env dosyası yok, hardcode değer yok, temiz bir çözüm.

Lambda Fonksiyonlarında Parameter Store Kullanımı

Lambda’da Parameter Store kullanırken dikkat edilmesi gereken önemli bir nokta var: Her invocation’da parametre çekmek Lambda’nızı yavaşlatır ve maliyeti artırır. Doğru yaklaşım değerleri cache’lemektir.

import boto3
import os
import json
from functools import lru_cache

# Boto3 client'ı modül seviyesinde oluşturun (cold start'ta bir kez çalışır)
ssm = boto3.client('ssm', region_name='eu-west-1')

@lru_cache(maxsize=None)
def get_parameter(name, with_decryption=True):
    """
    Parameter Store'dan değer çeker ve cache'ler.
    Lambda execution context yaşadığı sürece cache geçerlidir.
    """
    try:
        response = ssm.get_parameter(
            Name=name,
            WithDecryption=with_decryption
        )
        return response['Parameter']['Value']
    except ssm.exceptions.ParameterNotFound:
        raise ValueError(f"Parametre bulunamadı: {name}")

def get_db_config():
    """Database konfigürasyonunu Parameter Store'dan yükler."""
    env = os.environ.get('ENVIRONMENT', 'staging')
    
    return {
        'host': get_parameter(f'/myapp/{env}/database/host'),
        'port': int(get_parameter(f'/myapp/{env}/database/port')),
        'name': get_parameter(f'/myapp/{env}/database/name'),
        'password': get_parameter(f'/myapp/{env}/database/password'),
    }

def handler(event, context):
    # İlk çağrıda çeker, sonraki çağrılarda cache'den döner
    db_config = get_db_config()
    
    # İş mantığı buraya
    return {
        'statusCode': 200,
        'body': json.dumps({'status': 'ok'})
    }

Lambda için IAM rolüne şu izinleri vermeyi unutmayın:

# Lambda için minimum gerekli SSM izinleri
aws iam create-policy 
  --policy-name "LambdaSSMReadPolicy" 
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "ssm:GetParameter",
          "ssm:GetParameters",
          "ssm:GetParametersByPath"
        ],
        "Resource": "arn:aws:ssm:eu-west-1:123456789012:parameter/myapp/production/*"
      },
      {
        "Effect": "Allow",
        "Action": [
          "kms:Decrypt"
        ],
        "Resource": "arn:aws:kms:eu-west-1:123456789012:key/your-key-id"
      }
    ]
  }'

CloudFormation ile Entegrasyon

CloudFormation template’lerinde Parameter Store referansı kullanmak çok güçlü bir özellik. Özellikle paylaşılan konfigürasyonlar için idealdir.

# cloudformation-template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Parameter Store entegrasyonlu uygulama stack'

Parameters:
  Environment:
    Type: String
    Default: staging
    AllowedValues: [staging, production]

  # Parameter Store'dan dinamik değer çekme
  DatabaseHost:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /myapp/production/database/host

Resources:
  AppTaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: myapp
      ContainerDefinitions:
        - Name: app
          Image: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/myapp:latest"
          Secrets:
            # ECS task definition'da doğrudan SSM referansı
            - Name: DATABASE_PASSWORD
              ValueFrom: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/myapp/${Environment}/database/password"
            - Name: API_KEY
              ValueFrom: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/myapp/${Environment}/api-key"
          Environment:
            - Name: DATABASE_HOST
              Value: !Ref DatabaseHost
            - Name: ENVIRONMENT
              Value: !Ref Environment

ECS’de Secrets bloğunu kullandığınızda, AWS ECS agent container başlamadan önce SSM’den değerleri çeker ve ortam değişkeni olarak enjekte eder. Uygulamanız hiçbir SSM SDK kodu yazmadan değerlere erişebilir.

Toplu Parametre Yönetimi: Import/Export

Birden fazla ortam veya parametre yönetirken toplu işlemler hayat kurtarır. JSON dosyasından toplu parametre yükleme:

#!/bin/bash
# import-parameters.sh

ENVIRONMENT=${1:-staging}
CONFIG_FILE="config/${ENVIRONMENT}.json"

if [ ! -f "$CONFIG_FILE" ]; then
  echo "Config dosyası bulunamadı: $CONFIG_FILE"
  exit 1
fi

# JSON dosyasını oku ve her parametreyi yükle
jq -r 'to_entries[] | [.key, .value.value, .value.type, .value.description] | @tsv' "$CONFIG_FILE" | 
while IFS=$'t' read -r key value type description; do
  full_path="/myapp/${ENVIRONMENT}/${key}"
  
  echo "Yükleniyor: $full_path"
  
  aws ssm put-parameter 
    --name "$full_path" 
    --value "$value" 
    --type "$type" 
    --description "$description" 
    --overwrite 
    --no-cli-pager
    
  echo "  Tamamlandi: $full_path"
done

echo ""
echo "Tüm parametreler başarıyla yüklendi."

Bu script’le birlikte kullanabileceğiniz örnek JSON konfigürasyon dosyası:

{
  "database/host": {
    "value": "db.staging.example.com",
    "type": "String",
    "description": "Staging database host"
  },
  "database/port": {
    "value": "5432",
    "type": "String",
    "description": "Database port"
  },
  "app/log-level": {
    "value": "debug",
    "type": "String",
    "description": "Uygulama log seviyesi"
  }
}

Parametre Versiyonlama ve Rollback

Parameter Store’un gizli silahlarından biri versiyonlama. Her put-parameter çağrısı yeni bir versiyon oluşturur ve istediğiniz versiyona belirli bir versiyona referans verebilirsiniz.

# Parametre geçmişini görme
aws ssm get-parameter-history 
  --name "/myapp/production/database/host" 
  --query "Parameters[*].{Version:Version,Value:Value,Modified:LastModifiedDate}" 
  --output table

# Belirli bir versiyona referans (deployment'ta kullanışlı)
aws ssm get-parameter 
  --name "/myapp/production/database/host:3" 
  --query "Parameter.Value" 
  --output text

# Eski versiyona rollback (önceki değeri tekrar yaz)
OLD_VALUE=$(aws ssm get-parameter 
  --name "/myapp/production/database/host:2" 
  --query "Parameter.Value" 
  --output text)

aws ssm put-parameter 
  --name "/myapp/production/database/host" 
  --value "$OLD_VALUE" 
  --type String 
  --overwrite
  
echo "Rollback tamamlandi. Eski deger: $OLD_VALUE"

Prodüksiyon ortamında bir konfigürasyon değişikliği uygulamayı çökerttiğinde bu versiyonlama özelliği sizi kurtarır. Anında önceki versiyona dönebilirsiniz.

Parametre Değişikliklerini Takip Etme: CloudWatch Events

Parametre değişikliklerinde otomatik bildirim almak için EventBridge kullanabilirsiniz:

# SSM parametre değişikliklerini yakalayan EventBridge kuralı
aws events put-rule 
  --name "SSMParameterChangeAlert" 
  --event-pattern '{
    "source": ["aws.ssm"],
    "detail-type": ["Parameter Store Change"],
    "detail": {
      "name": [{"prefix": "/myapp/production/"}],
      "operation": ["Create", "Update", "Delete"]
    }
  }' 
  --state ENABLED 
  --description "Prodüksiyon SSM parametre değişikliklerini izle"

# SNS topic'e bildirim hedefi ekle
aws events put-targets 
  --rule "SSMParameterChangeAlert" 
  --targets '[
    {
      "Id": "NotifySNS",
      "Arn": "arn:aws:sns:eu-west-1:123456789012:ops-alerts"
    }
  ]'

Bu kurulumla, prodüksiyon parametrelerinizde herhangi bir değişiklik olduğunda anında bildirim alırsınız. Yetkisiz değişiklikleri anında fark edersiniz.

Güvenlik Best Practice’leri

Parameter Store kullanırken güvenlik açısından dikkat etmeniz gereken birkaç kritik konu var:

  • En az yetki prensibi: Her servis sadece kendi namespace’indeki parametrelere erişebilmeli. /myapp/service-a/ için ayrı IAM policy, /myapp/service-b/ için ayrı.
  • KMS CMK kullanımı: SecureString için AWS managed key yerine kendi Customer Managed Key’inizi kullanın. Böylece anahtar rotasyonunu ve erişimi tam kontrol edersiniz.
  • CloudTrail loglama: SSM API çağrıları otomatik olarak CloudTrail’e düşer. Kim ne zaman hangi parametreye erişti, değiştirdi, sildi, hepsi kayıt altında.
  • Resource tag’leme: Parametrelerinizi mutlaka tagleyın. Maliyet takibi ve erişim kontrolü için çok işe yarar.
  • Parameter adında ortamı belirtin: /prod/db/password yerine /myapp/production/database/password gibi açıklayıcı isimler kullanın. Yanlış ortam parametresini çekme riskini minimuma indirirsiniz.
  • Değerleri log’a yazdırmayın: SecureString değerleri çektikten sonra log’a, debug çıktısına veya hata mesajına asla yazdırmayın.

Terraform ile Parameter Store Yönetimi

Infrastructure as Code kullanıyorsanız Terraform’da Parameter Store’u şöyle yönetebilirsiniz:

# variables.tf
variable "environment" {
  type    = string
  default = "staging"
}

# ssm.tf
resource "aws_ssm_parameter" "db_host" {
  name        = "/myapp/${var.environment}/database/host"
  type        = "String"
  value       = aws_db_instance.main.address
  description = "${var.environment} ortamı database host"

  tags = {
    Environment = var.environment
    Application = "myapp"
    ManagedBy   = "terraform"
  }
}

resource "aws_ssm_parameter" "db_password" {
  name        = "/myapp/${var.environment}/database/password"
  type        = "SecureString"
  value       = random_password.db.result
  key_id      = aws_kms_key.ssm.arn
  description = "${var.environment} ortamı database şifresi"

  tags = {
    Environment = var.environment
    Application = "myapp"
    ManagedBy   = "terraform"
  }
}

# Başka bir module'de parametre değerini okuma
data "aws_ssm_parameter" "db_host" {
  name = "/myapp/${var.environment}/database/host"
}

output "database_host" {
  value = data.aws_ssm_parameter.db_host.value
}

Terraform’da dikkat edilmesi gereken önemli bir nokta: SecureString değerler terraform.tfstate dosyasına düz metin olarak yazılır. State dosyanızı S3’te şifrelenmiş olarak saklayın ve erişimi kısıtlayın.

Sonuç

Parameter Store, AWS üzerinde çalışan uygulamalar için konfigürasyon yönetiminin olmazsa olmaz bir parçası. Ücretsiz standart tier ile başlayabilir, karmaşıklık arttıkça Advanced tier’a geçebilirsiniz.

Özetlemek gerekirse, hemen bugün yapabileceğiniz şeyler şunlar:

  • Mevcut .env dosyalarınızı ve hardcode değerlerinizi inventarize edin
  • Hiyerarşik bir parametre isimlendirme standardı belirleyin
  • Hassas değerlerin hepsini SecureString olarak taşıyın
  • ECS veya Lambda deployment’larınızda SSM entegrasyonunu aktif edin
  • EventBridge ile parametre değişiklik bildirimlerini kurun

Konfigürasyon yönetimi bir kez düzgün kurulunca, hem güvenlik hem de operasyonel verimlilik açısından ciddi kazanımlar elde edersiniz. Deployment süreçleriniz standardize olur, ortamlar arası tutarsızlıklar azalır, gizli bilgi sızıntısı riski minimuma iner. Bu işe yatırdığınız birkaç saatlik kurulum zamanı, uzun vadede on kat fazlasını geri öder.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir