Bulut Ortamında Sıfır Güven (Zero Trust) Mimarisi

Geçen ay bir müşterimizin AWS ortamında yaşanan veri sızıntısını incelerken fark ettim ki sorun teknik değil, zihinseldi. Ekip “biz zaten firewall arkasındayız” diye düşünüyordu. Bulut ortamında bu düşünce tarzı sizi mahveder. Çünkü bulutta “içeri” ve “dışarı” kavramları artık eskisi gibi çalışmıyor. İşte tam bu noktada Sıfır Güven (Zero Trust) mimarisi devreye giriyor: kimseye güvenme, her şeyi doğrula.

Sıfır Güven Nedir ve Neden Bulut İçin Kritik?

Geleneksel güvenlik modeli bir kale-hendek (castle-and-moat) anlayışına dayanır. Dışarısı tehlikeli, içerisi güvenli. VPN bağlandınız mı? Artık “güvenli ağdasınız”. Bu model on yıl önce işe yarıyordu çünkü tüm kaynaklar şirket datacenterındaydı.

Bulut ortamında bu model çöküyor. Servisleriniz AWS, Azure, GCP üzerinde dağılmış durumda. Çalışanlarınız ev, kafe, otel üzerinden bağlanıyor. Uygulamalarınız birbirleriyle API üzerinden konuşuyor. “İçeri” diye bir kavram kalmadı.

Sıfır Güvenin temel prensipleri:

  • Hiçbir şeye varsayılan olarak güvenme: Ağ içinden gelen trafik bile doğrulanmalı
  • Her zaman doğrula: Kullanıcı, cihaz, uygulama, konum… hepsi sürekli doğrulama altında
  • En az yetki prensibi: Sadece ihtiyaç duyulan kaynaklara, sadece ihtiyaç duyulan süre boyunca erişim
  • Ihlal varsay: Sistem zaten ele geçirilmiş gibi davran, buna göre tasarla
  • Mikro-segmentasyon: Ağı küçük parçalara böl, yanal hareketi (lateral movement) engelle

Kimlik Merkezli Güvenlik: IAM’ı Doğru Kullanmak

Bulut ortamında kimlik, yeni çevre (perimeter) oldu. AWS IAM, Azure AD veya GCP IAM doğru yapılandırılmazsa Zero Trust’un temeli çürük olur.

# AWS CLI ile mevcut IAM policy'leri audit etme
# Fazla geniş policy olan kullanıcıları tespit et
aws iam get-account-authorization-details 
  --filter User 
  --query 'UserDetailList[?contains(AttachedManagedPolicies[].PolicyName, `AdministratorAccess`)].UserName' 
  --output text

# Kullanılmayan access key'leri bul (90 günden eski)
aws iam generate-credential-report
aws iam get-credential-report --query 'Content' --output text | base64 -d | 
  awk -F',' 'NR>1 && $9=="true" && $11!="N/A" {print $1, $11}'
# Servis hesapları için minimum yetki policy örneği
# Sadece belirli S3 bucket'a read-only erişim
cat <<EOF > minimal-s3-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::uygulama-veri-bucket",
        "arn:aws:s3:::uygulama-veri-bucket/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "eu-west-1"
        },
        "IpAddress": {
          "aws:SourceIp": ["10.0.0.0/8"]
        }
      }
    }
  ]
}
EOF

aws iam create-policy 
  --policy-name MinimalS3ReadPolicy 
  --policy-document file://minimal-s3-policy.json

Burada dikkat edin: policy’ye Condition bloğu ekledik. Sadece belirli region’dan ve belirli IP bloğundan gelen istekler kabul ediliyor. Bu Zero Trust’un “her zaman doğrula” prensibinin pratik yansıması.

Çok Faktörlü Doğrulama ve Dinamik Erişim Kontrolü

MFA artık opsiyonel değil, zorunlu. Ama daha da ileri gidip koşullu erişim (conditional access) politikaları uygulamak gerekiyor.

# Azure AD Conditional Access policy'yi PowerShell ile audit etme
# Hangi kullanıcılar MFA'dan muaf tutuluyor?
Connect-AzureAD
Get-AzureADMSConditionalAccessPolicy | Where-Object {
  $_.Conditions.Users.ExcludeUsers -ne $null
} | Select-Object DisplayName, Id, @{
  Name="ExcludedUsers"
  Expression={$_.Conditions.Users.ExcludeUsers -join ", "}
}
# AWS'de SCP (Service Control Policy) ile MFA zorunluluğu
# Bu policy MFA olmadan tüm işlemleri bloklar
cat <<EOF > require-mfa-scp.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyWithoutMFA",
      "Effect": "Deny",
      "NotAction": [
        "iam:CreateVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:GetUser",
        "iam:ListMFADevices",
        "iam:ListVirtualMFADevices",
        "iam:ResyncMFADevice",
        "sts:GetSessionToken"
      ],
      "Resource": "*",
      "Condition": {
        "BoolIfExists": {
          "aws:MultiFactorAuthPresent": "false"
        }
      }
    }
  ]
}
EOF

Gerçek dünya senaryosu: Bir fintech müşterimde DevOps ekibi “MFA çok zaman alıyor, CI/CD pipeline’ı bozuyor” diye direnç gösterdi. Çözüm şu oldu: insan kullanıcılar için MFA zorunlu, pipeline’lar için OIDC tabanlı kısa ömürlü token’lar. Böylece servis hesaplarında uzun ömürlü access key kullanımını tamamen ortadan kaldırdık.

Ağ Mikro-Segmentasyonu

Sıfır Güven’in en can alıcı kısmı mikro-segmentasyon. Bir saldırgan sisteme girdiğinde lateral movement yapamamalı. AWS’de bu VPC, Security Group ve Network ACL kombinasyonuyla sağlanır.

# Mevcut Security Group kurallarını audit et
# 0.0.0.0/0'a açık inbound kuralları bul
aws ec2 describe-security-groups 
  --query 'SecurityGroups[?contains(IpPermissions[].IpRanges[].CidrIp, `0.0.0.0/0`)].{
    GroupId:GroupId,
    GroupName:GroupName,
    VpcId:VpcId
  }' 
  --output json | jq '.[]'

# Kritik olmayan portlara açık grupları filtrele
aws ec2 describe-security-groups 
  --query 'SecurityGroups[*].{
    ID:GroupId,
    Name:GroupName,
    Rules:IpPermissions[?contains(IpRanges[].CidrIp, `0.0.0.0/0`) && (ToPort==`22` || ToPort==`3389` || ToPort==`5432`)]
  }' 
  --output json | jq '.[] | select(.Rules | length > 0)'

Mikro-segmentasyon için Kubernetes ortamında NetworkPolicy kullanmak da kritik önem taşıyor:

# Kubernetes NetworkPolicy örneği
# Sadece frontend pod'ları backend'e bağlanabilir
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-izole-et
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
      tier: api
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
          tier: web
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  # DNS trafiğine izin ver
  - ports:
    - protocol: UDP
      port: 53

Bu NetworkPolicy ile backend pod’ları sadece frontend’den istek alabilir ve sadece database’e bağlanabilir. Başka hiçbir lateral movement mümkün değil.

Sürekli İzleme ve Anomali Tespiti

Zero Trust “kur ve unut” değil, sürekli bir süreç. Sisteme giren her istek loglanmalı ve analiz edilmeli.

# AWS CloudTrail ile şüpheli aktivite tespiti
# Kısa sürede çok fazla API çağrısı yapan kullanıcıları bul
aws logs filter-log-events 
  --log-group-name "CloudTrail/DefaultLogGroup" 
  --start-time $(date -d "1 hour ago" +%s000) 
  --filter-pattern '{ $.errorCode = "AccessDenied" }' 
  --query 'events[*].message' 
  --output json | jq -r '.[] | fromjson | 
    "(.userIdentity.userName // .userIdentity.sessionContext.sessionIssuer.userName) - (.eventName) - (.sourceIPAddress)"' | 
  sort | uniq -c | sort -rn | head -20
# GuardDuty bulgularını otomatik olarak Slack'e ilet
# Lambda fonksiyonu için temel script
cat <<'EOF' > guardduty-alert.py
import boto3
import json
import urllib.request

def lambda_handler(event, context):
    finding = event['detail']
    severity = finding['severity']
    
    # Sadece yuksek ve kritik bulgulari ilet
    if severity < 7.0:
        return {'statusCode': 200, 'body': 'Dusuk oncelikli bulgu, atlanadi'}
    
    message = {
        "text": f":rotating_light: *GuardDuty Kritik Bulgu*",
        "attachments": [{
            "color": "danger",
            "fields": [
                {"title": "Tip", "value": finding['type'], "short": True},
                {"title": "Severity", "value": str(severity), "short": True},
                {"title": "Hesap", "value": finding['accountId'], "short": True},
                {"title": "Region", "value": finding['region'], "short": True},
                {"title": "Aciklama", "value": finding['description']}
            ]
        }]
    }
    
    webhook_url = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
    data = json.dumps(message).encode('utf-8')
    req = urllib.request.Request(webhook_url, data=data, 
                                  headers={'Content-Type': 'application/json'})
    urllib.request.urlopen(req)
    
    return {'statusCode': 200, 'body': 'Alert gonderildi'}
EOF

Servisler Arası Güven: mTLS ve Service Mesh

Mikroservis mimarisinde servisler birbirleriyle konuşuyor. Bu iletişim de Zero Trust kapsamında olmalı. Mutual TLS (mTLS) burada devreye giriyor.

# Istio ile mTLS zorunluluğu
# Namespace genelinde strict mTLS aktif et
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: strict-mtls
  namespace: production
spec:
  mtls:
    mode: STRICT
EOF

# Sadece belirli servislerin birbirine erişmesine izin ver
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: payment-service-policy
  namespace: production
spec:
  selector:
    matchLabels:
      app: payment-service
  rules:
  - from:
    - source:
        principals: 
          - "cluster.local/ns/production/sa/checkout-service"
          - "cluster.local/ns/production/sa/billing-service"
    to:
    - operation:
        methods: ["POST"]
        paths: ["/api/v1/payment/*"]
EOF

Bu yapıda ödeme servisi sadece checkout ve billing servislerinden gelen POST isteklerini kabul ediyor. mTLS sayesinde sertifika tabanlı kimlik doğrulama yapılıyor, IP tabanlı değil.

Gizli Bilgi Yönetimi: Secrets Management

Hardcoded credentials Zero Trust’un en büyük düşmanı. Tüm gizli bilgiler merkezi bir secrets manager üzerinden yönetilmeli.

# HashiCorp Vault ile dinamik database credential'ı
# Uygulama her seferinde kısa ömürlü credential alır

# Vault'ta database secret engine konfigürasyonu
vault secrets enable database

vault write database/config/postgres-prod 
  plugin_name=postgresql-database-plugin 
  allowed_roles="app-role" 
  connection_url="postgresql://{{username}}:{{password}}@db.internal:5432/proddb" 
  username="vault-admin" 
  password="vault-admin-pass"

# Rol tanımı: her credential maksimum 1 saat geçerli
vault write database/roles/app-role 
  db_name=postgres-prod 
  creation_statements="CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' 
    VALID UNTIL '{{expiration}}' IN GROUP app_users;" 
  default_ttl="1h" 
  max_ttl="2h"

# Uygulama credential alır
vault read database/creds/app-role
# Her seferinde farklı, geçici credential döner
# AWS Secrets Manager ile otomatik rotation script
aws secretsmanager rotate-secret 
  --secret-id prod/database/credentials 
  --rotation-rules AutomaticallyAfterDays=30

# Secret değerini uygulama kodu yerine ortam değişkeni olarak enjekte et
SECRET=$(aws secretsmanager get-secret-value 
  --secret-id prod/database/credentials 
  --query SecretString 
  --output text)

DB_PASSWORD=$(echo $SECRET | jq -r '.password')
export DB_PASSWORD

Gerçek Dünya Senaryosu: E-Ticaret Platformu

Büyük bir e-ticaret müşterimde Zero Trust geçişini nasıl yaptığımızı anlatayım. Başlangıç durumu şuydu: tüm servisler aynı VPC’de, servisler arası trafik filtrelenmiyor, developer’lar production’a doğrudan erişiyor, her yerde uzun ömürlü API key’ler.

Aşama 1 – Görünürlük: Önce mevcut durumu anlamak için bir hafta boyunca sadece VPC Flow Logs ve CloudTrail topladık. Hangi servis kime ne kadar konuşuyor? Hangi hesaplar hangi kaynaklara erişiyor? Bu veriler olmadan Zero Trust uygulayamazsınız, tahmine dayalı çalışırsınız.

Aşama 2 – Kimlik temizliği: 47 IAM kullanıcısını audit ettik. 12 tanesi eski çalışanlara aitti, hala aktifti. 8 servis hesabı gereksiz admin yetkisine sahipti. Bunları temizlemek inanılmaz güvenlik iyileştirmesi sağladı.

Aşama 3 – Segmentasyon: Monolitik VPC’yi üç katmana böldük: public (load balancer), private-app (uygulama sunucuları), private-data (veritabanları). Security Group’ları katmanlar arası minimal trafike izin verecek şekilde yeniden yazdık.

Aşama 4 – mTLS: Istio deploy ettik, servisler arası trafik şifrelendi ve her servis sertifika ile kimlik doğruladı.

Aşama 5 – Secrets rotation: Tüm uzun ömürlü credential’ları Vault’a taşıdık. CI/CD pipeline’ları OIDC token kullanmaya başladı.

Sonuç: 3 ay sonra bir penetration test yaptırdık. Önceki testte lateral movement ile 6 adımda üretim veritabanına ulaşılabiliyordu. Yeni testte saldırgan bir segmentin ötesine geçemedi.

Compliance ve Maliyet Dengesi

Zero Trust pahalı bir süreç olabilir ama doğru yapıldığında maliyet avantajı da var. Gereksiz geniş erişimler genellikle gereksiz kaynak kullanımını da beraberinde getirir.

Maliyet optimizasyonu için:

  • Kullanılmayan IAM kullanıcıları ve roller düzenli olarak temizlenmeli, bu audit maliyetlerini düşürür
  • Servis mesh (Istio/Linkerd) başlangıçta ek kaynak tüketir ama güvenlik olaylarının maliyetiyle kıyaslanmamalı
  • CloudTrail, GuardDuty, Security Hub maliyetleri hesaplanmalı ama bir veri ihlalinin ortalama maliyeti 4.5 milyon dolar düşünüldüğünde anlamsız kalır
  • Least privilege ile gereksiz API çağrıları ve kaynak erişimleri azalır

Compliance açısından:

  • PCI-DSS, SOC 2, ISO 27001 hepsi Zero Trust prensiplerini içeriyor
  • KVKK ve GDPR uyumluluğu için erişim logları ve data sınıflandırması Zero Trust’un doğal çıktıları
  • Düzenli access review’lar Zero Trust workflow’unun parçası olduğunda compliance audit’leri çok daha kolay geçiyor

Zero Trust Olgunluk Modeli

Sıfır Güvene geçiş bir gecede olmaz. Üç olgunluk seviyesi var:

Başlangıç seviyesi:

  • MFA aktif tüm kullanıcılarda
  • Temel IAM least privilege uygulandı
  • Merkezi loglama var
  • VPC segmentasyonu mevcut

Orta seviye:

  • Conditional access policy’leri aktif
  • Secrets management merkezi
  • Otomatik anomali tespiti çalışıyor
  • Service mesh ile mTLS uygulandı
  • Düzenli access review süreci işliyor

Olgun seviye:

  • Just-in-time (JIT) erişim: gerektiğinde, gerektiği kadar
  • Davranış tabanlı risk skoru ile dinamik erişim
  • Tüm workload kimlik tabanlı erişim kontrolü
  • Otomatik remediation
  • Continuous compliance monitoring

Yaygın Hatalar ve Nasıl Kaçınılır

“VPN olsun yeter” yanılgısı: VPN Zero Trust değil. Kullanıcı VPN’e bağlandıktan sonra iç ağda sınırsız dolaşabiliyorsa sorun var.

Sadece insan kimliklerine odaklanmak: Makine kimlikleri (servis hesapları, Lambda fonksiyonları, container’lar) çok daha büyük risk. Bunları ihmal etmeyin.

Logging’i sonraya bırakmak: Zero Trust’ta logging önce gelir, her şeyin önünde. Göremediğinizi yönetemezsiniz.

Her şeyi aynı anda yapmaya çalışmak: Önce en kritik asset’leri belirleyin, oradan başlayın. Tüm ortamı birden Zero Trust’a çevirmek hem başarısızlık hem de ekip yorgunluğu getirir.

Kullanıcı deneyimini göz ardı etmek: Security ekibinden geçen politikalar kullanıcılar tarafından bypass edilir. Shadow IT doğar. FIDO2 hardware key’ler, SSO entegrasyonu, self-service access request portalleri hem güvenliği hem deneyimi iyileştirir.

Sonuç

Bulut ortamında Sıfır Güven artık bir nice-to-have değil, temel güvenlik mimarisi olmalı. Çevre güvenliği anlayışı bulutla birlikte işlevsiz hale geldi. Kimlik yeni çevredir, mikro-segmentasyon yeni ağdır, sürekli doğrulama yeni güvenlik duvarıdır.

Buradan çıkarılacak pratik adımlar şunlar: önce mevcut ortamınızı görünür hale getirin, sonra kimlik ve erişim yönetimini temizleyin, ardından ağ segmentasyonu uygulayın ve servisler arası güveni kriptografik kimlik doğrulamaya taşıyın. Bu bir yolculuk, sprint değil maraton.

En önemli şey şu: Zero Trust bir ürün değil, bir mimari felsefe. Tek bir araç satın alarak Zero Trust geçişi yapamazsınız. Süreçlerinizi, kültürünüzü ve araçlarınızı birlikte değiştirmeniz gerekiyor. Ve bunu küçük, ölçülebilir adımlarla yaparsanız hem güvenlik ekibi hem de geliştirme ekibi bu geçişi başarıyla tamamlayabilir.

Bir yanıt yazın

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