Bulut Güvenliği Denetim ve Uyumluluk Yönetimi

Bulut ortamlarında güvenlik denetimi yapmak, on-premise dünyasındaki klasik güvenlik anlayışından çok farklı bir zihin yapısı gerektiriyor. “Sunucu odamın kapısını kilitlersem güvendeyim” mantığı burada işe yaramıyor. AWS, Azure veya GCP üzerinde çalışan bir altyapıda yanlış yapılandırılmış tek bir S3 bucket veya fazla yetkili bir IAM rolü, tüm güvenlik duvarı yatırımınızı anlamsız kılabilir. Bu yazıda bulut güvenliği denetimini nasıl otomatize edeceğinizi, uyumluluk gereksinimlerini nasıl yöneteceğinizi ve gerçek dünya senaryolarıyla bu süreçleri nasıl hayata geçireceğinizi ele alacağız.

Bulut Güvenliği Denetiminin Temelleri

Bulut güvenliği denetimi, üç temel eksende düşünülmeli:

  • Yapılandırma denetimi: Servisler doğru yapılandırılmış mı?
  • Erişim denetimi: Kim neye erişebiliyor?
  • Veri denetimi: Veriler nerede, nasıl korunuyor?

Bu üç ekseni düzenli aralıklarla kontrol etmeden “güvenliyiz” demek, arabayı sürerken aynalara bakmamak gibi bir şey. Anlık görüntünüz temiz olabilir, ama arka tarafta neler olduğunu bilmiyorsunuzdur.

Uyumluluk Standartları ve Gerçek Dünya

Kurumlar genellikle şu standartlarla karşılaşıyor:

  • CIS Benchmarks: Pratik ve teknik odaklı, bulut için özel benchmark setleri var
  • SOC 2: Özellikle SaaS firmaları için kritik
  • PCI DSS: Ödeme sistemleriyle temas eden her ortam için zorunlu
  • ISO 27001: Kurumsal güvenlik yönetim sistemi çerçevesi
  • KVKK/GDPR: Kişisel veri işleyen tüm sistemler için

Bunların hepsini manuel takip etmeye çalışırsanız bir ay sonra ya burnout olursunuz ya da denetim raporunuzun yarısını atlarsınız. Otomasyon şart.

AWS Ortamı için Güvenlik Denetimi

Prowler ile Kapsamlı AWS Denetimi

Prowler, AWS güvenlik denetimi için açık kaynaklı en güçlü araçlardan biri. CIS AWS Foundations Benchmark dahil 300’den fazla kontrolü otomatik olarak çalıştırıyor.

# Prowler kurulumu
pip install prowler

# Temel denetim çalıştırma
prowler aws

# Belirli bir profil ve bölge için
prowler aws --profile production --region eu-west-1

# Sadece CIS benchmark kontrollerini çalıştır
prowler aws --compliance cis_aws_foundations_benchmark_3.0

# HTML rapor oluştur
prowler aws --output-formats html --output-path /var/reports/prowler/

# Sadece kritik ve yüksek bulgular
prowler aws --severity critical high --output-formats json

Prowler çıktısında gördüğünüz her bulguyu körü körüne düzeltmeye çalışmayın. Önce “bu bulgu bizim iş sürecimizi etkiler mi?” sorusunu sorun. Örneğin MFA olmayan bir IAM kullanıcısı bulgusu çıktığında, o kullanıcının aslında bir CI/CD pipeline servis hesabı olduğunu anlayabilirsiniz. Çözüm MFA değil, kullanıcıyı kaldırıp IAM role’e geçmek olacaktır.

AWS Config ile Sürekli Uyumluluk İzleme

Tek seferlik denetim yeterli değil. AWS Config, kaynak yapılandırmalarını sürekli izler ve uyumsuzlukları anında tespit eder.

# AWS CLI ile Config kuralı oluşturma
aws configservice put-config-rule 
  --config-rule '{
    "ConfigRuleName": "s3-bucket-public-read-prohibited",
    "Source": {
      "Owner": "AWS",
      "SourceIdentifier": "S3_BUCKET_PUBLIC_READ_PROHIBITED"
    },
    "Scope": {
      "ComplianceResourceTypes": ["AWS::S3::Bucket"]
    }
  }'

# Uyumsuz kaynakları listele
aws configservice get-compliance-details-by-config-rule 
  --config-rule-name s3-bucket-public-read-prohibited 
  --compliance-types NON_COMPLIANT 
  --query 'EvaluationResults[*].EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId'

# Tüm Config kurallarının uyumluluk özetini al
aws configservice describe-compliance-by-config-rule 
  --query 'ComplianceByConfigRules[*].{Rule:ConfigRuleName, Compliance:Compliance.ComplianceType}' 
  --output table

Lambda ile Otomatik Remediation

Bulgu tespit etmek güzel ama otomatik düzeltme yapabilmek daha güzel. Aşağıdaki Lambda fonksiyonu, herkese açık S3 bucket’ı tespit edince otomatik kapatıyor.

# lambda_s3_remediation.py
import boto3
import json

def lambda_handler(event, context):
    s3_client = boto3.client('s3')
    
    # Config event'inden bucket adını al
    config_item = event.get('detail', {})
    resource_id = config_item.get('resourceId', '')
    
    if not resource_id:
        print("Bucket adı bulunamadı")
        return {'statusCode': 400}
    
    try:
        # Public access block ayarlarını uygula
        s3_client.put_public_access_block(
            Bucket=resource_id,
            PublicAccessBlockConfiguration={
                'BlockPublicAcls': True,
                'IgnorePublicAcls': True,
                'BlockPublicPolicy': True,
                'RestrictPublicBuckets': True
            }
        )
        
        print(f"Bucket {resource_id} public erişime kapatıldı")
        
        # SNS ile bildirim gönder
        sns_client = boto3.client('sns')
        sns_client.publish(
            TopicArn='arn:aws:sns:eu-west-1:123456789:security-alerts',
            Subject=f'Otomatik Remediation: {resource_id}',
            Message=f'S3 bucket {resource_id} herkese açıktı. Otomatik olarak kapatıldı.'
        )
        
        return {'statusCode': 200, 'body': 'Remediation tamamlandi'}
        
    except Exception as e:
        print(f"Hata: {str(e)}")
        return {'statusCode': 500, 'body': str(e)}

Bu yaklaşımı production’a almadan önce bir “dry-run” modu ekleyin. Yanlış tetiklenmiş bir remediation, çalışan bir servisi durdurabilir.

Azure Ortamı için Güvenlik Denetimi

Microsoft Defender for Cloud ile Güvenlik Skoru

Azure’da Defender for Cloud (eski adıyla Security Center) yerleşik uyumluluk panosu sunuyor. Ancak CLI üzerinden bu verileri çekip kendi raporlama sistemlerinize entegre edebilirsiniz.

# Azure CLI ile güvenlik önerilerini listele
az security assessment list 
  --query "[?status.code=='Unhealthy'].{Name:displayName, Severity:metadata.severity, Status:status.code}" 
  --output table

# Belirli bir politika atamasının uyumluluk durumunu kontrol et
az policy state list 
  --resource-group production-rg 
  --filter "complianceState eq 'NonCompliant'" 
  --query "[*].{Resource:resourceId, Policy:policyDefinitionName}" 
  --output table

# Güvenlik skoru al
az security secure-score-controls list 
  --query "[*].{Control:displayName, Score:score.current, MaxScore:score.max}" 
  --output table

Terraform ile Policy as Code

Uyumluluk kurallarını kod olarak yönetmek, hem tekrarlanabilirlik hem de versiyon kontrolü açısından kritik. Aşağıda Azure Policy ataması için örnek bir Terraform modülü var.

# azure_compliance_policy.tf

# CIS Benchmark policy girişimi ataması
resource "azurerm_subscription_policy_assignment" "cis_benchmark" {
  name                 = "cis-benchmark-assignment"
  subscription_id      = data.azurerm_subscription.current.id
  policy_definition_id = "/providers/Microsoft.Authorization/policySetDefinitions/1a5bb27d-173f-493e-9568-eb56638dde4d"
  display_name         = "CIS Microsoft Azure Foundations Benchmark"
  description          = "Otomatik CIS uyumluluk denetimi"

  parameters = jsonencode({
    "effect" = {
      value = "AuditIfNotExists"
    }
  })

  identity {
    type = "SystemAssigned"
  }

  location = "westeurope"
}

# Storage account public erişim engel politikası
resource "azurerm_resource_group_policy_assignment" "deny_public_storage" {
  name                 = "deny-public-storage"
  resource_group_id    = azurerm_resource_group.production.id
  policy_definition_id = azurerm_policy_definition.deny_storage_public_access.id
  display_name         = "Storage Account Public Erisimi Engelle"

  parameters = jsonencode({
    "effect" = {
      value = "Deny"
    }
  })
}

Çoklu Bulut Ortamlarında Merkezi Denetim

Birden fazla bulut sağlayıcısıyla çalışıyorsanız, her birini ayrı ayrı takip etmek hızla kaotik hale gelir. Bu durumda Open Policy Agent (OPA) veya Steampipe gibi araçlar hayat kurtarıcı oluyor.

Steampipe ile Çoklu Bulut Sorguları

# Steampipe kurulumu
sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/turbot/steampipe/main/install.sh)"

# AWS ve Azure eklentilerini kur
steampipe plugin install aws azure

# Tüm buluttaki herkese açık S3 ve Azure Storage bucket'larını bul
steampipe query "
SELECT
  'aws' as cloud,
  name,
  region,
  bucket_policy_is_public
FROM aws_s3_bucket
WHERE bucket_policy_is_public = true

UNION ALL

SELECT
  'azure' as cloud,
  name,
  location as region,
  allow_blob_public_access::text
FROM azure_storage_account
WHERE allow_blob_public_access = true;
"

# MFA olmayan kullanıcıları her iki cloud'da bul
steampipe query "
SELECT 'aws' as cloud, user_name, mfa_active
FROM aws_iam_user
WHERE NOT mfa_active
UNION ALL
SELECT 'azure' as cloud, display_name, account_enabled::text
FROM azure_ad_user
WHERE NOT account_enabled;
"

Güvenlik Denetim Raporu Otomasyon Scripti

Gerçek dünyada güvenlik ekibi olmayan orta ölçekli firmalarda, sysadmin olarak hem teknik işleri yapıp hem de yönetime anlaşılır raporlar sunmanız gerekiyor. Bu bash scripti her hafta otomatik çalışıp özet rapor üretiyor.

#!/bin/bash
# weekly_security_audit.sh

set -euo pipefail

REPORT_DATE=$(date +%Y-%m-%d)
REPORT_DIR="/var/reports/security"
REPORT_FILE="${REPORT_DIR}/weekly_audit_${REPORT_DATE}.txt"
AWS_REGION="eu-west-1"
SNS_TOPIC="arn:aws:sns:eu-west-1:123456789:security-weekly-report"

mkdir -p "$REPORT_DIR"

echo "=== HAFTALIK GUVENLIK DENETIM RAPORU ===" > "$REPORT_FILE"
echo "Tarih: $REPORT_DATE" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"

# 1. MFA olmayan IAM kullanicilari
echo "### MFA OLMAYAN IAM KULLANICILARI ###" >> "$REPORT_FILE"
aws iam generate-credential-report --output text > /dev/null 2>&1
sleep 5
aws iam get-credential-report --query 'Content' --output text | 
  base64 -d | 
  awk -F',' 'NR>1 && $4=="true" && $8=="false" {print "UYARI: " $1 " - MFA aktif degil"}' 
  >> "$REPORT_FILE"

# 2. Public S3 bucket kontrolu
echo "" >> "$REPORT_FILE"
echo "### PUBLIC S3 BUCKET KONTROLU ###" >> "$REPORT_FILE"
aws s3api list-buckets --query 'Buckets[*].Name' --output text | 
  tr 't' 'n' | while read bucket; do
    result=$(aws s3api get-public-access-block 
      --bucket "$bucket" 
      --query 'PublicAccessBlockConfiguration.BlockPublicAcls' 
      --output text 2>/dev/null || echo "HATA")
    if [ "$result" != "True" ]; then
      echo "KRITIK: $bucket - Public erisim engeli yok!" >> "$REPORT_FILE"
    fi
  done

# 3. 90 gunden uzun suredir kullanilmayan access key'ler
echo "" >> "$REPORT_FILE"
echo "### ESKI ACCESS KEY KONTROLU ###" >> "$REPORT_FILE"
CUTOFF_DATE=$(date -d "90 days ago" +%Y-%m-%d)
aws iam list-users --query 'Users[*].UserName' --output text | 
  tr 't' 'n' | while read username; do
    aws iam list-access-keys --user-name "$username" 
      --query "AccessKeyMetadata[?CreateDate<='${CUTOFF_DATE}' && Status=='Active'].AccessKeyId" 
      --output text | grep -v "^$" | while read keyid; do
      echo "UYARI: $username - $keyid anahtari 90 gunden eski" >> "$REPORT_FILE"
    done
  done

# 4. Raporun SNS uzerinden gonderilmesi
CRITICAL_COUNT=$(grep -c "KRITIK:" "$REPORT_FILE" || true)
WARNING_COUNT=$(grep -c "UYARI:" "$REPORT_FILE" || true)

aws sns publish 
  --topic-arn "$SNS_TOPIC" 
  --subject "Haftalik Guvenlik Raporu: ${CRITICAL_COUNT} Kritik, ${WARNING_COUNT} Uyari" 
  --message "$(cat $REPORT_FILE)"

echo "Rapor olusturuldu: $REPORT_FILE"
echo "Kritik bulgular: $CRITICAL_COUNT"
echo "Uyarilar: $WARNING_COUNT"

Bu scripti crontab’a ekleyin:

# Her Pazartesi sabah 07:00'de calistir
0 7 * * 1 /opt/scripts/weekly_security_audit.sh >> /var/log/security_audit.log 2>&1

Gerçek Dünya Senaryosu: Yanlış Yapılandırılmış IAM Rolü

Birkaç yıl önce bir e-ticaret firmasının AWS altyapısını denetlerken şöyle bir senaryo yaşadım. Geliştirme ekibi hızlı ilerleme amacıyla bir Lambda fonksiyonuna AdministratorAccess policy’si atamış. Fonksiyon aslında sadece DynamoDB’ye yazıyordu. Bu tek hata, eğer fonksiyon bir güvenlik açığıyla ele geçirilseydi, tüm AWS hesabının kontrolünü kaybetmeleri anlamına geliyordu.

Denetim sonrası uyguladığımız düzeltme:

# En az yetki prensibini uygulamak icin custom policy olustur
aws iam create-policy 
  --policy-name LambdaDynamoDBWriteOnly 
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "dynamodb:PutItem",
          "dynamodb:UpdateItem",
          "dynamodb:BatchWriteItem"
        ],
        "Resource": "arn:aws:dynamodb:eu-west-1:123456789:table/orders"
      },
      {
        "Effect": "Allow",
        "Action": [
          "logs:CreateLogGroup",
          "logs:CreateLogStream",
          "logs:PutLogEvents"
        ],
        "Resource": "arn:aws:logs:*:*:*"
      }
    ]
  }'

# Eski AdministratorAccess policy'sini kaldır
aws iam detach-role-policy 
  --role-name OrderProcessingLambdaRole 
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

# Yeni dar kapsamlı policy'yi bağla
aws iam attach-role-policy 
  --role-name OrderProcessingLambdaRole 
  --policy-arn arn:aws:iam::123456789:policy/LambdaDynamoDBWriteOnly

Bu denetim yaklaşımı sayesinde hem güvenlik açığı kapatıldı hem de fonksiyonun gerçekte hangi kaynaklara ihtiyaç duyduğu netlik kazandı.

Uyumluluk Sürecini Yönetmek için Pratik Öneriler

Teknik araçlar kadar önemli olan bir diğer boyut, uyumluluk sürecinin organizasyonel yönetimi.

  • Bulguları önceliklendirin: Her bulgu eşit önemde değil. CVSS skoru veya iş etkisi bazlı bir önceliklendirme matrisi oluşturun
  • False positive yönetimi: Bazı bulgular gerçek bir risk teşkil etmeyebilir. Bu istisnaları belgeleyerek “kabul edilmiş risk” olarak kaydedin
  • Değişiklik yönetimiyle entegre edin: Yeni kaynak açılışlarında güvenlik kontrolü zorunlu olsun; bu CI/CD pipeline’ına entegre edilebilir
  • Periyodik gözden geçirme: Ayda bir uyumluluk skoru toplantısı yapın, trendin hangi yönde gittiğini takip edin
  • İstisna süresi koyun: Kabul edilen risklerin süresini sınırlı tutun; 6 ay sonra otomatik olarak yeniden değerlendirilsin
  • Ekip farkındalığı: Geliştiricilere “neden” yapılıyor sorusunun cevabını verin; korku kültürü değil anlayış kültürü oluşturun

SIEM Entegrasyonu

Güvenlik denetim bulgularını bir SIEM sistemine besleyebilirsiniz. Elastic Security veya Splunk kullananlar için Prowler ve AWS Security Hub çıktılarını bu sistemlere göndermek mümkün.

# AWS Security Hub'ı etkinleştir
aws securityhub enable-security-hub 
  --enable-default-standards 
  --tags '{"Environment":"production", "Team":"security"}'

# Security Hub bulgularını Elastic'e gönder
# Logstash pipeline konfigürasyonu
cat > /etc/logstash/conf.d/securityhub.conf << 'EOF'
input {
  sqs {
    queue => "security-hub-findings"
    region => "eu-west-1"
    codec => "json"
  }
}

filter {
  mutate {
    add_field => {
      "[@metadata][index]" => "security-findings-%{+YYYY.MM}"
    }
  }
  
  date {
    match => ["CreatedAt", "ISO8601"]
    target => "@timestamp"
  }
}

output {
  elasticsearch {
    hosts => ["https://elasticsearch:9200"]
    index => "%{[@metadata][index]}"
    user => "${ES_USER}"
    password => "${ES_PASSWORD}"
  }
}
EOF

Sonuç

Bulut güvenliği denetimi ve uyumluluk yönetimi, bir kez yapılıp unutulan bir proje değil, sürekli işletilmesi gereken bir süreç. Prowler ve AWS Config gibi araçlarla denetimi otomatize etmek, Terraform ile politikaları kod olarak yönetmek ve Lambda fonksiyonlarıyla otomatik düzeltme mekanizmaları kurmak; bu sürecin temel taşları.

En önemli nokta şu: Mükemmel uyumluluk skoru hedefi sizi yanıltmasın. Yüzde yüz uyumluluk bazen gerçek iş süreçleriyle çelişir ve çelişmesi doğaldır. Önemli olan kabul edilebilir riskleri bilinçli olarak belgelemek, kritik bulguları hızla kapatmak ve sisteminizin güvenlik durumunu her zaman görünür kılmak.

Sysadmin olarak bu araçları kurup otomatize ettiğinizde, güvenlik ekibiniz olmasa bile makul bir uyumluluk seviyesini sürdürebilirsiniz. Ama şunu da unutmayın: Araçlar rehberiniz, insan değerlendirmesi ise nihai kararın sahibidir. Bir script size “kritik” diyorsa bunu körü körüne kapatmadan önce iş bağlamını anlayın. O denge, iyi bir sysadmin’i harika bir sysadmin’den ayıran şeydir.

Bir yanıt yazın

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