Container ve Kubernetes Log Güvenliği – Bölüm 6

Merhaba

Seri: SOC Analistleri İçin Log İzleme Rehberi (Ödeme Kuruluşları)

  1. Log İzleme Temelleri
  2. Mevzuat, Retention ve Silme Yasağı
  3. Windows/AD ve Linux Hardening
  4. Uygulama ve Veritabanı Katmanı
  5. Ağ Katmanı (Firewall/IDS-IPS/WAF/DDoS)
  6. Container ve Kubernetes (Bu Yazı)
  7. Bulut (AWS/Azure/GCP)
  8. XDR/EDR ve Bütünsel Korelasyon

Ön Not – Kapsam ve Amaç

Bu seri, kritik logları izlemeyi ve anlamayı öğretmek amacıyla yazılmıştır. Odak noktası tek tek ürünler değil, sürecin kendisidir: hangi olayın neden önemli olduğu, nasıl toplandığı, korele edildiği ve korunduğu.

Metindeki donanım, yazılım ve uygulama örnekleri (ürün adları, Event ID’ler, konfigürasyon parametreleri, komutlar) versiyona, sürüme ve yıllara göre değişiklik gösterebilir. Bir ayarın adı değişebilir, bir ürün yaşam döngüsünü tamamlayabilir, yeni bir alternatif ortaya çıkabilir. Bu nedenle örnekleri birebir kopyalanacak reçeteler olarak değil, mantığı kavramak için birer illüstrasyon olarak okuyun; kendi ortamınıza uygularken ilgili üreticinin güncel dokümantasyonunu esas alın.

Aynı şekilde, “Ödeme Kuruluşları İçin PCI DSS, HIPAA ve Türkiye Mevzuatı Bağlamında” hazırlanan bölümler de yürürlükteki düzenlemelere dayanır ve mevzuat değiştikçe güncellenmesi gerekir. PCI DSS sürümleri, TCMB tebliğleri, KVKK/MASAK düzenlemeleri ve retention süreleri zaman içinde değişebilir. Bu rehber hukuki veya denetim danışmanlığı yerine geçmez; nihai uygulama için kurumunuzun uyumluluk ekibine, QSA’sına ve güncel resmi mevzuata başvurun.

Kısacası: amaç, süreci ve mantığı anlamaktır. Örnekler bugünün fotoğrafıdır; ilke ise kalıcıdır.

Serinin altıncı bölümü. Konteyner ortamı geleneksel sunucudan farklı kurallara sahiptir: Kubernetes API audit ≠ pod stdout. RKE2 audit policy, Kyverno/OPA admission control (Riskli İşlemleri loglamak değil ENGELLEMEK), etcd encryption, Fluent Bit log toplama, CDE cluster ayrımı ve container’a özgü silme yasağı.

4.50. Container / Kubernetes – Log Katmanları

RKE2/Rancher gibi bir Kubernetes ortamında log yönetimi, geleneksel sunucudan farklı katmanlara sahiptir. En kritik yanılgı Bölüm 4.18’de belirttiğimizdir: pod stdout ≠ Kubernetes API audit log. Aşağıdaki tablo katmanları ve regülatif ağırlıklarını gösteriyor.

Katman Kaynak PCI DSS Retention Kritiklik
Kubernetes API Audit kube-apiserver audit log 🔴 10.2 tümü – en kritik 10 yıl 🔴🔴
Container/Pod stdout Uygulama logu 10.2.1.x 10 yıl (audit) / 90 gün (debug) 🔴
Container Runtime containerd, CRI-O, Docker daemon 10.2.1.7 1 yıl 🟠
Node/Host (Linux) auditd, journald 10.2.1.2 10 yıl 🔴
etcd Cluster state DB 🔴 Secret’lar burada! 1 yıl 🔴
Admission Controller OPA/Gatekeeper, Kyverno 6.5.1 (policy enforcement) 10 yıl 🔴
Image Registry Harbor, ECR, Quay 6.3.2 (SBOM), 11.3 10 yıl 🟠
CNI / Network Policy Calico, Cilium 1.2, 1.3 (segmentasyon) 1 yıl 🔴
Secrets Management Vault, Sealed Secrets 3.5, 3.6, 8.6 10 yıl 🔴
CI/CD Pipeline GitLab CI, ArgoCD, Jenkins 6.5.1, 6.5.4 10 yıl 🔴

4.51. Windows Event ID ↔ Kubernetes Karşılığı

Windows Anlam Kubernetes Karşılığı
4624 Başarılı login API audit: responseStatus.code=200/201
4625 Başarısız login API audit: responseStatus.code=401 (Unauthorized)
4672 Special privileges 🔴 cluster-admin ClusterRoleBinding · privileged: true pod
4688 Process oluşturuldu 🔴 pods/exec (kubectl exec) · Node’da auditd execve
4720 Kullanıcı oluşturuldu create serviceaccounts
4728/4732/4756 ⭐ Gruba üye eklendi 🔴🔴 create/update clusterrolebindings → cluster-admin verilmesi
4670 İzin (ACL) değişti 🔴 create/update clusterroles, roles (RBAC rule değişimi)
4719 ⚠️ Audit policy değişti 🔴🔴 audit-policy.yaml değişimi · apiserver flag değişimi
1102 ⚠️ Log temizlendi 🔴🔴 Audit log dosyası silme · Fluent Bit/Filebeat durdurma
1100 Log servisi durdu Fluent Bit / Filebeat DaemonSet silinmesi

Kubernetes’e özgü – Windows’ta Karşılığı Olmayan Kritik Olaylar:

Olay Neden Kritik
🔴 pods/exec Container’a shell açma = production’da doğrudan komut. CDE’de neredeyse hiç olmamalı
🔴 privileged: true pod Container escape → node root
🔴 hostPath volume mount Node dosya sistemine erişim (/ , /var/run/docker.sock)
🔴 secrets GET/LIST Vault/Secret içeriği okunması
🔴 hostNetwork/hostPID/hostIPC Node namespace’ine erişim
🔴 nodes/proxy Kubelet API’ye doğrudan erişim = tüm pod’lara komut
🔴 CronJob oluşturma Persistence mekanizması
🔴 etcd erişimi Tüm secret’lar düz metin (encryption at rest yoksa)

4.52. RKE2 – Kubernetes API Audit Policy

/etc/rancher/rke2/audit-policy.yaml (Kritik Kurallar):

apiVersion: audit.k8s.io/v1
kind: Policy
omitStages: ["RequestReceived"]
omitManagedFields: true

rules:
  # RBAC DEĞİŞİKLİKLERİ - Windows 4728/4729/4670 karşılığı
  - level: RequestResponse
    verbs: ["create", "update", "patch", "delete", "deletecollection"]
    resources:
      - group: "rbac.authorization.k8s.io"
        resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]

  # 🔴 EXEC / ATTACH / PORT-FORWARD - Windows 4688 karşılığı (CDE'de neredeyse hiç olmamalı)
  - level: RequestResponse
    resources:
      - group: ""
        resources: ["pods/exec", "pods/attach", "pods/portforward", "pods/proxy"]

  # 🔴 SECRETS - içerik loglanmaz ama ERİŞİM loglanır
  - level: Metadata           # 🔴 RequestResponse DEĞİL! Secret içeriği log'a düşer!
    resources:
      - group: ""
        resources: ["secrets", "configmaps"]

  # 🔴 Node erişimi (kubelet API bypass)
  - level: RequestResponse
    resources:
      - group: ""
        resources: ["nodes", "nodes/proxy", "nodes/status"]

  # 🔴 Admission controller / policy değişimi
  - level: RequestResponse
    resources:
      - group: "admissionregistration.k8s.io"
        resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"]
      - group: "kyverno.io"
        resources: ["clusterpolicies", "policies"]

  # 🔴 Network Policy (segmentasyon - PCI 1.2/1.3)
  - level: RequestResponse
    resources:
      - group: "networking.k8s.io"
        resources: ["networkpolicies", "ingresses"]

  # 🔴 CDE namespace'lerinde TÜM yazma işlemleri
  - level: RequestResponse
    namespaces: ["payment-prod", "cde", "payment-db"]
    verbs: ["create", "update", "patch", "delete"]

  # 🔴 SİLME İŞLEMLERİ - TÜMÜ
  - level: RequestResponse
    verbs: ["delete", "deletecollection"]

  # Sağlık kontrolleri (gürültü filtresi)
  - level: None
    nonResourceURLs: ["/healthz*", "/readyz*", "/livez*", "/metrics"]

🔴 KRİTİK: secrets için level: Metadata olmalı, RequestResponse değil. Aksi halde secret’ın base64 içeriği (veritabanı parolası, API key, sertifika) audit log’a düz metin düşer – PCI DSS 3.5/8.6 ihlali ve ciddi QSA bulgusu.

⚠️ Geniş level: None kuralları tehlikelidir. users: ["system:serviceaccount:*"] gibi bir muafiyet asla konulmamalı saldırgan tam da bir ServiceAccount kullanır.

/etc/rancher/rke2/config.yaml (Audit + Hardening):

kube-apiserver-arg:
  - "audit-policy-file=/etc/rancher/rke2/audit-policy.yaml"
  - "audit-log-path=/var/lib/rancher/rke2/server/logs/audit.log"
  - "audit-log-maxage=365"              # 🔴 Yerel: 1 yıl (arşiv 10 yıl WORM'da)
  - "audit-log-maxbackup=100"
  - "audit-log-mode=blocking-strict"    # 🔴🔴 LOG YAZILAMAZSA API İSTEĞİ REDDEDİLİR
  - "encryption-provider-config=/etc/rancher/rke2/encryption-config.yaml"  # 🔴 etcd şifreleme
  - "anonymous-auth=false"
  - "profiling=false"
  - "enable-admission-plugins=NodeRestriction,PodSecurity,ServiceAccount,AlwaysPullImages"

kubelet-arg:
  - "read-only-port=0"                  # 🔴 Kimlik doğrulamasız kubelet portu KAPALI
  - "anonymous-auth=false"
  - "protect-kernel-defaults=true"

profile: "cis"                          # 🔴 CIS Kubernetes Benchmark
secrets-encryption: true                # 🔴 RKE2 native secret encryption

etcd encryption at rest (PCI DSS 3.5) – encryption-config.yaml:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources: ["secrets", "configmaps"]
    providers:
      - kms:                            # 🔴 KMS (Vault) - anahtar dışarıda
          apiVersion: v2
          name: vault-kms
          endpoint: unix:///opt/vault-kms/socket.sock
      - aescbc:
          keys:
            - name: key1
              secret: 
      - identity: {}                    # 🔴 EN SONA! (identity = şifresiz)

🔴 identity: {} en sonda olmalı. Başta olursa hiçbir şey şifrelenmez (sessiz fail). etcd snapshot’ı çalınırsa tüm DB parolaları ve API key’ler açık gider.

4.53. Kubernetes Audit Log – Örnek Kayıtlar

🔴🔴 cluster-admin Verildi (Windows 4728 Muadili):

{
  "level": "RequestResponse",
  "verb": "create",
  "requestURI": "/apis/rbac.authorization.k8s.io/v1/clusterrolebindings",
  "user": { "username": "[email protected]", "groups": ["platform-admins"] },
  "sourceIPs": ["10.20.5.44"],
  "objectRef": { "resource": "clusterrolebindings", "name": "backdoor-admin" },
  "requestObject": {
    "roleRef": { "kind": "ClusterRole", "name": "cluster-admin" },
    "subjects": [{ "kind": "ServiceAccount", "name": "svc-backdoor", "namespace": "default" }]
  },
  "responseStatus": { "code": 201 }
}

🔴 kubectl exec (Windows 4688 Muadili – CDE’de Olmamalı!):

{
  "level": "RequestResponse",
  "verb": "create",
  "requestURI": ".../namespaces/payment-prod/pods/payment-api-7d9f/exec?command=%2Fbin%2Fsh...",
  "user": { "username": "[email protected]" },
  "objectRef": { "resource": "pods", "subresource": "exec",
                 "namespace": "payment-prod", "name": "payment-api-7d9f" },
  "responseStatus": { "code": 101 }
}

🔴 subresource: exec + namespace: payment-prod (CDE) = P1 alarm. Change Ticket ve CyberArk PAM oturumu ile eşleşmeli. Container içindeki komutlar audit log’da GÖRÜNMEZ bu yüzden node auditd + sudo I/O recording ile tamamlanmalıdır.

🔴 Privileged pod (Container Escape Riski):

{
  "level": "Request", "verb": "create",
  "user": { "username": "system:serviceaccount:default:svc-backdoor" },
  "requestObject": { "spec": {
    "hostPID": true, "hostNetwork": true,
    "containers": [{ "securityContext": { "privileged": true },
                     "command": ["nsenter", "--target", "1", "--mount", "--", "/bin/bash"] }],
    "volumes": [{ "hostPath": { "path": "/" } }]
  }},
  "responseStatus": { "code": 201 }
}

🔴 Bu pod başarıyla oluştuysa (201), admission controller (OPA/Kyverno/PSA) yok demektir. Engellenmiş (403) olmalıydı sadece loglanmamalıydı.

4.54. Admission Control – Riskli İşlemleri Engelleme (Kyverno)

Audit log loglar ama engellemez. Ödeme kuruluşunda riskli işlemler admission controller ile engellenmelidir.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: pci-dss-baseline
spec:
  validationFailureAction: Enforce      # 🔴 Audit değil, ENFORCE (blokla)
  rules:
  # 🔴 Privileged / host namespace / hostPath YASAK (PCI 2.2.6)
  - name: disallow-privileged-and-host
    match: { any: [{ resources: { kinds: ["Pod"] } }] }
    validate:
      message: "PCI DSS 2.2.6: privileged/hostNetwork/hostPID/hostPath yasak"
      pattern:
        spec:
          =(hostNetwork): "false"
          =(hostPID): "false"
          containers:
          - =(securityContext):
              =(privileged): "false"
              allowPrivilegeEscalation: false
              readOnlyRootFilesystem: true
              capabilities: { drop: ["ALL"] }
          securityContext: { runAsNonRoot: true }

  # 🔴 Sadece onaylı registry + imza (PCI 6.3.2)
  - name: allowed-registries
    match: { any: [{ resources: { kinds: ["Pod"] } }] }
    validate:
      message: "PCI DSS 6.3.2: Sadece harbor.example.local"
      pattern:
        spec:
          containers:
          - image: "harbor.example.local/*"

  # 🔴 :latest tag YASAK (izlenebilirlik - PCI 6.5.3)
  - name: disallow-latest
    match: { any: [{ resources: { kinds: ["Pod"] } }] }
    validate:
      message: "':latest' yasak - versiyon/digest belirtilmeli"
      pattern:
        spec:
          containers:
          - image: "!*:latest"

Silme Yasağı – Admission Webhook:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: prevent-deletion-compliance
spec:
  validationFailureAction: Enforce
  rules:
  # 🔴 CDE'de PVC/StatefulSet silme YASAK
  - name: prevent-pvc-deletion
    match:
      any:
      - resources:
          kinds: ["PersistentVolumeClaim", "PersistentVolume", "StatefulSet"]
          namespaces: ["payment-prod", "payment-db", "cde", "logging"]
    preconditions:
      all: [{ key: "{{ request.operation }}", operator: Equals, value: DELETE }]
    validate:
      message: "SILME YASAK - 6493/TCMB 10 yil saklama zorunlu. Imha Komisyonu karari gerekir."
      deny: {}

  # 🔴 Log toplama altyapısı silinemez (PCI 10.7)
  - name: prevent-logging-deletion
    match:
      any:
      - resources:
          kinds: ["DaemonSet", "Deployment", "ConfigMap"]
          namespaces: ["logging", "cattle-logging-system"]
    preconditions:
      all: [{ key: "{{ request.operation }}", operator: Equals, value: DELETE }]
    validate:
      message: "PCI DSS 10.7: Log toplama altyapisi silinemez/durdurulamaz."
      deny: {}

OPA/Gatekeeper Alternatifi Aynı Mantığı Rego ile İfade Eder:

package k8spcicompliance

violation[{"msg": msg}] {
  input.review.operation == "DELETE"
  input.review.kind.kind == "PersistentVolumeClaim"
  {"payment-prod", "payment-db", "cde"}[input.review.namespace]
  msg := sprintf("SILME YASAK: PVC %v/%v - 6493/TCMB 10 yil", [input.review.namespace, input.review.name])
}

4.55. Container Log Toplama – Fluent Bit DaemonSet

Container’ların ephemeral doğası (pod silinince /var/log/containers/*.log kaybolur) log toplamayı kritik kılar. Kritik gereksinimler: pod/node çökse de log kaybolmamalı, anında SIEM’e forward, 3. maskeleme katmanı, shipper silinemez/durdurulamaz.

fluent-bit.conf (Kritik Kısımlar):

[SERVICE]
    Health_Check      On                    # 🔴 Heartbeat (PCI 10.7)
    storage.path      /var/log/flb-storage/ # 🔴 Disk-backed buffer
    storage.checksum  on                    # 🔴 Bütünlük

# 🔴 Kubernetes API Audit Log (EN KRİTİK)
[INPUT]
    Name              tail
    Tag               k8s.audit
    Path              /var/lib/rancher/rke2/server/logs/audit.log
    DB                /var/log/flb_audit.db
    Skip_Long_Lines   Off                   # 🔴 UZUN SATIRI ATLAMA! (log kaybı)
    storage.type      filesystem            # 🔴 RAM değil, disk

# Container stdout + Node auditd inputs benzer şekilde tanımlanır...

[FILTER]
    Name                kubernetes
    Match               kube.*
    Merge_Log           On
    K8S-Logging.Exclude Off                  # 🔴 Pod annotation ile log HARİÇ TUTMA YASAK!

# 🔴 PCI DSS MASKELEME (3. katman)
[FILTER]
    Name    lua
    Match   *
    script  /fluent-bit/scripts/pci_mask.lua
    call    mask_sensitive

# 🔴 Hassas alanları tamamen kaldır
[FILTER]
    Name          record_modifier
    Match         *
    Remove_key    password
    Remove_key    token
    Remove_key    cvv
    Remove_key    pan

# 🔴 SIEM'e gönderim (mTLS)
[OUTPUT]
    Name              es
    Match             *
    Host              elasticsearch.example.local
    tls               On                     # 🔴 TLS zorunlu
    tls.crt_file      /certs/client.crt      # 🔴 mTLS
    Retry_Limit       False                  # 🔴 SONSUZ RETRY (log kaybolmasın!)
    storage.total_limit_size 10G

🔴 K8S-Logging.Exclude Off kritiktir. On olursa, bir pod kendi annotation’ıyla (fluentbit.io/exclude: "true") loglanmamayı seçebilir saldırgan izlerini böyle gizler.

🔴 Retry_Limit False – SIEM geçici erişilemezse log düşürülmez, disk queue’da bekler. Retry_Limit 5 olsa log kaybolur = PCI 10.2 ihlali.

4.56. Docker (Standalone) – Kısa Not

Kubernetes dışında Docker kullanılıyorsa: daemon.json‘da icc: false , no-new-privileges: true , userns-remap , live-restore , log rotation. En kritik nokta 🔴🔴 /var/run/docker.sock – bir container’a mount edilirse tam node kontrolü sağlar (K8s’teki privileged: true ile aynı tehlike). auditd ile izlenmeli:

# /etc/audit/rules.d/docker-pci.rules
-w /var/run/docker.sock          -p rwa -k docker_socket_CRITICAL
-w /run/containerd/containerd.sock -p rwa -k containerd_socket_CRITICAL
-w /etc/docker/daemon.json       -p wa  -k docker_config

PCI Uyumlu Container Çalıştırma:

--read-only , --cap-drop=ALL , --security-opt=no-new-privileges:true , --user 10001 , --memory/--cpus limit, digest ile (@sha256:...) – asla --privileged , -v /var/run/docker.sock , --net=host , --pid=host , image:latest.

4.57. Container / Kubernetes – SIEM Korelasyon Kuralları

🔴 P1 – Anında Alarm

Kural K1 – cluster-admin Yetkisi Verildi 🔴🔴 (Windows 4728 Muadili)

  k8s_audit: verb IN ("create","update","patch")
  AND objectRef.resource = "clusterrolebindings"
  AND requestObject.roleRef.name IN ("cluster-admin","admin","edit")
  AND responseStatus.code IN (200,201)
  → P1: Change Ticket + CyberArk oturumu ile eşleştir
  → MITRE: T1098

Kural K2 – Privileged Pod / Container Escape 🔴🔴

  k8s_audit: verb="create" AND resource="pods"
  AND (securityContext.privileged=true OR hostPID=true OR hostNetwork=true
       OR volumes[*].hostPath EXISTS)
  AND responseStatus.code = 201        # 🔴 BAŞARILI = admission controller YOK!
  → P1 KRİTİK: Container escape mümkün. Kyverno/OPA eksik!
  → MITRE: T1611 (Escape to Host)

Kural K3 – CDE Namespace’inde kubectl exec 🔴

  k8s_audit: objectRef.subresource IN ("exec","attach")
  AND objectRef.namespace IN ("payment-prod","cde","payment-db")
  → P1: CyberArk PAM oturumu + Change Ticket zorunlu
  → ⚠️ Container İÇİNDEKİ komutlar audit'te GÖRÜNMEZ → node auditd ile tamamla
  → MITRE: T1609

Kural K4 – Kubernetes Audit Log Kesildi / Silindi 🔴🔴 (Windows 1102 Muadili)

  Fluent Bit/Filebeat heartbeat kesildi > 5 dk
  OR k8s_audit: verb="delete" AND resource="daemonsets" AND namespace="logging"
  OR auditd: key="pci_log_tamper" AND path CONTAINS "audit.log"
  → P1 KRİTİK: PCI DSS 10.7
  → MITRE: T1562.008 (Disable Cloud Logs)

Kural K5 – Secret Toplu Erişim / Exfiltration 🔴

  k8s_audit: verb IN ("get","list") AND resource="secrets"
  AND COUNT > 10 in 5 dakika BY same user.username
  AND user NOT IN (approved_controllers)
  → MITRE: T1552.007

Kural K8 – Silme Girişimi (CDE Kaynağı) 🔴🔴

  k8s_audit: verb IN ("delete","deletecollection")
  AND namespace IN ("payment-prod","payment-db","cde","logging")
  AND resource IN ("persistentvolumeclaims","statefulsets","daemonsets","secrets")
  → P1: 6493/TCMB SİLME YASAĞI. Engellenmiş mi (403)? Değilse admission controller eksik!
  → MITRE: T1485

Kural K10 – Admission Controller Devre Dışı 🔴🔴

  k8s_audit: verb IN ("delete","update")
  AND resource IN ("validatingwebhookconfigurations","clusterpolicies","constrainttemplates")
  → P1: Güvenlik politikaları kaldırılıyor
  → MITRE: T1562.001

🟠 P2 – Aynı Gün

Kural K13 – RBAC Keşfi (Recon)

  k8s_audit: verb IN ("list","get")
  AND resource IN ("clusterroles","clusterrolebindings","roles","rolebindings")
  COUNT > 20 in 5 dk BY same user
  → kubectl-who-can / rakkess = saldırı hazırlığı
  → MITRE: T1069

Kural K11 – Container İçinde Şüpheli Process (node auditd Korelasyonu)

  [node auditd] key="pci_exec"
  AND process IN ("nsenter","chroot","crictl","kubectl")
  OR cmdline MATCHES "/var/run/docker.sock|/proc/1/ns"
  → Container escape (audit log'da görünmez, node'da görünür!)
  → MITRE: T1611

Kural K15 – CronJob / Job Oluşturuldu (Persistence)

  k8s_audit: verb="create" AND resource IN ("cronjobs","jobs")
  AND namespace NOT IN (approved_batch_namespaces) AND NO change_ticket
  → MITRE: T1053.007

4.58. CDE Cluster Ayrımı – Kritik Mimari Kararı

PCI DSS scope’unu küçültmek için en önemli mimari karar: CDE’yi ayrı bir cluster’da çalıştırmak.

SEÇENEK A (önerilen): Ayrı cluster
  ┌──────────────────┐    ┌──────────────────┐
  │ CDE Cluster      │    │ Non-CDE Cluster  │
  │ payment-api      │    │ crm, hr, portal  │
  │ payment-db       │    │                  │
  │ 🔴 PCI scope     │    │ ✅ scope dışı    │
  └──────────────────┘    └──────────────────┘

SEÇENEK B: Tek cluster + katı izolasyon
  ⚠️ Control plane (apiserver, etcd) PAYLAŞILDIĞI için
     TÜM CLUSTER PCI SCOPE'A GİRER

🔴 QSA’nın bakış açısı: Tek cluster’da CDE ve non-CDE varsa, control plane paylaşıldığı için tüm cluster scope’a girer. Namespace izolasyonu segmentasyon sayılmaz (VLAN/firewall gibi değildir). Ödeme kuruluşu için ayrı cluster çok daha savunulabilir bir mimaridir.

4.59. Container’a Özgü Kritik Riskler

Risk Neden Kritik Kontrol
🔴 Ephemeral pod = kaybolan log Pod silinince log dosyası silinir Fluent Bit anında forward + disk queue
🔴 Secret env var’da kubectl describe pod kubectl describe pod ile görünür Vault Agent / CSI Secret Store, volume mount
🔴 etcd’de secret düz metin Snapshot çalınırsa tüm parolalar secrets-encryption: true + KMS (Vault)
🔴 Container image’da hardcoded secret Registry’den çıkarılabilir Trivy/Grype scan + Cosign imza
🔴 Container escape Node root = tüm cluster Kyverno: privileged/hostPath/hostPID yasak
🔴 Docker socket mount Anında node kontrolü auditd + Kyverno engelleme
🔴 :latest tag Hangi kod çalışıyor bilinmez Digest (@sha256:...) zorunlu
🔴 Multi-tenancy CDE ve non-CDE aynı cluster’da Ayrı cluster önerilir

4.60. Container Saldırı Zinciri – Bütünsel Görünüm

SALDIRI ZİNCİRİ - Tüm log katmanları:

 1. [Ingress/WAF]   Uygulama zafiyeti (Log4Shell) exploit        → T1190
 2. [Pod stdout]    Uygulama exception + anormal davranış        → 🟡 tek başına düşük
 3. [Node auditd]   Container içinde reverse shell (execve)       → T1059
 4. [K8s Audit]     SA token ile API'ye erişim (pod'dan)          → T1552.007
 5. [K8s Audit]     403 yoğunluğu - yetki testi                   → T1613
 6. [K8s Audit]     🔴 secrets LIST → DB credentials okundu       → T1552
 7. [K8s Audit]     🔴 privileged pod create (hostPath: /)        → T1611 ESCAPE
 8. [Node auditd]   🔴 nsenter → node root                        → T1611
 9. [K8s Audit]     🔴🔴 clusterrolebinding → cluster-admin       → T1098
10. [pgaudit]       payment.cardholder_data toplu SELECT          → T1213
11. [FortiGate]     CDE → internete DNS tunneling                 → T1071.004
12. [K8s Audit]     🔴 Fluent Bit DaemonSet DELETE (iz silme)     → T1562.008
13. [Node auditd]   🔴 /var/log/audit/audit.log unlink            → T1070.002
  1. adımda admission controller engelleseydi zincir kırılırdı. 12–13. adımda silme yasağı (Kyverno + chattr +a + auditd -e 2) engellemeliydi. Her katman ayrı log kaynağıdır – WAF + Pod + Node auditd + K8s Audit + DB + Firewall ve XDR/SIEM bunları tek storyline olarak birleştirir.

4.61. Container / Kubernetes – Denetim Kanıtları ve Sık Bulgular

Denetim Kanıt Listesi (Özet)

  • kube-apiserver --audit-policy-file ayarlı + --audit-log-mode=blocking-strict
  • Audit policy’de secrets → level: Metadata (RequestResponse değil) 🔴
  • Geniş level: None kuralı yok (bypass riski)
  • Audit log SIEM’de + retention (yerel 1 yıl + WORM 10 yıl)
  • cluster-admin yetkisine sahip kullanıcı/SA listesi (≤5, named)
  • Default SA’larda automountServiceAccountToken: false
  • Kyverno/Gatekeeper Enforce modda 🔴
  • Negatif test: privileged pod deploy → 403 reddedildi kanıtı
  • Silme yasağı policy’si + test (PVC delete → 403)
  • secrets-encryption: true + identity: {} en sonda 🔴
  • Fluent Bit Retry_Limit False + K8S-Logging.Exclude Off 🔴
  • Pod restart testi: log kaybolmuyor kanıtı
  • CDE namespace’lerinde NetworkPolicy (default deny)
  • Sadece onaylı registry + Cosign imza doğrulama
  • Node’larda auditd (-e 2) + docker.sock izleniyor
  • CDE cluster ayrımı veya tek cluster ise tüm cluster PCI scope kabulü

En Sık Denetim Bulguları

Bulgu Sonuç
🔴 K8s API audit log YOK (sadece pod stdout) PCI DSS 10.2 FAIL – kim ne yaptı bilinmiyor
🔴 Audit policy’de secrets: RequestResponse Secret içeriği düz metin log’da – PCI 3.5/8.6 FAIL
🔴 audit-log-mode=batch (blocking değil) Log yazılamazsa API çalışmaya devam eder
🔴 Admission controller yok / Audit modda Privileged pod deploy edilebiliyor
🔴 privileged: true pod’lar production’da Container escape mümkün
🔴 hostPath: / veya docker.sock mount Node tam kontrolü
🔴 Default SA’da cluster-admin Her pod cluster admin
🔴 secrets-encryption kapalı etcd’de parolalar düz metin
🔴 identity: {} config’de başta Hiçbir şey şifrelenmiyor (sessiz fail!)
🔴 Pod restart’ta log kayboluyor Log bütünlüğü yok
🔴 K8S-Logging.Exclude On Pod kendini log’dan gizleyebiliyor
🔴 CDE ve non-CDE aynı cluster, “segmente” deniyor QSA kabul etmez – tüm cluster scope’a girer
🔴 kubectl exec production CDE’de serbest 10.2.1.2 – izlenemeyen ayrıcalıklı erişim
🔴 PVC/StatefulSet silinebiliyor 6493 – silme yasağı ihlali
🟠 NetworkPolicy yok (default allow) Segmentasyon yok
🟠 Node’larda auditd yok Container escape sonrası kör nokta

Container/K8s – Sekiz Maddelik Ana İlke:

  1. Pod stdout ≠ Kubernetes Audit Log. K8s API audit = Windows Security Event Log muadili, zorunludur.
  2. secrets audit level = Metadata asla RequestResponse (içerik log’a düşer).
  3. audit-log-mode=blocking-strict log yazılamıyorsa API isteği reddedilir.
  4. Admission controller (Kyverno/OPA) Enforce modda riskli işlemler loglanmaz, ENGELLENİR.
  5. CDE için ayrı cluster tek cluster’da namespace izolasyonu QSA’ya segmentasyon olarak satılamaz.
  6. kubectl exec CDE’de yasak break-glass hariç; yapılırsa node auditd ile içerideki komutlar da yakalanmalı.
  7. Log shipper silinemez/durdurulamaz – Kyverno policy + PCI DSS 10.7 alarmı.
  8. Ephemeral doğa = anında forward pod silinince log kaybolmamalı (disk-backed queue, sonsuz retry).

Bu yazıda container ve Kubernetes ortamında log güvenliğini; Kubernetes API audit ile pod stdout ayrımını, RKE2 audit policy’yi, Kyverno/OPA admission control’ü, etcd encryption’ı, Fluent Bit ile log toplamayı ve CDE cluster ayrımını ele aldık. Container ve Kubernetes – Bölüm 6 böylece tamamlandı.

Serinin bir sonraki yazısında “Bulut Loglama: AWS, Azure, GCP ve Veri Lokasyonu” konularına giriyoruz: CloudTrail/Activity Log/Cloud Audit kurgusu, data event’ler ve immutable storage.

Başka bir yazıda görüşmek dileğiyle…

Bir yanıt yazın

Başa Dön