AWS Config ile Kaynak Uyumluluk Denetimi
Bulut altyapılarının büyümesiyle birlikte “acaba tüm kaynaklarım doğru yapılandırılmış mı?” sorusu artık her sysadmin’in aklını kurcalayan bir sorguya dönüştü. Yüzlerce EC2 instance’ı, onlarca S3 bucket’ı ve sayısız IAM policy’si olan bir ortamda manuel denetim yapmak hem zaman kaybı hem de hata riski demek. AWS Config tam da bu noktada devreye giriyor: kaynaklarınızı sürekli izleyen, değişiklikleri kaydeden ve belirlediğiniz kurallarla uyumluluğu otomatik kontrol eden bir hizmet.
AWS Config Nedir ve Neden Kullanmalısınız
AWS Config, AWS kaynaklarınızın yapılandırmasını sürekli olarak kaydeden ve bu kayıtlar üzerinden uyumluluk değerlendirmesi yapmanızı sağlayan bir hizmettir. “Configuration Management Database” kavramının bulut dünyasındaki karşılığı olarak da düşünebilirsiniz.
Somut bir senaryo düşünelim: Güvenlik ekibiniz tüm S3 bucket’larının public erişime kapalı olması gerektiğini söylüyor. Siz de bunu yapılandırıyorsunuz. Ama bir geliştirici iki gün sonra test amaçlı bir bucket’ı public yapıyor ve kimse fark etmiyor. İşte AWS Config bu durumu anında yakalıyor, kayıt altına alıyor ve sizi uyarıyor.
AWS Config’in temel yetenekleri şunlar:
- Configuration History: Herhangi bir kaynağın zaman içinde nasıl değiştiğini görebilirsiniz
- Configuration Snapshot: Belirli bir andaki tüm altyapı yapılandırmanızın fotoğrafını çekebilirsiniz
- Compliance Rules: Önceden tanımlanmış veya kendi yazdığınız kurallarla uyumluluk kontrolü yapabilirsiniz
- Remediation: Uyumsuz kaynakları otomatik olarak düzeltebilirsiniz
- Multi-account/Multi-region: Tüm AWS organizasyonunuzu tek noktadan yönetebilirsiniz
AWS Config’i Aktif Etme
İlk olarak AWS Config’i AWS CLI üzerinden aktif edelim. Önce gerekli IAM rolünü oluşturalım:
# Config için service role oluşturma
aws iam create-role
--role-name AWSConfigRole
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
# AWS managed policy'yi role ekle
aws iam attach-role-policy
--role-name AWSConfigRole
--policy-arn arn:aws:iam::aws:policy/service-role/AWS_ConfigRole
Şimdi Config’in kayıtları yazacağı S3 bucket’ını oluşturalım:
# Hesap ID'nizi alın
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION="eu-west-1"
BUCKET_NAME="aws-config-logs-${ACCOUNT_ID}-${REGION}"
# Bucket oluştur
aws s3 mb s3://${BUCKET_NAME} --region ${REGION}
# Bucket policy ekle (Config'in yazabilmesi için)
cat > /tmp/config-bucket-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSConfigBucketPermissionsCheck",
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::${BUCKET_NAME}"
},
{
"Sid": "AWSConfigBucketDelivery",
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::${BUCKET_NAME}/AWSLogs/${ACCOUNT_ID}/Config/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
EOF
aws s3api put-bucket-policy
--bucket ${BUCKET_NAME}
--policy file:///tmp/config-bucket-policy.json
Configuration recorder’ı başlatalım:
# Delivery channel oluştur
aws configservice put-delivery-channel
--delivery-channel "{
"name": "default",
"s3BucketName": "${BUCKET_NAME}",
"configSnapshotDeliveryProperties": {
"deliveryFrequency": "TwentyFour_Hours"
}
}"
# Configuration recorder başlat
aws configservice put-configuration-recorder
--configuration-recorder "{
"name": "default",
"roleARN": "arn:aws:iam::${ACCOUNT_ID}:role/AWSConfigRole",
"recordingGroup": {
"allSupported": true,
"includeGlobalResourceTypes": true
}
}"
# Recorder'ı aktif et
aws configservice start-configuration-recorder
--configuration-recorder-name default
echo "AWS Config başarıyla aktif edildi!"
Managed Rules ile Hızlı Başlangıç
AWS Config, 150’den fazla önceden hazırlanmış kural (managed rule) sunuyor. Bu kuralları tek tek aktif etmek yerine en kritik olanları bir script ile toplu ekleyelim:
#!/bin/bash
# Temel güvenlik kurallarını aktif eden script
RULES=(
"s3-bucket-public-read-prohibited"
"s3-bucket-public-write-prohibited"
"s3-bucket-server-side-encryption-enabled"
"ec2-instance-no-public-ip"
"restricted-ssh"
"restricted-common-ports"
"iam-password-policy"
"iam-root-access-key-check"
"mfa-enabled-for-iam-console-access"
"cloudtrail-enabled"
"vpc-flow-logs-enabled"
"ebs-snapshot-public-restorable-check"
)
for rule in "${RULES[@]}"; do
echo "Kural ekleniyor: ${rule}"
aws configservice put-config-rule
--config-rule "{
"ConfigRuleName": "${rule}",
"Source": {
"Owner": "AWS",
"SourceIdentifier": "$(echo ${rule} | tr '-' '_' | tr '[:lower:]' '[:upper:]')"
}
}" 2>/dev/null || echo "HATA: ${rule} eklenemedi, identifier kontrol edin"
sleep 1
done
echo "Kural ekleme işlemi tamamlandı."
Not: Managed rule’ların SourceIdentifier değerleri AWS dokümantasyonundan doğrulanmalıdır. Örneğin s3-bucket-public-read-prohibited kuralının identifier’ı S3_BUCKET_PUBLIC_READ_PROHIBITED şeklinde.
Uyumluluk Durumunu Sorgulama
Kuralları ekledikten sonra hangi kaynaklarınızın uyumsuz olduğunu görmek için:
#!/bin/bash
# Uyumsuz kaynakları listeleyen script
echo "=== UYUMSUZ KAYNAKLAR RAPORU ==="
echo "Tarih: $(date)"
echo ""
# Her kural için uyumsuzlukları getir
aws configservice get-compliance-details-by-config-rule
--config-rule-name "s3-bucket-public-read-prohibited"
--compliance-types NON_COMPLIANT
--query 'EvaluationResults[*].{Kaynak:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId, Tip:EvaluationResultIdentifier.EvaluationResultQualifier.ResourceType, Zaman:ResultRecordedTime}'
--output table
echo ""
echo "=== GENEL UYUMLULUK OZETI ==="
aws configservice describe-compliance-by-config-rule
--query 'ComplianceByConfigRules[*].{Kural:ConfigRuleName, Durum:Compliance.ComplianceType}'
--output table
Belirli bir kaynağın tüm kurallara göre durumunu kontrol etmek için:
# Belirli bir EC2 instance'ının uyumluluk durumu
INSTANCE_ID="i-0123456789abcdef0"
aws configservice get-compliance-details-by-resource
--resource-type AWS::EC2::Instance
--resource-id ${INSTANCE_ID}
--query 'EvaluationResults[*].{Kural:EvaluationResultIdentifier.EvaluationResultQualifier.ConfigRuleName, Durum:ComplianceType}'
--output table
Özel Kural Yazma: Lambda ile Custom Rule
Managed rules her zaman ihtiyacınızı karşılamaz. Diyelim ki “tüm EC2 instance’larında belirli tag’ler olmalı” gibi kurumsal bir politikanız var. Bunun için custom rule yazmanız gerekiyor.
Önce Lambda fonksiyonunu yazalım:
# lambda_function.py
import json
import boto3
config_client = boto3.client('config')
REQUIRED_TAGS = ['Environment', 'Owner', 'Project', 'CostCenter']
def evaluate_compliance(configuration_item):
"""EC2 instance'ının gerekli tag'lere sahip olup olmadığını kontrol et"""
if configuration_item['resourceType'] != 'AWS::EC2::Instance':
return 'NOT_APPLICABLE'
tags = configuration_item.get('tags', {})
missing_tags = []
for required_tag in REQUIRED_TAGS:
if required_tag not in tags:
missing_tags.append(required_tag)
if missing_tags:
return {
'compliance_type': 'NON_COMPLIANT',
'annotation': f"Eksik tag'ler: {', '.join(missing_tags)}"
}
return {
'compliance_type': 'COMPLIANT',
'annotation': 'Tüm gerekli tag'ler mevcut'
}
def lambda_handler(event, context):
invoking_event = json.loads(event['invokingEvent'])
rule_parameters = {}
if 'ruleParameters' in event:
rule_parameters = json.loads(event['ruleParameters'])
configuration_item = invoking_event.get('configurationItem')
if configuration_item is None:
return
# Silinmiş kaynakları atla
if configuration_item['configurationItemStatus'] == 'ResourceDeleted':
result = 'NOT_APPLICABLE'
annotation = 'Kaynak silinmiş'
else:
evaluation_result = evaluate_compliance(configuration_item)
if isinstance(evaluation_result, dict):
result = evaluation_result['compliance_type']
annotation = evaluation_result['annotation']
else:
result = evaluation_result
annotation = ''
evaluation = {
'ComplianceResourceType': configuration_item['resourceType'],
'ComplianceResourceId': configuration_item['resourceId'],
'ComplianceType': result,
'OrderingTimestamp': configuration_item['configurationItemCaptureTime']
}
if annotation:
evaluation['Annotation'] = annotation
config_client.put_evaluations(
Evaluations=[evaluation],
ResultToken=event['resultToken']
)
print(f"Değerlendirme tamamlandı: {configuration_item['resourceId']} - {result}")
Lambda fonksiyonunu deploy edelim ve Config rule olarak ekleyelim:
# Lambda fonksiyonunu zip'le
zip -j /tmp/tag-compliance-rule.zip lambda_function.py
# Lambda oluştur
aws lambda create-function
--function-name config-ec2-tag-compliance
--runtime python3.11
--role arn:aws:iam::${ACCOUNT_ID}:role/LambdaConfigRole
--handler lambda_function.lambda_handler
--zip-file fileb:///tmp/tag-compliance-rule.zip
--timeout 60
# Config'in Lambda'yı çağırabilmesi için izin ekle
aws lambda add-permission
--function-name config-ec2-tag-compliance
--statement-id AllowConfigInvoke
--action lambda:InvokeFunction
--principal config.amazonaws.com
# Custom rule'u Config'e ekle
aws configservice put-config-rule
--config-rule '{
"ConfigRuleName": "ec2-required-tags-check",
"Description": "EC2 instancelarinda zorunlu tagler kontrolu",
"Scope": {
"ComplianceResourceTypes": ["AWS::EC2::Instance"]
},
"Source": {
"Owner": "CUSTOM_LAMBDA",
"SourceIdentifier": "arn:aws:lambda:'${REGION}':'${ACCOUNT_ID}':function:config-ec2-tag-compliance",
"SourceDetails": [
{
"EventSource": "aws.config",
"MessageType": "ConfigurationItemChangeNotification"
}
]
}
}'
echo "Custom kural başarıyla eklendi!"
Otomatik Düzeltme (Auto Remediation)
Uyumsuzlukları tespit etmek yetmez, otomatik düzeltme de yapabilirsiniz. Örneğin public S3 bucket’larını otomatik olarak private yapabilirsiniz:
# SSM Automation document'ı kullanarak remediation ekle
aws configservice put-remediation-configurations
--remediation-configurations '[
{
"ConfigRuleName": "s3-bucket-public-read-prohibited",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWS-DisableS3BucketPublicReadWrite",
"Parameters": {
"AutomationAssumeRole": {
"StaticValue": {
"Values": ["arn:aws:iam::'${ACCOUNT_ID}':role/AutoRemediationRole"]
}
},
"S3BucketName": {
"ResourceValue": {
"Value": "RESOURCE_ID"
}
}
},
"Automatic": true,
"MaximumAutomaticAttempts": 3,
"RetryAttemptSeconds": 60
}
]'
Dikkat: Otomatik düzeltmeyi production’da etkinleştirmeden önce mutlaka test ortamında deneyin. Yanlış yapılandırılmış bir remediation, çalışan sistemleri bozabilir.
Conformance Pack ile Standart Paketler
AWS Config Conformance Pack’leri, birden fazla kuralı tek bir şablon olarak yönetmenizi sağlar. CIS AWS Foundations Benchmark gibi standartları kolayca uygulayabilirsiniz:
# CIS Level 1 conformance pack'i deploy et
aws configservice put-conformance-pack
--conformance-pack-name "cis-aws-foundations-benchmark"
--template-s3-uri "s3://aws-config-rules-packages-${REGION}/conformance-packs/Operational-Best-Practices-for-CIS-AWS-v1.4-Level1.yaml"
--delivery-s3-bucket ${BUCKET_NAME}
# Conformance pack durumunu kontrol et
aws configservice describe-conformance-pack-status
--conformance-pack-names "cis-aws-foundations-benchmark"
--query 'ConformancePackStatusDetails[*].{Ad:ConformancePackName, Durum:ConformancePackState}'
Kendi conformance pack YAML’ınızı da yazabilirsiniz:
cat > /tmp/custom-conformance-pack.yaml << 'EOF'
Parameters:
MaxAccessKeyAge:
Default: "90"
Type: String
Resources:
S3PublicReadProhibited:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-public-read-prohibited
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_PUBLIC_READ_PROHIBITED
IAMPasswordPolicy:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: iam-password-policy-check
Source:
Owner: AWS
SourceIdentifier: IAM_PASSWORD_POLICY
InputParameters:
MinimumPasswordLength: "14"
RequireUppercaseCharacters: "true"
RequireLowercaseCharacters: "true"
RequireNumbers: "true"
RequireSymbols: "true"
MaxPasswordAge: "90"
PasswordReusePrevention: "24"
AccessKeyRotation:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: access-keys-rotated
Source:
Owner: AWS
SourceIdentifier: ACCESS_KEYS_ROTATED
InputParameters:
maxAccessKeyAge: !Ref MaxAccessKeyAge
EOF
# S3'e yükle ve deploy et
aws s3 cp /tmp/custom-conformance-pack.yaml s3://${BUCKET_NAME}/conformance-packs/
aws configservice put-conformance-pack
--conformance-pack-name "kurumsal-guvenlik-standartlari"
--template-s3-uri "s3://${BUCKET_NAME}/conformance-packs/custom-conformance-pack.yaml"
--delivery-s3-bucket ${BUCKET_NAME}
Uyumluluk Raporları Oluşturma
Yöneticilere sunmak üzere düzenli raporlar oluşturan bir script hazırlayalım:
#!/bin/bash
# Haftalik uyumluluk raporu olusturucu
REPORT_DATE=$(date +%Y-%m-%d)
REPORT_FILE="/tmp/aws-config-compliance-${REPORT_DATE}.txt"
cat > ${REPORT_FILE} << HEADER
AWS CONFIG UYUMLULUK RAPORU
Tarih: ${REPORT_DATE}
Hesap: $(aws sts get-caller-identity --query Account --output text)
Bolge: ${AWS_DEFAULT_REGION:-eu-west-1}
========================================
HEADER
# Toplam kural sayısı ve uyumluluk oranı
echo "GENEL OZET" >> ${REPORT_FILE}
echo "----------" >> ${REPORT_FILE}
TOTAL=$(aws configservice describe-config-rules
--query 'length(ConfigRules)' --output text)
COMPLIANT=$(aws configservice describe-compliance-by-config-rule
--compliance-types COMPLIANT
--query 'length(ComplianceByConfigRules)' --output text)
NON_COMPLIANT=$(aws configservice describe-compliance-by-config-rule
--compliance-types NON_COMPLIANT
--query 'length(ComplianceByConfigRules)' --output text)
echo "Toplam Kural: ${TOTAL}" >> ${REPORT_FILE}
echo "Uyumlu: ${COMPLIANT}" >> ${REPORT_FILE}
echo "Uyumsuz: ${NON_COMPLIANT}" >> ${REPORT_FILE}
if [ "${TOTAL}" -gt 0 ]; then
COMPLIANCE_RATE=$(echo "scale=1; ${COMPLIANT} * 100 / ${TOTAL}" | bc)
echo "Uyumluluk Orani: %${COMPLIANCE_RATE}" >> ${REPORT_FILE}
fi
echo "" >> ${REPORT_FILE}
echo "UYUMSUZ KURALLAR" >> ${REPORT_FILE}
echo "----------------" >> ${REPORT_FILE}
# Uyumsuz kuralları listele
aws configservice describe-compliance-by-config-rule
--compliance-types NON_COMPLIANT
--query 'ComplianceByConfigRules[*].ConfigRuleName'
--output text | tr 't' 'n' >> ${REPORT_FILE}
echo "" >> ${REPORT_FILE}
echo "Rapor olusturuldu: ${REPORT_FILE}"
cat ${REPORT_FILE}
# Raporu SNS ile gonder (optional)
# aws sns publish
# --topic-arn "arn:aws:sns:${REGION}:${ACCOUNT_ID}:aws-config-reports"
# --message file://${REPORT_FILE}
# --subject "AWS Config Haftalik Raporu - ${REPORT_DATE}"
Maliyet Optimizasyonu ve İpuçları
AWS Config kullanırken dikkat edilmesi gereken bazı noktalara değinelim:
- Kayıt edilen kaynak sayısını optimize edin: Her kaynak değişikliği için ücret ödersiniz. Gereksiz kaynakları kayıt dışı bırakabilirsiniz
- Snapshot sıklığını ayarlayın: Çok sık snapshot almak maliyet artırır, günlük genellikle yeterlidir
- S3 lifecycle policy ekleyin: Config logları zamanla büyür, eski kayıtları Glacier’a taşıyın
- Multi-region kurulum: Her bölge için ayrı ücretlendirme yapılır, sadece kullandığınız bölgelerde aktif edin
- Aggregator kullanın: Çok hesaplı ortamlarda merkezi bir aggregator kurarak yönetimi basitleştirin
S3 lifecycle policy eklemek için:
aws s3api put-bucket-lifecycle-configuration
--bucket ${BUCKET_NAME}
--lifecycle-configuration '{
"Rules": [
{
"ID": "config-logs-lifecycle",
"Status": "Enabled",
"Filter": {"Prefix": "AWSLogs/"},
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER"
}
],
"Expiration": {
"Days": 365
}
}
]
}'
Gerçek Dünya Senaryosu: PCI-DSS Uyumluluğu
Bir fintech şirketinde çalıştığınızı ve PCI-DSS uyumluluğunu AWS Config ile otomatize etmeniz gerektiğini düşünün. En kritik kontroller şunlar olur:
- Tüm veritabanı instance’larının şifrelenmiş olması (RDS encryption at rest)
- Security group’larda gereksiz portların açık olmaması
- CloudTrail’in tüm bölgelerde aktif olması
- Tüm kullanıcıların MFA kullanması
- Root account erişim anahtarı olmaması
Bu kontrolleri conformance pack olarak paketleyip hem dev hem de prod hesaplarına Organizations üzerinden dağıtabilirsiniz. Herhangi bir uyumsuzluk durumunda SNS üzerinden güvenlik ekibine anlık bildirim gidecek şekilde EventBridge entegrasyonu kurabilirsiniz.
Denetçiler her yıl geldiğinde “sistemleriniz uyumlu mu?” diye sorduğunda AWS Config Console’u açıp yeşil tiklerin olduğu ekranı göstermek, Excel dosyalarını karıştırmaktan çok daha profesyonel bir izlenim bırakır.
Sonuç
AWS Config, bulut altyapısında proaktif güvenlik ve uyumluluk yönetiminin temel taşlarından biri. Manuel kontrollerin aksine, sürekli çalışıyor, değişiklikleri anında yakalıyor ve tarihsel kayıt tutуyor. Bu makalede gördüklerimizi özetleyecek olursak:
Başlangıç için temel managed rule’larla işe başlayın, bunlar kurulum gerektirmiyor ve yaygın güvenlik açıklarını hızlıca yakalar. Kuruma özgü kurallar için Lambda tabanlı custom rule’lar yazın, bu size tam esneklik sağlar. İlgili kuralları conformance pack’lere toplayarak hem yönetimi basitleştirin hem de organizasyon genelinde standartları kolayca dağıtın. Remediation özelliğini dikkatli kullanın, önce “audit” modunda test edin, production’a geçmeden önce ne yapacağını iyice anlayın.
AWS Config’i tam olarak kullanamayan ekiplerin en büyük sorunu başlangıçtaki kurulum karmaşıklığı. Ama bir kez doğru kuruldu mu, sabahları ofise geldiğinizde “dün gece bir şey değişti mi, bir şey açıldı mı?” diye S3 loglarını karıştırmanız gerekmiyor. Config size söylüyor.
