Zum Inhalt springen

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen

Container-Sicherheit und Kubernetes Hardening: Der vollständige Guide

Container- und Kubernetes-Sicherheit von Grund auf: Das 4C-Modell, Docker-Image-Hardening (non-root, distroless, multi-stage), Container-Scanning mit Trivy und Grype, Kubernetes RBAC, Pod Security Standards (restricted), NetworkPolicy (deny-all + Allowlist), Secrets Management mit External Secrets Operator und Vault, Runtime-Security mit Falco und eBPF, Serverless Security, Supply Chain Security mit Cosign/SLSA, CI/CD-Pipeline und Cloud-Native Security Maturity Model.

Inhaltsverzeichnis (14 Abschnitte)

Container haben die Art und Weise, wie Anwendungen deployed werden, revolutioniert - und gleichzeitig neue Angriffsflächen geschaffen. Von unsicheren Images über überprivilegierte Pods bis hin zu Container-Escape: ein falsch konfigurierter Kubernetes-Cluster ermöglicht Ausbrüche aus Containern, laterale Bewegung zu anderen Pods und vollständige Cluster-Übernahme. Dieser Guide zeigt, wie Container-Sicherheit und Kubernetes wirklich gehärtet werden.

Das 4C-Modell der Cloud-Native Security

Cloud (Infrastruktur-Sicherheit)
  └── Cluster (Kubernetes-Sicherheit)
       └── Container (Image- und Laufzeit-Sicherheit)
            └── Code (Anwendungssicherheit)

Jede Schicht schützt die darunter liegende.
Eine Schwachstelle in der Cloud-Schicht gefährdet alles.

Das 4C-Modell stammt aus dem CNCF Cloud Native Security Whitepaper und definiert vier Sicherheitsebenen:

  1. Cloud - Infrastruktur, Cloud Provider IAM, VPC-Design
  2. Cluster - Kubernetes selbst: RBAC, API-Server-Härtung, etcd-Verschlüsselung
  3. Container - Images, Runtime-Security, Capabilities
  4. Code - Anwendungssicherheit, Dependencies, Secrets im Code

Kubernetes Threat-Landschaft

OWASP Kubernetes Top 10 - häufigste Angriffsvektoren:

  1. Kompromittierter Container → Escape zum Host
  2. Schwache RBAC → unberechtigter API-Server-Zugriff
  3. Unverschlüsselte Secrets → Credentials im Klartext in etcd
  4. Fehlende Network Policies → laterale Bewegung zwischen Pods
  5. Unsichere Images → bekannte CVEs in Container-Images
  6. Privilegierte Container → Host-Zugriff aus Container
  7. Misconfigured ServiceAccounts → automatisch gemountete Tokens
  8. Unsicheres Kubernetes Dashboard ohne Authentifizierung
  9. Fehlende Audit Logs → keine Forensik möglich
  10. Überprivilegierte Cloud-IAM-Rollen für Worker Nodes (z.B. EC2)

Container-Image-Sicherheit

Sichere Dockerfiles

# Multi-stage build: Build-Tools bleiben aus dem Produktions-Image heraus

# Go-Beispiel: Minimalstes Image (FROM scratch)
FROM golang:1.22-alpine AS builder
WORKDIR /build
COPY go.sum go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app ./cmd/server

FROM scratch  # LEER - nur Binary + CA-Certs
COPY --from=builder /app /app
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
USER 65534:65534  # nobody
ENTRYPOINT ["/app"]

# Python-Beispiel: Distroless Image (kein Shell, kein Paketmanager)
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
COPY . .

FROM gcr.io/distroless/python3-debian12
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY --from=builder /app .
USER nonroot:nonroot  # Nicht root!
CMD ["app.py"]

# Java-Beispiel: JRE statt JDK, kein Maven in Production
FROM maven:3.9-eclipse-temurin-21 AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests

FROM eclipse-temurin:21-jre-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
USER appuser
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

# Node-Beispiel: Non-Root User
FROM node:20-alpine
WORKDIR /app
COPY package*.json .
RUN npm ci --production && \
    addgroup -S appgroup && \
    adduser -S appuser -G appgroup
COPY . .
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]

Was Distroless Images bieten:

  • Kein Shell (bash, sh)
  • Kein Paketmanager (apt, apk)
  • Kein curl, wget
  • Minimale Angriffsfläche - Angreifer kann nach Eindringen kaum etwas ausführen

Container-Image-Scanning

# Trivy (Aqua Security, kostenlos - empfohlen):
trivy image --severity HIGH,CRITICAL nginx:latest
trivy image --severity CRITICAL,HIGH python:3.12

# Dockerfile auf Fehlkonfigurationen prüfen:
trivy config --severity HIGH,CRITICAL Dockerfile

# Kubernetes-Manifeste prüfen:
trivy config --severity HIGH,CRITICAL ./k8s/

# CI/CD Integration (GitHub Actions):
# - name: Trivy Image Scan
#   uses: aquasecurity/trivy-action@master
#   with:
#     image-ref: 'myapp:${{ github.sha }}'
#     format: 'sarif'
#     output: 'trivy-results.sarif'
#     severity: 'CRITICAL,HIGH'
#     exit-code: '1'  # Pipeline schlägt fehl bei Findings!

# GitLab CI Integration:
# scan_image:
#   stage: security
#   image: aquasec/trivy:latest
#   script:
#     - trivy image --exit-code 1 --severity HIGH,CRITICAL
#       $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
#   allow_failure: false

# Grype (Anchore):
grype myapp:latest
grype myapp:latest --only-fixed  # Nur patchbare Schwachstellen

# Snyk:
snyk container test myapp:v1.2.3

Image-Policy-Regeln:

  • Keine Images mit HIGH/CRITICAL CVEs in Produktion
  • Base-Images wöchentlich rebuilden (frische Patches)
  • Private Registry (Harbor) statt direktes Docker Hub
  • Digest-Pinning: image: nginx:1.25-alpine@sha256:a8560b36... (Tag kann neu gebaut werden, Digest nicht)

Supply Chain Security

Image-Signierung mit Cosign (Sigstore)

# Cosign - Image-Signierung (SLSA Level 2+)

# 1. Keypair generieren
cosign generate-key-pair

# 2. Image nach dem Build signieren
cosign sign --key cosign.key \
  registry.example.com/myapp:1.2.3

# 3. Verifizierung (in CI/CD oder Admission Controller)
cosign verify --key cosign.pub \
  registry.example.com/myapp:1.2.3

# Keyless Signing mit OIDC (GitHub Actions)
cosign sign \
  --oidc-issuer=https://token.actions.githubusercontent.com \
  --identity-token="${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
  registry.example.com/myapp:${{ github.sha }}

# SBOM (Software Bill of Materials) generieren und attachen
syft registry.example.com/myapp:1.2.3 \
  -o spdx-json > sbom.json

cosign attach sbom --sbom sbom.json \
  registry.example.com/myapp:1.2.3

# SBOM auf Schwachstellen prüfen
grype sbom:sbom.json --fail-on high

Kubernetes Cluster Hardening

Das Kubernetes-Sicherheitsmodell

CIS Kubernetes Benchmark v1.9 (2024):
  Über 100 Checks für Control Plane, Worker Nodes, Policies
  kube-bench: automatisiertes Benchmark-Testing

kube-bench ausführen:
  kubectl apply -f \
    https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
  kubectl logs -l app=kube-bench

Wichtige CIS-Kontrollen:
  1.2.1  --anonymous-auth=false (API Server)
  1.2.6  --authorization-mode=Node,RBAC (nie AlwaysAllow!)
  4.2.1  --anonymous-auth=false (Kubelet)
  5.1.1  RBAC: nicht cluster-admin vergeben

Häufige kube-bench FAIL-Punkte beheben:
  Anonymous Auth deaktivieren:
    --anonymous-auth=false

  RBAC aktivieren:
    --authorization-mode=Node,RBAC

  Audit Logging aktivieren:
    --audit-log-path=/var/log/kubernetes/audit.log
    --audit-log-maxage=30
    --audit-log-maxbackup=10
    --audit-log-maxsize=100

RBAC - Rollenbasierte Zugriffskontrolle

# Kubernetes RBAC-Konzepte:
#   Role/ClusterRole:     Was darf man tun? (Verbs auf Resources)
#   RoleBinding:          Wer bekommt eine Role? (in einem Namespace)
#   ClusterRoleBinding:   Wer bekommt eine ClusterRole? (clusterweit)

# GEFÄHRLICH - Anti-Pattern: Vollzugriff für alle Service Accounts
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: terrible-idea
subjects:
- kind: Group
  name: system:serviceaccounts  # ALLE Service Accounts!
roleRef:
  kind: ClusterRole
  name: cluster-admin           # Vollständiger Cluster-Admin!

---
# KORREKT - Least Privilege: Dedizierter ServiceAccount pro App
apiVersion: v1
kind: ServiceAccount
metadata:
  name: myapp-sa
  namespace: production

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: myapp-role
  namespace: production
rules:
  # Nur was die App wirklich braucht:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list"]
    resourceNames: ["myapp-config"]  # Nur eigene ConfigMap!
  # Kein: secrets (braucht External Secrets Operator!)
  # Kein: pods/exec (Container-Shell!)
  # Kein: cluster-scoped resources

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: myapp-rolebinding
  namespace: production
subjects:
  - kind: ServiceAccount
    name: myapp-sa
    namespace: production
roleRef:
  kind: Role
  name: myapp-role
  apiGroup: rbac.authorization.k8s.io

Gefährliche RBAC-Berechtigungen - niemals vergeben:

  • cluster-admin für Anwendungs-ServiceAccounts
  • Wildcards: verbs: ["*"], resources: ["*"]
  • secrets: ["get", "list"] (alle Secrets lesen!)
  • pods/exec (Shell in beliebige Pods!)
  • nodes: ["*"] (Node-Übernahme!)
# RBAC-Audit:
kubectl auth can-i create pods --namespace=production
kubectl auth can-i '*' '*' --all-namespaces  # Cluster-Admin-Check

# Alle Bindings für einen Service Account:
kubectl get rolebindings,clusterrolebindings -A \
  -o json | jq '.items[] | select(.subjects[]?.name=="myapp-sa")'

# rbac-lookup (Visualization):
kubectl-rbac-lookup myapp-sa -k serviceaccount -n production

Pod Security Standards (PSS)

# Namespace mit "restricted" Policy labeln (seit Kubernetes 1.25):
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/audit: restricted

# Alternativ via kubectl:
# kubectl label namespace production \
#   pod-security.kubernetes.io/enforce=restricted
Pod Security Profile:
  privileged:  Alles erlaubt (nur für System-Workloads!)
  baseline:    Grundlegende Sicherheit (verhindert Eskalation)
  restricted:  Maximal sicher (empfohlen für Anwendungen)

Restricted verhindert:
  Privileged containers
  hostNetwork, hostPID, hostIPC
  hostPath volumes
  PrivilegeEscalation
  Root-User
  Nicht-sichere Capabilities
# Restricted-konformer Pod (vollständiges Beispiel):
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: production
spec:
  template:
    spec:
      serviceAccountName: myapp-sa      # Dedizierter SA!
      automountServiceAccountToken: false  # Kein Token wenn nicht nötig!
      securityContext:
        runAsNonRoot: true
        runAsUser: 10001
        runAsGroup: 10001
        fsGroup: 10001
        seccompProfile:
          type: RuntimeDefault           # Syscall-Filterung aktiv!
      containers:
        - name: myapp
          image: myregistry/myapp:v1.2.3@sha256:abc123  # Digest-pinning!
          securityContext:
            allowPrivilegeEscalation: false  # Kein sudo/setuid!
            readOnlyRootFilesystem: true
            capabilities:
              drop: ["ALL"]             # Alle Linux-Capabilities entfernen!
              # add: ["NET_BIND_SERVICE"] # Nur wenn Port < 1024 nötig
          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "500m"               # Kein unbegrenzter CPU!
          volumeMounts:
            - name: tmp
              mountPath: /tmp           # Schreibbares /tmp trotz readOnlyRootFilesystem
      volumes:
        - name: tmp
          emptyDir: {}

NetworkPolicy und Microsegmentierung

Standard-Kubernetes: Alle Pods können alle Pods erreichen!
NetworkPolicy ist ein kritisches Härtungsmittel.

Voraussetzung: CNI mit NetworkPolicy-Support
  (Calico, Cilium, Weave Net - NICHT: Flannel ohne Calico)
# 1. Default-Deny-Policy: erst alles blockieren, dann erlauben
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}           # Alle Pods im Namespace
  policyTypes:
    - Ingress
    - Egress

---
# 2. Erlaubt: Ingress vom Ingress-Controller
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ingress-controller
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: ingress-nginx
          podSelector:
            matchLabels:
              app.kubernetes.io/name: ingress-nginx
      ports:
        - protocol: TCP
          port: 3000

---
# 3. Erlaubt: Frontend zu Backend (nur spezifische Pods)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080

---
# 4. Erlaubt: Egress zur DB und DNS
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-db-egress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
    - Egress
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: postgresql
      ports:
        - protocol: TCP
          port: 5432
    # DNS immer erlauben!
    - ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

Erweitert mit Cilium (DNS-basiertes Filtering):

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: restrict-egress-to-fqdn
spec:
  endpointSelector:
    matchLabels:
      app: backend
  egress:
    - toFQDNs:
        - matchName: "api.extern.de"  # Nur diese Domain erlaubt!
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP

Secrets Management in Kubernetes

Problem: Kubernetes Secrets sind standardmäßig nur Base64-kodiert
(= nicht verschlüsselt!) in etcd gespeichert.

Wer etcd lesen kann, kennt alle Secrets.
Secrets in Git (häufigster Fehler): niemals!

etcd-Verschlüsselung aktivieren

# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: <base64-encoded-32-byte-key>  # openssl rand -base64 32
  - identity: {}  # Fallback für unverschlüsselte Secrets (Migration)

# kube-apiserver starten mit:
# --encryption-provider-config=/etc/kubernetes/encryption-config.yaml

# Bestehende Secrets re-encrypten:
# kubectl get secrets -A -o json | kubectl replace -f -
# Überprüfung: Ist etcd verschlüsselt?
etcdctl get /registry/secrets/default/my-secret --print-value-only \
  | strings | head -5
# Wenn Plaintext → nicht verschlüsselt!
# Mit Encryption: Ausgabe beginnt mit "k8s:enc:..."

External Secrets Operator (empfohlen)

# Secrets in Vault/AWS SSM - nie direkt in K8s
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: myapp-secrets
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: myapp-secrets   # Erstellt K8s Secret automatisch!
    creationPolicy: Owner
  data:
    - secretKey: db-password      # K8s Secret Key
      remoteRef:
        key: production/myapp/database  # Vault Pfad
        property: password

---
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: vault-backend
spec:
  provider:
    vault:
      server: "https://vault.company.com"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "external-secrets"  # Vault Role mit Least Privilege

Sealed Secrets (Bitnami) - GitOps-freundlich: Secrets werden asymmetrisch verschlüsselt in Git gespeichert. Der Controller im Cluster entschlüsselt. Schlüssel-Rotation möglich.


Admission Controller und Policy Enforcement

# Kyverno Policy: Kein latest-Tag erlaubt
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-latest-tag
spec:
  validationFailureAction: enforce
  rules:
  - name: require-image-tag
    match:
      resources:
        kinds: ["Pod"]
    validate:
      message: "Image tag ':latest' ist verboten. Nutze einen spezifischen Tag."
      pattern:
        spec:
          containers:
          - image: "!*:latest"

---
# Kyverno: Root-User verboten
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-root-user
spec:
  validationFailureAction: enforce
  rules:
  - name: check-runAsNonRoot
    match:
      resources:
        kinds: ["Pod"]
    validate:
      message: "Container dürfen nicht als root laufen."
      pattern:
        spec:
          containers:
          - (securityContext):
              runAsNonRoot: true

---
# OPA Gatekeeper: Nur Registry-interne Images erlaubt
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
  name: allowed-repos
spec:
  match:
    kinds:
    - apiGroups: [""]
      kinds: ["Pod"]
  parameters:
    repos:
      - "registry.intern.firma.de/"
      - "registry.k8s.io/"
      # Docker Hub Images (docker.io/) werden abgelehnt!

Runtime Security mit Falco und eBPF

Falco - eBPF-basierte Laufzeit-Sicherheit

# Installation via Helm:
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
  --namespace falco \
  --set driver.kind=ebpf \
  --set falcosidekick.enabled=true \
  --set falcosidekick.config.slack.webhookurl=<WEBHOOK>
# Was Falco erkennt:
#   Shell in Container geöffnet (pod exec)
#   Privileg-Eskalation versucht
#   Sensitive Dateien gelesen (/etc/shadow, /etc/passwd)
#   Ungewöhnliche Netzwerkverbindungen von Containers
#   Malware-ähnliches Verhalten (Crypto-Mining, Reverse Shell)

# Wichtige Default-Rules (bereits in Falco eingebaut):
- rule: "Terminal shell in container"
  desc: "A shell was used as entrypoint/exec in a container"
  condition: >
    evt.type = execve and
    container and
    proc.name in (shell_binaries)

- rule: "Write below binary dir"
  desc: "An attempt to write to any file below a set of binary directories"
  condition: >
    bin_dir and evt.dir = < and
    not user_known_write_below_binary_dir_activities

# Custom Rule: Crypto-Mining erkennen
- rule: "Crypto Mining Activity"
  desc: "Detected potential crypto mining"
  condition: >
    evt.type = connect and
    fd.sport in (3333, 4444, 8888, 14444, 45700) and
    container
  output: >
    Crypto mining (connection=%fd.name pid=%proc.pid container=%container.id)
  priority: CRITICAL

# Falco-Alerts nach Slack/PagerDuty (falcosidekick Helm values):
# falcosidekick:
#   config:
#     slack:
#       webhookurl: "https://hooks.slack.com/services/..."
#       minimumpriority: "warning"
#     pagerduty:
#       routingkey: "<ROUTING-KEY>"
#       minimumpriority: "critical"

Tetragon und Cilium (eBPF)

Moderne Laufzeit-Sicherheitstools nutzen eBPF:

Tetragon (Cilium):
  Process, File, Network Events
  Real-time Enforcement (nicht nur Alerting)
  K8s-native (aware von Namespace, Pod, ServiceAccount)
  Alert: wenn /etc/shadow gelesen wird
  Alert: wenn kubectl im Container ausgeführt wird
  Kill: wenn Crypto-Miner-Verhalten erkannt wird

Cilium (Network Policy mit eBPF):
  L7-Awareness: HTTP-Method, DNS-basiertes Filtering
  Wireguard-Verschlüsselung zwischen Nodes
  Hubble: Network Observability

Service Mesh für Zero Trust

# Istio PeerAuthentication: mTLS Pflicht (alle Pods müssen sich authentifizieren)
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT

Serverless Security

Serverless (AWS Lambda, Azure Functions, Google Cloud Functions)
hat eigene Risiken:

Angriffsvektoren:
  Event-Injection: Angreifer kontrolliert Input-Event (S3, SQS, etc.)
  Dependency Vulnerabilities: npm/pip-Pakete ohne EDR-Schutz
  Overly Permissive IAM Roles
  Secrets in Environment Variables
  Denial-of-Wallet (kostspielige Loops oder rekursive Aufrufe)

Best Practices:
  Lambda Execution Role: nur minimal permissions
  Secrets: AWS Secrets Manager / Parameter Store (nicht Env Vars)
  Function Timeout setzen (verhindert Denial-of-Wallet)
  Dead Letter Queue für Fehler-Handling
  VPC-Placement wenn interne Ressourcen (RDS, ElastiCache)
  Input Validation: event['key'] niemals direkt in SQL/OS-Command
# AWS Lambda - sichere Struktur
import re, boto3

def handler(event, context):
    # Validierung ZUERST
    bucket = event.get('bucket', '')
    if not re.match(r'^[a-z0-9-]+$', bucket):
        raise ValueError("Invalid bucket name")

    # Secrets aus SSM, nicht aus Env Vars
    ssm = boto3.client('ssm')
    api_key = ssm.get_parameter(
        Name='/myapp/api_key', WithDecryption=True
    )['Parameter']['Value']
    # ...

Security im CI/CD-Pipeline

# Vollständige Sicherheits-Pipeline (GitHub Actions)
name: Secure Build Pipeline

on: [push]

jobs:
  sast:
    name: Static Analysis
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Semgrep SAST
      uses: returntocorp/semgrep-action@v1
      with:
        config: p/owasp-top-ten

  sca:
    name: Dependency Scan
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: pip-audit
      run: pip-audit -r requirements.txt

  container-scan:
    name: Container Image Scan
    needs: [sast, sca]
    runs-on: ubuntu-latest
    steps:
    - name: Build Image
      run: docker build -t myapp:${{ github.sha }} .

    - name: Trivy Scan
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: myapp:${{ github.sha }}
        severity: CRITICAL,HIGH
        exit-code: 1

    - name: Sign Image
      run: |
        cosign sign --key env://COSIGN_KEY \
          registry.example.com/myapp:${{ github.sha }}
      env:
        COSIGN_KEY: ${{ secrets.COSIGN_KEY }}

  dast:
    name: Dynamic Analysis (Staging)
    needs: container-scan
    runs-on: ubuntu-latest
    steps:
    - name: Deploy to Staging
      run: helm upgrade --install myapp ./chart \
             --set tag=${{ github.sha }}
    - name: OWASP ZAP Scan
      uses: zaproxy/action-full-scan@v0.10.0
      with:
        target: https://staging.example.com

Cloud-Native Security Maturity Model

Level 0 - Blind:
  Keine Container-Scans
  Default Kubernetes-Config
  Root-Container überall

Level 1 - Basic:
  Image Scanning (Trivy/Snyk)
  Non-root Container
  RBAC aktiviert (aber broad)

Level 2 - Managed:
  Supply Chain Signing (Cosign)
  Pod Security Standards (restricted)
  NetworkPolicy für alle Namespaces
  Falco Laufzeit-Monitoring

Level 3 - Advanced:
  SLSA Level 3 (Build-Herkunft verifiziert)
  eBPF-basiertes Laufzeit-Enforcement (Tetragon)
  Service Mesh mit mTLS (Istio/Linkerd)
  GitOps mit Policy-as-Code (OPA, Kyverno)
  Automatisches Remediation

Level 4 - Optimized:
  Kontinuierliche Compliance (CSPM + Policy)
  Chaos Engineering für Security
  Red Team Exercises in Cloud-Umgebung

Security-Checkliste für Kubernetes

API-Server:
  --anonymous-auth=false
  --authorization-mode=Node,RBAC (nie AlwaysAllow!)
  --audit-log-path konfiguriert
  --encryption-provider-config für Secrets
  --tls-cipher-suites auf sichere Ciphers gesetzt

Worker Nodes:
  kubelet --anonymous-auth=false
  kubelet --authorization-mode=Webhook
  kubelet --read-only-port=0 (schließt Port 10255!)
  Kernel-Updates aktuell

RBAC:
  Kein cluster-admin für normale Service Accounts
  RBAC-Audit mit rbac-lookup durchgeführt
  automountServiceAccountToken: false (per Namespace-Default)

Network:
  Default-Deny NetworkPolicy in allen Namespaces
  Ingress Controller mit TLS
  Egress-Policies für externe Kommunikation

Images:
  Image-Scanning in CI/CD (Trivy/Grype)
  Nur Registry-interne Images erlaubt (OPA Gatekeeper/Kyverno)
  Digest-Pinning für alle produktiven Images
  Non-Root-User in allen Containern
  Distroless oder Scratch-Images bevorzugen

Secrets:
  etcd-Verschlüsselung aktiviert
  Keine Secrets in Environment-Variablen oder Configmaps
  External Secrets Operator oder Sealed Secrets für sensitive Daten

Monitoring:
  Falco für Runtime-Anomalie-Erkennung
  Kubernetes Audit-Logs in SIEM weitergeleitet
  kube-bench regelmäßig ausführen

IaC / GitOps:
  Kubernetes-Manifeste via Checkov/tfsec geprüft
  Kyverno oder OPA Gatekeeper als Admission Controller
  Image-Signierung mit Cosign erzwungen

Fazit

Container und Kubernetes bieten enorme Vorteile für Deployment und Skalierung - aber ohne konsequentes Hardening entstehen massive Sicherheitsrisiken. Das 4C-Modell gibt den Rahmen: Cloud, Cluster, Container, Code - jede Schicht muss gesichert sein. Die wichtigsten Maßnahmen sind: Distroless-Images mit Digest-Pinning, RBAC nach Least-Privilege, Pod Security Standards auf “restricted”, NetworkPolicy Default-Deny, External Secrets statt etcd-Secrets und Falco für Runtime-Anomalie-Erkennung.

Weiterführend: Cloud Security Hub | Cloud Detection Engineering

Quellen & Referenzen

  1. [1] NIST SP 800-204 Security Strategies for Microservices-based Application Systems - NIST
  2. [2] CNCF Cloud Native Security Whitepaper - CNCF
  3. [3] CIS Kubernetes Benchmark - CIS
  4. [4] OWASP Kubernetes Top 10 - OWASP

Fragen zu diesem Thema?

Unsere Experten beraten Sie kostenlos und unverbindlich.

Erstberatung

Über den Autor

Chris Wojzechowski
Chris Wojzechowski

Geschäftsführender Gesellschafter

Geschäftsführender Gesellschafter der AWARE7 GmbH mit langjähriger Expertise in Informationssicherheit, Penetrationstesting und IT-Risikomanagement. Absolvent des Masterstudiengangs Internet-Sicherheit an der Westfälischen Hochschule (if(is), Prof. Norbert Pohlmann). Bestseller-Autor im Wiley-VCH Verlag und Lehrbeauftragter der ASW-Akademie. Einschätzungen zu Cybersecurity und digitaler Souveränität erschienen u.a. in Welt am Sonntag, WDR, Deutschlandfunk und Handelsblatt.

10 Publikationen
  • Einsatz von elektronischer Verschlüsselung - Hemmnisse für die Wirtschaft (2018)
  • Kompass IT-Verschlüsselung - Orientierungshilfen für KMU (2018)
  • IT Security Day 2025 - Live Hacking: KI in der Cybersicherheit (2025)
  • Live Hacking - Credential Stuffing: Finanzrisiken jenseits Ransomware (2025)
  • Keynote: Live Hacking Show - Ein Blick in die Welt der Cyberkriminalität (2025)
  • Analyse von Angriffsflächen bei Shared-Hosting-Anbietern (2024)
  • Gänsehaut garantiert: Die schaurigsten Funde aus dem Leben eines Pentesters (2022)
  • IT Security Zertifizierungen — CISSP, T.I.S.P. & Co (Live-Webinar) (2023)
  • Sicherheitsforum Online-Banking — Live Hacking (2021)
  • Nipster im Netz und das Ende der Kreidezeit (2017)
IT-Grundschutz-Praktiker (TÜV) IT Risk Manager (DGI) § 8a BSIG Prüfverfahrenskompetenz Ausbilderprüfung (IHK)
Dieser Artikel wurde zuletzt am 08.03.2026 bearbeitet. Verantwortlich: Chris Wojzechowski, Geschäftsführender Gesellschafter bei AWARE7 GmbH. Lizenz: CC BY 4.0 — freie Nutzung mit Namensnennung: „AWARE7 GmbH, https://a7.de

Cookielose Analyse via Matomo (selbst gehostet, kein Tracking-Cookie). Datenschutzerklärung