AWS IAM Access Key Yönetimi ve Güvenliği
AWS hesabınızı açtığınız ilk günden itibaren karşınıza çıkan o küçük “Access Key ID” ve “Secret Access Key” ikilisi, aslında dünyalar kadar önem taşıyor. Yanlış yönetilen bir IAM access key, hem şirketinize astronomik faturaların gelmesine hem de ciddi güvenlik ihlallerine neden olabilir. Ben yıllar içinde onlarca farklı AWS ortamında çalıştım ve inanın en yaygın güvenlik açıklarının başında hâlâ IAM key yönetimi geliyor. Bu yazıda bu konuyu A’dan Z’ye ele alacağız.
IAM Access Key Nedir ve Neden Bu Kadar Kritik?
IAM access key’ler, AWS API’lerine programatik erişim için kullanılan kimlik bilgileridir. İki bileşenden oluşur:
- Access Key ID: Kullanıcı adı gibi düşünebilirsiniz, genellikle
AKIAile başlar - Secret Access Key: Şifre gibidir, yalnızca oluşturulduğu anda görünür
Bu key’lerin tehlikeli olmasının ana sebebi, doğru izinlerle birleştiğinde tüm AWS altyapınıza kapı aralayabilmeleri. GitHub’a yanlışlıkla push edilen bir access key, dakikalar içinde kötü aktörler tarafından bulunup kullanılabiliyor. Bu benim sadece söylediğim bir şey değil; GitGuardian’ın raporlarına göre her yıl milyonlarca secret credential GitHub’da tespit ediliyor.
Temel Güvenlik Prensipleri
Başlamadan önce şu prensibi kafanıza kazıyın: Least Privilege (En Az Yetki). Bir kullanıcı veya uygulama sadece ihtiyacı olan izinlere sahip olmalı, fazlası değil.
Root Account Key’i Asla Kullanmayın
AWS root hesabı için access key oluşturmak, evinizin ana kilidini sokağa bırakmak gibidir. Root account’a ait key’i silmeniz gerekiyor. Eğer hâlâ varsa şimdi silin:
# Root account key'lerinizi kontrol edin
aws iam get-account-summary --query 'SummaryMap.AccountAccessKeysPresent'
# Bu komut 1 dönüyorsa root key mevcut demektir
# Console'dan silmeniz gerekiyor
IAM User Yerine Role Kullanın
Mümkün olan her durumda uzun ömürlü access key’ler yerine IAM role kullanmayı tercih edin. Role’ler geçici credential üretir ve bu credential’lar otomatik olarak expire olur.
# EC2 instance'ınızın üzerindeki role credential'larını görmek için
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# STS ile geçici credential alma örneği
aws sts assume-role
--role-arn "arn:aws:iam::123456789012:role/MyAppRole"
--role-session-name "my-session"
--duration-seconds 3600
Mevcut Key’lerin Denetimi
Önce elinizin altındakileri iyi bilin. AWS hesabınızdaki tüm IAM kullanıcılarının key durumunu tek seferde görmek için credential report oluşturabilirsiniz.
# Credential report oluştur
aws iam generate-credential-report
# Raporu indir ve decode et
aws iam get-credential-report
--query 'Content'
--output text | base64 -d > credential_report.csv
# CSV'yi görüntüle
cat credential_report.csv
Bu rapor size her kullanıcı için şu bilgileri verir:
- user: IAM kullanıcı adı
- access_key_1_active: İlk key’in aktif olup olmadığı
- access_key_1_last_used_date: Son kullanım tarihi
- access_key_1_last_rotated: Son rotasyon tarihi
- access_key_2_active: İkinci key’in durumu
90 günden uzun süredir kullanılmayan key’leri tespit edip deaktive etmek iyi bir başlangıç noktasıdır. Şimdi bunu otomatize eden bir script yazalım:
#!/bin/bash
# inactive_keys_checker.sh
# 90 günden eski ve kullanılmayan key'leri listeler
THRESHOLD_DAYS=90
TODAY=$(date +%s)
echo "=== 90 Günden Eski Kullanılmayan Access Key'ler ==="
# Tüm IAM kullanıcılarını listele
aws iam list-users --query 'Users[*].UserName' --output text | tr 't' 'n' | while read USERNAME; do
# Her kullanıcının key'lerini kontrol et
aws iam list-access-keys --user-name "$USERNAME"
--query 'AccessKeyMetadata[*].[AccessKeyId,Status,CreateDate]'
--output text | while read KEY_ID STATUS CREATE_DATE; do
# Oluşturma tarihini epoch'a çevir
CREATE_EPOCH=$(date -d "$CREATE_DATE" +%s 2>/dev/null || date -j -f "%Y-%m-%dT%H:%M:%S+00:00" "$CREATE_DATE" +%s 2>/dev/null)
AGE_DAYS=$(( (TODAY - CREATE_EPOCH) / 86400 ))
# Son kullanım tarihini al
LAST_USED=$(aws iam get-access-key-last-used
--access-key-id "$KEY_ID"
--query 'AccessKeyLastUsed.LastUsedDate'
--output text 2>/dev/null)
if [ "$AGE_DAYS" -gt "$THRESHOLD_DAYS" ] && [ "$STATUS" = "Active" ]; then
echo "Kullanici: $USERNAME | Key: $KEY_ID | Yas: ${AGE_DAYS} gun | Son Kullanim: $LAST_USED"
fi
done
done
Key Rotation (Key Döndürme) Stratejisi
Key rotation, güvenlik hijyeninin temel taşlarından biridir. Her 90 günde bir key’leri döndürmeniz öneriliyor. Peki bunu kesinti yaratmadan nasıl yaparsınız?
Zero-Downtime Key Rotation Yaklaşımı
#!/bin/bash
# rotate_key.sh - Kesintisiz key rotation scripti
# Kullanim: ./rotate_key.sh <username>
USERNAME=$1
if [ -z "$USERNAME" ]; then
echo "Kullanim: $0 <iam-username>"
exit 1
fi
echo "[1] Yeni access key olusturuluyor: $USERNAME"
NEW_KEY_OUTPUT=$(aws iam create-access-key --user-name "$USERNAME" --output json)
NEW_ACCESS_KEY=$(echo "$NEW_KEY_OUTPUT" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d['AccessKey']['AccessKeyId'])")
NEW_SECRET_KEY=$(echo "$NEW_KEY_OUTPUT" | python3 -c "import sys, json; d=json.load(sys.stdin); print(d['AccessKey']['SecretAccessKey'])")
echo "[2] Yeni Key ID: $NEW_ACCESS_KEY"
echo "[3] Yeni Secret Key: $NEW_SECRET_KEY"
echo ""
echo "ONEMLI: Bu secret key'i guvenli bir yere kaydedin!"
echo "Uygulamanizi yeni key ile yapilandirin, sonra eski key'i deaktive edin."
echo ""
# Mevcut key'leri listele
echo "[4] Mevcut key'ler:"
aws iam list-access-keys --user-name "$USERNAME"
--query 'AccessKeyMetadata[*].[AccessKeyId,Status]'
--output table
echo ""
echo "Eski key'i deaktive etmek icin:"
echo "aws iam update-access-key --user-name $USERNAME --access-key-id <ESKI_KEY_ID> --status Inactive"
echo ""
echo "Eski key'i silmek icin:"
echo "aws iam delete-access-key --user-name $USERNAME --access-key-id <ESKI_KEY_ID>"
Rotation sürecinde dikkat edilmesi gereken adımlar:
- Önce yeni key oluşturun: AWS kullanıcı başına 2 key’e izin verir, bu window’u kullanın
- Uygulamayı yeni key ile güncelleyin: Tüm sistemlerin yeni key’i kullandığından emin olun
- Eski key’i önce deaktive edin, silmeyin: Bir şeyler ters giderse geri dönebilirsiniz
- Birkaç gün bekleyin: Her şeyin çalıştığını doğrulayın
- Sonra silin: Eski key’i kalıcı olarak kaldırın
AWS Secrets Manager ile Key Yönetimi
Access key’leri düz metin olarak config dosyalarında saklamak bir felaket reçetesidir. AWS Secrets Manager veya Parameter Store kullanarak bu key’leri merkezi, şifreli bir yerde tutabilirsiniz.
# Secret oluştur
aws secretsmanager create-secret
--name "prod/myapp/aws-credentials"
--description "MyApp Production AWS Credentials"
--secret-string '{
"access_key_id": "AKIAIOSFODNN7EXAMPLE",
"secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}'
# Secret'i oku
aws secretsmanager get-secret-value
--secret-id "prod/myapp/aws-credentials"
--query 'SecretString'
--output text | python3 -c "import sys, json; d=json.load(sys.stdin); print(d['access_key_id'])"
# Rotation ayarla (30 gunde bir otomatik rotation)
aws secretsmanager rotate-secret
--secret-id "prod/myapp/aws-credentials"
--rotation-rules AutomaticallyAfterDays=30
Uygulamanızda bu secret’i kullanmak için örnek Python kodu:
# Python ile secret okuma - bash'ten cagirabilirsiniz
python3 << 'EOF'
import boto3
import json
def get_aws_credentials(secret_name):
client = boto3.client('secretsmanager', region_name='eu-west-1')
try:
response = client.get_secret_value(SecretId=secret_name)
secret = json.loads(response['SecretString'])
return secret['access_key_id'], secret['secret_access_key']
except Exception as e:
print(f"Hata: {e}")
raise
access_key, secret_key = get_aws_credentials('prod/myapp/aws-credentials')
print(f"Access Key: {access_key[:8]}...") # Guvenlik icin tam key'i basma
EOF
CloudTrail ile Key Kullanımını İzleme
Hangi key ne yapıyor? Bunu bilmeden güvenlik durumunuzu değerlendiremezsiniz. CloudTrail her API çağrısını loglar.
# Belirli bir access key'in son 7 gundeki aktivitelerini sorgula
aws cloudtrail lookup-events
--lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAIOSFODNN7EXAMPLE
--start-time $(date -d '7 days ago' --iso-8601=seconds)
--max-results 50
--query 'Events[*].[EventTime,EventName,SourceIPAddress,Username]'
--output table
# Sadece hata veren API cagrilarini bul
aws logs filter-log-events
--log-group-name "CloudTrail/DefaultLogGroup"
--filter-pattern '{ $.errorCode = "AccessDenied" }'
--start-time $(date -d '1 day ago' +%s000)
--query 'events[*].message'
--output text | python3 -c "
import sys, json
for line in sys.stdin:
try:
event = json.loads(line.strip())
print(f"{event.get('eventTime')} | {event.get('userIdentity',{}).get('accessKeyId','N/A')} | {event.get('eventName')} | {event.get('sourceIPAddress')}")
except:
pass
"
AWS Config ile Otomatik Uyumluluk Kontrolü
AWS Config, hesabınızdaki kaynakları sürekli izler ve belirlediğiniz kurallara uygunluğu denetler. IAM key güvenliği için hazır kurallar mevcut:
# IAM access key rotation kuralini aktif et
aws configservice put-config-rule
--config-rule '{
"ConfigRuleName": "access-keys-rotated",
"Description": "90 gunden eski access keyleri tespit eder",
"Source": {
"Owner": "AWS",
"SourceIdentifier": "ACCESS_KEYS_ROTATED"
},
"InputParameters": "{"maxAccessKeyAge": "90"}",
"ConfigRuleState": "ACTIVE"
}'
# Mevcut uyumluluk durumunu kontrol et
aws configservice describe-compliance-by-config-rule
--config-rule-names access-keys-rotated
--query 'ComplianceByConfigRules[*].[ConfigRuleName,Compliance.ComplianceType]'
--output table
# Uyumsuz kaynakları listele
aws configservice get-compliance-details-by-config-rule
--config-rule-name access-keys-rotated
--compliance-types NON_COMPLIANT
--query 'EvaluationResults[*].[EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,ComplianceType]'
--output table
Gerçek Dünya Senaryosu: Sızdırılmış Key Müdahalesi
Diyelim ki bir geliştirici yanlışlıkla access key’i GitHub’a push etti. Ne yapacaksınız? Sakin olun, ama hızlı hareket edin.
#!/bin/bash
# emergency_key_disable.sh
# Sızdırılan key'i hemen deaktive et
COMPROMISED_KEY_ID="AKIAIOSFODNN7EXAMPLE"
USERNAME="developer-john"
echo "[ACIL] Sızdırılan key deaktive ediliyor..."
# Key'i hemen deaktive et
aws iam update-access-key
--user-name "$USERNAME"
--access-key-id "$COMPROMISED_KEY_ID"
--status Inactive
echo "[1] Key deaktive edildi: $COMPROMISED_KEY_ID"
# Son saatteki aktiviteyi kontrol et
echo "[2] Son 1 saatteki aktivite kontrol ediliyor..."
aws cloudtrail lookup-events
--lookup-attributes AttributeKey=AccessKeyId,AttributeValue="$COMPROMISED_KEY_ID"
--start-time $(date -d '1 hour ago' --iso-8601=seconds)
--query 'Events[*].[EventTime,EventName,SourceIPAddress]'
--output table
# Hangi kaynaklar etkilenmiş olabilir?
echo "[3] Son API cagriları inceleniyor..."
aws cloudtrail lookup-events
--lookup-attributes AttributeKey=AccessKeyId,AttributeValue="$COMPROMISED_KEY_ID"
--start-time $(date -d '24 hours ago' --iso-8601=seconds)
--query 'Events[*].EventName'
--output text | sort | uniq -c | sort -rn | head -20
echo ""
echo "Sonraki adimlar:"
echo " 1. Key'i tamamen silin"
echo " 2. Bu key ile yapilan tum islemleri inceleyin"
echo " 3. Yeni IAM kullanicilari veya roller olusturulduysa hemen silin"
echo " 4. S3 bucket'larinda public erişim değişikliği olup olmadığını kontrol edin"
echo " 5. Beklenmedik EC2 instance'ları veya Lambda fonksiyonlarını kontrol edin"
echo " 6. Billing anomalilerini kontrol edin"
Bu senaryoda şu adımları hızla tamamlamanız gerekir:
- Key’i hemen deaktive edin: Silmeyin, önce deaktive edin, inceleme için ihtiyacınız olabilir
- CloudTrail’i inceleyin: Ne yapıldığını anlayın, yeni kullanıcı veya role oluşturulmuş mu?
- Billing alarmlarını kontrol edin: Crypto mining saldırısı başlamış olabilir
- Beklenmedik kaynakları arayın: Tüm region’larda EC2, Lambda, RDS kontrol edin
- Güvenlik ekibini haberdar edin: Bu bir güvenlik olayıdır, kayıt altına alınmalı
IAM Policy ile Key Kullanımını Kısıtlama
Key’e ek güvenlik katmanı eklemek için policy koşulları kullanabilirsiniz. Örneğin bir key’i yalnızca belirli IP adreslerinden kullanılacak şekilde kısıtlayabilirsiniz:
# IP kisitlamali policy olustur
aws iam put-user-policy
--user-name "api-service-user"
--policy-name "IPRestrictedAccess"
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"203.0.113.0/24",
"198.51.100.50/32"
]
}
}
},
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"203.0.113.0/24",
"198.51.100.50/32"
]
}
}
}
]
}'
Güvenlik Kontrol Listesi
Her ay yapmanız gereken kontroller:
- Credential report çekin: Kullanılmayan ve eski key’leri tespit edin
- 90 günden eski key’leri rotate edin: Otomatize etmek için Lambda kullanın
- Root account key’inin olmadığını doğrulayın: Bu kritik
- MFA durumunu kontrol edin: Key’lere ek olarak MFA zorunlu kılın
- Kullanılmayan IAM kullanıcılarını silin: Off-boarding sürecinizi gözden geçirin
- CloudTrail loglarını inceleyin: Anomali var mı bakın
- AWS Trusted Advisor önerilerini inceleyin: IAM bölümüne özellikle dikkat edin
Sürekli olarak yapmanız gerekenler:
- Billing alarmları kurun: Beklenmedik maliyet artışı erken uyarı sistemidir
- GuardDuty aktif tutun: Anomalileri otomatik tespit eder
- Access Analyzer kullanın: Dışarıya açık izinleri bulur
Sonuç
IAM access key yönetimi, “bir kez yapılır ve unutulur” türünden bir iş değil. Sürekli dikkat, düzenli denetim ve otomatize edilmiş süreçler gerektiriyor. Bu yazıda ele aldığımız konuları özetleyecek olursam:
En önemli üç kural şunlar. Root account key’i kullanmayın, bu konuda taviz yok. Key’leri düzenli rotate edin, 90 gün makul bir süre ama sektörünüze göre daha kısa tutabilirsiniz. Mümkün olan her yerde IAM role kullanın, uzun ömürlü credential’lardan kaçının.
Bunların ötesinde, CloudTrail ve GuardDuty gibi izleme araçlarına mutlaka yatırım yapın. Bir güvenlik ihlali yaşandığında ne kadar hızlı tespit ettiğiniz, hasarın büyüklüğünü doğrudan etkiliyor. Sızdırılmış bir key’i birkaç dakika içinde fark etmek ile birkaç gün sonra fatura gelince fark etmek arasında büyük fark var.
Son olarak şunu söyleyeyim: En iyi güvenlik, kullanışlılıkla dengeli olan güvenliktir. Çok katı kurallar, geliştiricilerin güvenlik protokollerini bypass etmesine neden olur. Kolayı güvenli, güvensizi zor yapın. İşte o zaman güvenlik kültürü gerçekten yerleşiyor.
