AWS CloudFront ile SSL/TLS Sertifika Entegrasyonu

Web sitenizin HTTPS üzerinden güvenli bir şekilde sunulması artık bir tercih değil, zorunluluk. Google sıralama faktörü olarak SSL’i kullanıyor, tarayıcılar HTTP sitelerini “Güvenli Değil” diye işaretliyor ve kullanıcılar da bilinçleniyor. CloudFront kullanıyorsanız bu işi doğru yapmak hem performans hem güvenlik açısından kritik. Gelin bu entegrasyonu baştan sona, gerçek dünya senaryolarıyla birlikte ele alalım.

CloudFront ve SSL/TLS Temelleri

CloudFront, Amazon’un global CDN hizmetidir. Edge location’lardan içerik dağıtırken SSL/TLS terminasyonu da bu edge noktalarda gerçekleşir. Yani kullanıcıdan gelen şifreli bağlantı CloudFront’ta sonlanır, CloudFront da origin sunucunuzla ayrı bir bağlantı kurar.

Bu mimaride iki farklı SSL bağlantısı vardır:

  • Viewer-CloudFront arası: Kullanıcının tarayıcısı ile CloudFront edge arasındaki bağlantı
  • CloudFront-Origin arası: CloudFront ile sizin origin sunucunuz (S3, EC2, ALB vs.) arasındaki bağlantı

Her iki segmenti de ayrı ayrı yapılandırmanız gerekiyor. Çoğu sysadmin sadece viewer tarafını ayarlayıp origin bağlantısını HTTP bırakıyor, bu büyük bir güvenlik açığı.

Sertifika Türleri ve Kısıtlamalar

CloudFront için sertifika kullanırken bilmeniz gereken kritik bir kısıtlama var: ACM (AWS Certificate Manager) üzerinden CloudFront’a ekleyeceğiniz sertifikanın mutlaka us-east-1 (N. Virginia) bölgesinde oluşturulması gerekiyor. Diğer bölgelerde oluşturulan sertifikalar CloudFront’ta görünmüyor, bu konuda çok sık soru geliyor.

Sertifika seçenekleriniz:

  • AWS Certificate Manager (ACM): Ücretsiz, otomatik yenileme, AWS ile entegre
  • Üçüncü parti sertifika: Wildcard, EV sertifikaları için, IAM’e yüklemeniz gerekiyor
  • Self-signed: Sadece CloudFront-Origin arası için, production’da viewer tarafında kullanmayın

ACM ile Sertifika Oluşturma

En yaygın ve önerilen yöntemden başlayalım. AWS CLI ile us-east-1’de sertifika isteği oluşturalım:

# us-east-1 bölgesinde sertifika isteği oluştur
aws acm request-certificate 
  --domain-name "example.com" 
  --subject-alternative-names "*.example.com" "www.example.com" 
  --validation-method DNS 
  --region us-east-1 
  --tags Key=Environment,Value=Production Key=Project,Value=WebApp

# Oluşturulan sertifikanın ARN'ini ve doğrulama bilgilerini al
aws acm describe-certificate 
  --certificate-arn "arn:aws:acm:us-east-1:123456789012:certificate/abc-123" 
  --region us-east-1 
  --query "Certificate.DomainValidationOptions"

DNS doğrulama tercih edin çünkü e-posta doğrulama hem zahmetli hem de bazı durumlarda e-postalar gelmiyor. DNS doğrulaması için ACM size bir CNAME kaydı verecek, bunu domain’inizin DNS yönetim panelinde oluşturmanız gerekiyor.

Route53 kullanıyorsanız bunu otomatik yapabilirsiniz:

# Route53 hosted zone ID'sini bul
ZONE_ID=$(aws route53 list-hosted-zones-by-name 
  --dns-name "example.com" 
  --query "HostedZones[0].Id" 
  --output text | cut -d'/' -f3)

# ACM'den doğrulama CNAME bilgilerini çek
CERT_ARN="arn:aws:acm:us-east-1:123456789012:certificate/abc-123"

# Doğrulama kaydını Route53'e ekle (ACM konsolundan da yapabilirsiniz)
aws acm describe-certificate 
  --certificate-arn $CERT_ARN 
  --region us-east-1 
  --query "Certificate.DomainValidationOptions[0].ResourceRecord"

Sertifika durumunu takip edin, DNS propagasyonu 5-30 dakika sürebilir:

# Sertifika durumunu izle
watch -n 30 "aws acm describe-certificate 
  --certificate-arn $CERT_ARN 
  --region us-east-1 
  --query 'Certificate.Status' 
  --output text"

“ISSUED” durumunu gördüğünüzde sertifikanız hazır demektir.

CloudFront Distribution Oluşturma

Sertifikanız hazırsa CloudFront distribution’ı yapılandırma zamanı. Önce bir JSON konfigürasyon dosyası oluşturalım:

cat > cloudfront-config.json << 'EOF'
{
  "CallerReference": "my-distribution-2024",
  "Aliases": {
    "Quantity": 2,
    "Items": ["example.com", "www.example.com"]
  },
  "DefaultRootObject": "index.html",
  "Origins": {
    "Quantity": 1,
    "Items": [
      {
        "Id": "S3-example-bucket",
        "DomainName": "example-bucket.s3.amazonaws.com",
        "S3OriginConfig": {
          "OriginAccessIdentity": ""
        }
      }
    ]
  },
  "DefaultCacheBehavior": {
    "TargetOriginId": "S3-example-bucket",
    "ViewerProtocolPolicy": "redirect-to-https",
    "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6",
    "AllowedMethods": {
      "Quantity": 2,
      "Items": ["GET", "HEAD"]
    }
  },
  "ViewerCertificate": {
    "ACMCertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
    "SSLSupportMethod": "sni-only",
    "MinimumProtocolVersion": "TLSv1.2_2021"
  },
  "Enabled": true,
  "HttpVersion": "http2and3",
  "IsIPV6Enabled": true
}
EOF

# Distribution'ı oluştur
aws cloudfront create-distribution 
  --distribution-config file://cloudfront-config.json

Burada dikkat edilmesi gereken birkaç nokta var:

  • ViewerProtocolPolicy: redirect-to-https kullanın, allow-all asla production’da kullanmayın
  • SSLSupportMethod: sni-only seçin, vip çok pahalı ve artık gerekli değil
  • MinimumProtocolVersion: En az TLSv1.2_2021 kullanın, TLS 1.0 ve 1.1 güvensiz

Mevcut Distribution’a Sertifika Ekleme

Genellikle yeni distribution oluşturmak yerine mevcut birine sertifika eklemeniz gerekir. Bu senaryo için önce mevcut konfigürasyonu çekin:

# Distribution ID'nizi bulun
DIST_ID="E1234567890ABC"

# Mevcut konfigürasyonu ve ETag'i çek
aws cloudfront get-distribution-config 
  --id $DIST_ID 
  --output json > current-config.json

# ETag değerini sakla (update için gerekli)
ETAG=$(aws cloudfront get-distribution-config 
  --id $DIST_ID 
  --query "ETag" 
  --output text)

echo "ETag: $ETAG"

# DistributionConfig kısmını ayır
cat current-config.json | python3 -c "
import json, sys
data = json.load(sys.stdin)
print(json.dumps(data['DistributionConfig'], indent=2))
" > dist-config-only.json

# ViewerCertificate bölümünü güncelle
python3 << 'PYTHON'
import json

with open('dist-config-only.json', 'r') as f:
    config = json.load(f)

config['ViewerCertificate'] = {
    'ACMCertificateArn': 'arn:aws:acm:us-east-1:123456789012:certificate/abc-123',
    'SSLSupportMethod': 'sni-only',
    'MinimumProtocolVersion': 'TLSv1.2_2021'
}

# Alias ekle
config['Aliases'] = {
    'Quantity': 1,
    'Items': ['example.com']
}

with open('updated-config.json', 'w') as f:
    json.dump(config, f, indent=2)

print("Konfigürasyon güncellendi")
PYTHON

# Distribution'ı güncelle
aws cloudfront update-distribution 
  --id $DIST_ID 
  --distribution-config file://updated-config.json 
  --if-match $ETAG

Origin SSL/TLS Yapılandırması

Viewer tarafını hallettik, şimdi CloudFront-Origin arası güvenliği sağlayalım. Origin’iniz ALB ise:

# Origin'i HTTPS olarak yapılandır
cat > origin-update.json << 'EOF'
{
  "Origins": {
    "Quantity": 1,
    "Items": [
      {
        "Id": "ALB-origin",
        "DomainName": "my-alb-123.us-east-1.elb.amazonaws.com",
        "CustomOriginConfig": {
          "HTTPPort": 80,
          "HTTPSPort": 443,
          "OriginProtocolPolicy": "https-only",
          "OriginSSLProtocols": {
            "Quantity": 1,
            "Items": ["TLSv1.2"]
          },
          "OriginReadTimeout": 30,
          "OriginKeepaliveTimeout": 5
        },
        "OriginShieldEnabled": true,
        "OriginShieldRegion": "eu-west-1"
      }
    ]
  }
}
EOF

OriginProtocolPolicy için seçenekler:

  • http-only: CloudFront origin’e HTTP ile bağlanır, güvensiz
  • https-only: Her zaman HTTPS, önerilen
  • match-viewer: Viewer ne kullanıyorsa onu kullanır, HTTPS redirect açıksa sorun olmaz ama yine de https-only tercih edin

Güvenlik Politikası Sıkılaştırma

Modern bir güvenlik duruşu için TLS versiyonu ve cipher suite’leri kontrol etmeniz gerekiyor. CloudFront’ta kullanabileceğiniz güvenlik politikaları:

  • TLSv1.2_2021: TLS 1.2 ve 1.3, modern cipher’lar, önerilen
  • TLSv1.2_2019: TLS 1.2 ve 1.3, biraz daha geniş cipher listesi
  • TLSv1: Eski, kullanmayın
  • SSLv3: Hiç kullanmayın, CVE dolup taşıyor

Mevcut distribution’ın güvenlik politikasını kontrol edin:

# Güvenlik politikasını kontrol et
aws cloudfront get-distribution 
  --id $DIST_ID 
  --query "Distribution.DistributionConfig.ViewerCertificate.MinimumProtocolVersion" 
  --output text

# SSL/TLS yapılandırmasını detaylı gör
aws cloudfront get-distribution 
  --id $DIST_ID 
  --query "Distribution.DistributionConfig.ViewerCertificate" 
  --output json

Eğer eski bir TLS versiyonu görüyorsanız hemen güncelleyin. TLS 1.0 kullanan kullanıcı sayısı artık ihmal edilebilir düzeyde, geriye uyumluluk için güvenlikten taviz vermek mantıklı değil.

HTTP’den HTTPS’e Yönlendirme

CloudFront seviyesinde yönlendirme yapabilirsiniz ama bazen daha granüler kontrol gerekiyor. CloudFront Functions kullanarak:

# HTTP to HTTPS redirect için CloudFront Function oluştur
cat > redirect-function.js << 'EOF'
function handler(event) {
    var request = event.request;
    var headers = request.headers;
    
    // X-Forwarded-Proto header kontrolü
    if (headers['x-forwarded-proto'] && 
        headers['x-forwarded-proto'].value === 'http') {
        
        var response = {
            statusCode: 301,
            statusDescription: 'Moved Permanently',
            headers: {
                'location': { 
                    value: 'https://' + headers.host.value + request.uri 
                },
                'strict-transport-security': {
                    value: 'max-age=31536000; includeSubDomains; preload'
                }
            }
        };
        return response;
    }
    
    // HSTS header ekle
    if (!request.headers['strict-transport-security']) {
        request.headers['strict-transport-security'] = {
            value: 'max-age=31536000; includeSubDomains; preload'
        };
    }
    
    return request;
}
EOF

# Fonksiyonu AWS'e yükle
aws cloudfront create-function 
  --name "HTTPSRedirect" 
  --function-config Comment="HTTP to HTTPS redirect with HSTS",Runtime=cloudfront-js-1.0 
  --function-code fileb://redirect-function.js 
  --region us-east-1

# Fonksiyonu yayınla
aws cloudfront publish-function 
  --name "HTTPSRedirect" 
  --if-match $(aws cloudfront describe-function 
    --name "HTTPSRedirect" 
    --query "ETag" 
    --output text)

Sertifika Yenileme ve Monitoring

ACM sertifikaları otomatik yenileniyor ama bunu doğrulamanız ve sorun çıkarsa haberdar olmanız gerekiyor. CloudWatch alarm oluşturalım:

# Sertifika son kullanma tarihi alarmı
aws cloudwatch put-metric-alarm 
  --alarm-name "ACM-Certificate-Expiry-Warning" 
  --alarm-description "SSL sertifikasi 30 gun icinde sona eriyor" 
  --metric-name DaysToExpiry 
  --namespace AWS/CertificateManager 
  --statistic Minimum 
  --period 86400 
  --threshold 30 
  --comparison-operator LessThanThreshold 
  --dimensions Name=CertificateArn,Value="arn:aws:acm:us-east-1:123456789012:certificate/abc-123" 
  --evaluation-periods 1 
  --alarm-actions "arn:aws:sns:us-east-1:123456789012:ssl-alerts" 
  --treat-missing-data breaching

# Tüm sertifika durumlarını listele ve son kullanma tarihlerini kontrol et
aws acm list-certificates 
  --region us-east-1 
  --query "CertificateSummaryList[*].{Domain:DomainName,ARN:CertificateArn}" 
  --output table

# Detaylı sertifika bilgisi
for cert_arn in $(aws acm list-certificates 
  --region us-east-1 
  --query "CertificateSummaryList[*].CertificateArn" 
  --output text); do
  echo "=== $cert_arn ==="
  aws acm describe-certificate 
    --certificate-arn $cert_arn 
    --region us-east-1 
    --query "Certificate.{Status:Status,NotAfter:NotAfter,Domain:DomainName}" 
    --output json
done

Üçüncü Parti Sertifika Yükleme

Bazen EV (Extended Validation) sertifika veya özel CA’dan sertifika kullanmanız gerekiyor. Bu durumda IAM’e yükleme yapmanız gerekiyor (CloudFront için IAM’i kullanmak zorundayız, ACM değil):

# Sertifika, private key ve chain'i hazırla
# Dosyalarınızın hazır olduğunu varsayıyoruz:
# - certificate.crt (sertifika)
# - private.key (özel anahtar)
# - chain.crt (ara sertifika zinciri)

# IAM'e sertifikayı yükle
aws iam upload-server-certificate 
  --server-certificate-name "example-com-2024" 
  --certificate-body file://certificate.crt 
  --private-key file://private.key 
  --certificate-chain file://chain.crt 
  --path "/cloudfront/"

# Yüklenen sertifikanın ARN'ini al
aws iam list-server-certificates 
  --path-prefix "/cloudfront/" 
  --query "ServerCertificateMetadataList[*].{Name:ServerCertificateName,ARN:Arn,Expiry:Expiration}" 
  --output json

# Sertifikayı CloudFront'ta kullanmak için ViewerCertificate
# IAMCertificateId kullanılır, ACMCertificateArn değil

IAM’deki sertifika için CloudFront konfigürasyonu şöyle olur:

# IAM sertifikası ile CloudFront yapılandırması
CERT_ID=$(aws iam list-server-certificates 
  --path-prefix "/cloudfront/" 
  --query "ServerCertificateMetadataList[?ServerCertificateName=='example-com-2024'].ServerCertificateId" 
  --output text)

# Bu ID'yi ViewerCertificate.IAMCertificateId olarak kullanın
echo "IAM Certificate ID: $CERT_ID"

Gerçek Dünya Senaryosu: Wildcard Sertifika ile Multi-tenant CDN

Birden fazla subdomain’i tek CloudFront distribution ile yönetmek yaygın bir senaryo. Diyelim ki *.app.example.com şeklinde subdomain’leriniz var:

# Wildcard sertifika iste
aws acm request-certificate 
  --domain-name "*.app.example.com" 
  --subject-alternative-names "app.example.com" 
  --validation-method DNS 
  --region us-east-1

# Distribution'da birden fazla alias tanımla
python3 << 'PYTHON'
import boto3
import json

cf = boto3.client('cloudfront', region_name='us-east-1')

dist_id = "E1234567890ABC"
response = cf.get_distribution_config(Id=dist_id)
etag = response['ETag']
config = response['DistributionConfig']

# Alias listesini güncelle
subdomains = ['tenant1.app.example.com', 'tenant2.app.example.com', 
              'tenant3.app.example.com', 'app.example.com']

config['Aliases'] = {
    'Quantity': len(subdomains),
    'Items': subdomains
}

# Güncelle
cf.update_distribution(
    Id=dist_id,
    DistributionConfig=config,
    IfMatch=etag
)

print(f"Distribution güncellendi, {len(subdomains)} alias eklendi")
PYTHON

SSL Konfigürasyonunu Test Etme

Yaptığınız değişikliklerin doğru çalışıp çalışmadığını doğrulayın:

# SSL Labs benzeri temel test
curl -vI https://example.com 2>&1 | grep -E "SSL|TLS|certificate|issuer|expire"

# TLS versiyonunu test et
openssl s_client -connect example.com:443 -tls1_2 -servername example.com < /dev/null 2>&1 | 
  grep -E "Protocol|Cipher|subject|issuer|notAfter"

# TLS 1.0 ve 1.1 reddedilmeli
openssl s_client -connect example.com:443 -tls1 -servername example.com < /dev/null 2>&1 | 
  grep -E "handshake|error|alert"

# Certificate chain kontrolü
openssl s_client -connect example.com:443 -servername example.com -showcerts < /dev/null 2>&1 | 
  grep -E "subject|issuer|notBefore|notAfter"

# HSTS header kontrolü
curl -sI https://example.com | grep -i "strict-transport-security"

# HTTP'nin HTTPS'e yönlenip yönlenmediğini test et
curl -sI http://example.com | grep -E "301|302|location"

CloudFront’un kendi edge’inden test etmek için:

# CloudFront edge'ini bypass ederek origin'i test et
curl -vI https://example.com 
  -H "X-Forwarded-For: 8.8.8.8" 
  -H "Cache-Control: no-cache" 
  --resolve "example.com:443:$(dig +short example.com | head -1)"

# CloudFront response headers kontrolü
curl -sI https://example.com | grep -E "x-cache|x-amz|via|server"

Yaygın Sorunlar ve Çözümleri

Sertifika entegrasyonunda sık karşılaşılan sorunlar:

  • “Certificate not found” hatası: Sertifikanızın us-east-1’de olduğunu doğrulayın. Başka bölgede açılmış sertifikalar CloudFront’ta görünmez.
  • “CNAMEAlreadyExists” hatası: Alias olarak eklemeye çalıştığınız domain başka bir distribution’da zaten kayıtlı. aws cloudfront list-distributions ile tüm distribution’ları kontrol edin.
  • “Alias validation failed”: Domain’in sertifikada tanımlı olmadığı anlamına gelir. Sertifikanın Subject Alternative Names listesini kontrol edin.
  • Origin SSL handshake hatası: Origin’inizdeki sertifikanın geçerli, CA-signed olduğundan emin olun. Self-signed kullanıyorsanız CloudFront origin SSL verification’ı devre dışı bırakmanız gerekir, ama bu production için önerilmez.
  • ACM otomatik yenileme başarısız: DNS validation kayıtlarının hala mevcut olduğundan emin olun. Route53 kullanıyorsanız bu kayıtlar otomatik korunur, farklı bir DNS sağlayıcı kullanıyorsanız CNAME kayıtlarını silmemiş olmanız gerekiyor.

Sonuç

CloudFront ile SSL/TLS entegrasyonu, doğru yapılandırıldığında hem performanslı hem de güvenli bir CDN altyapısı oluşturmanızı sağlıyor. Özetleyecek olursak:

  • ACM sertifikalarını her zaman us-east-1 bölgesinde oluşturun
  • Viewer tarafında minimum TLSv1.2_2021 politikasını kullanın
  • Origin bağlantısını da HTTPS ile güvence altına alın, sadece viewer tarafıyla yetinmeyin
  • HTTP’yi HTTPS’e yönlendirin ve HSTS header’ı ekleyin
  • CloudWatch ile sertifika son kullanma tarihini izleyin
  • Değişikliklerinizi openssl ve curl ile doğrulayın

Bu yapıyı bir kez doğru kurduğunuzda ACM’in otomatik yenileme özelliği sayesinde sertifika yönetimi neredeyse sıfır bakım gerektiriyor. Yalnızca üçüncü parti sertifika kullanıyorsanız yenileme sürecini takviminize kaydedin, çünkü IAM’deki sertifikalar otomatik yenilenmiyor ve site güvensiz hale gelmeden müdahale etmeniz gerekiyor.

Bir yanıt yazın

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