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

Das 4C-Modell stammt aus dem CNCF Cloud Native Security Whitepaper und definiert vier konzentrische Sicherheitsebenen: Cloud umschließt Cluster, Cluster umschließt Container, Container umschließt Code. Jede Schicht schützt die darunter liegende - eine Schwachstelle auf der Cloud-Ebene gefährdet alle anderen Ebenen.

Das Modell 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

Der CIS Kubernetes Benchmark v1.9 (2024) umfasst über 100 Checks für Control Plane, Worker Nodes und Policies. kube-bench führt diesen Benchmark automatisiert aus:

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

Die wichtigsten CIS-Kontrollen: --anonymous-auth=false für den API Server (1.2.1) und Kubelet (4.2.1), --authorization-mode=Node,RBAC statt dem unsicheren AlwaysAllow (1.2.6) sowie keine cluster-admin-Vergabe in RBAC (5.1.1). Für Audit Logging sind --audit-log-path, --audit-log-maxage=30, --audit-log-maxbackup=10 und --audit-log-maxsize=100 zu setzen.

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

Es gibt drei Pod Security Profile: privileged erlaubt alles (nur für System-Workloads), baseline bietet grundlegende Sicherheit und verhindert Eskalation, und restricted ist maximal sicher und wird für alle Anwendungs-Workloads empfohlen. Das restricted-Profil verhindert privilegierte Container, hostNetwork/hostPID/hostIPC, hostPath-Volumes, Privilege Escalation, den Betrieb als Root-User und unsichere Linux 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

In Standard-Kubernetes können alle Pods alle anderen Pods erreichen - NetworkPolicy ist ein kritisches Härtungsmittel. Voraussetzung ist ein CNI-Plugin mit NetworkPolicy-Support: Calico, Cilium oder Weave Net funktionieren; Flannel ohne Calico unterstützt keine NetworkPolicies.

# 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

Kubernetes Secrets sind standardmäßig nur Base64-kodiert in etcd gespeichert - das ist keine Verschlüsselung. Wer etcd lesen kann, kennt alle Secrets. Secrets in Git zu committen ist der häufigste Fehler und muss konsequent vermieden werden.

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 für tiefe Kernel-Integration ohne Performance-Einbußen. Tetragon (von Cilium) überwacht Process, File und Network Events in Echtzeit und kann nicht nur alertieren, sondern auch aktiv eingreifen (Enforcement): Prozesse können beendet werden, wenn Crypto-Miner-Verhalten erkannt wird. Tetragon ist K8s-native und kennt Namespace, Pod und ServiceAccount. Typische Alerts: /etc/shadow wird aus einem Container gelesen, oder kubectl wird innerhalb eines Containers ausgeführt.

Cilium bietet als CNI Network Policies mit eBPF und L7-Awareness (HTTP-Method-basiertes und DNS-basiertes Filtering), Wireguard-Verschlüsselung zwischen Nodes und Hubble für vollständige 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-Plattformen wie AWS Lambda, Azure Functions und Google Cloud Functions haben eigene Risiken. Typische Angriffsvektoren sind Event Injection (der Angreifer kontrolliert das Input-Event aus S3, SQS usw.), Dependency Vulnerabilities in npm/pip-Paketen ohne EDR-Schutz, zu weit gefasste IAM Execution Roles, Secrets in Environment Variables und Denial-of-Wallet durch kostspielige Loops oder rekursive Aufrufe.

Best Practices für Serverless: Lambda Execution Role auf minimal permissions beschränken, Secrets aus AWS Secrets Manager oder Parameter Store statt aus Environment Variables lesen, Function Timeout setzen (verhindert Denial-of-Wallet), Dead Letter Queue für Fehler-Handling konfigurieren, VPC-Placement nutzen wenn interne Ressourcen wie RDS oder ElastiCache angebunden werden, und event['key'] niemals unvalidiert in SQL-Queries oder OS-Befehlen verwenden.

# 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-Konfiguration, Root-Container überall.

Level 1 - Basic: Image Scanning mit Trivy oder Snyk, Non-root Container, RBAC aktiviert (wenn auch noch zu weit gefasst).

Level 2 - Managed: Supply Chain Signing mit Cosign, Pod Security Standards auf restricted, NetworkPolicy für alle Namespaces und Falco für Laufzeit-Monitoring.

Level 3 - Advanced: SLSA Level 3 für verifizierte Build-Herkunft, eBPF-basiertes Laufzeit-Enforcement mit Tetragon, Service Mesh mit mTLS (Istio/Linkerd), GitOps mit Policy-as-Code (OPA, Kyverno) und automatisiertes Remediation.

Level 4 - Optimized: Kontinuierliche Compliance mit CSPM und Policy-as-Code, Chaos Engineering für Security und regelmäßige Red Team Exercises in der 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 halten

RBAC:

  • Kein cluster-admin für normale Service Accounts
  • RBAC-Audit mit rbac-lookup durchgeführt
  • automountServiceAccountToken: false als 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] CIS Kubernetes Benchmark - CIS
  3. [3] 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

E-Mail

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