Docker-Container laufen in der Produktion. Kubernetes orchestriert Hunderte von Pods. Aber wer kontrolliert, dass das Base Image keine kritische CVE enthält? Dass der Container nicht als Root läuft? Dass der Pod keinen Zugriff auf das Host-Dateisystem hat? Container Security ist 2018 ein kritisches Thema.
Sicherheit beginnt beim Base Image¶
Die meisten Container-Sicherheitsprobleme stammen vom Base Image. Ein typisches node:10 Image basiert auf Debian und enthält Hunderte von Paketen — einschließlich solcher mit bekannten Schwachstellen.
- Verwenden Sie Alpine-Varianten —
node:10-alpinehat ~5 MB vs. ~900 MB des vollen Debian-Images. Weniger Pakete = weniger Angriffsfläche. - Multi-Stage Builds — Build-Dependencies gehören nicht ins Produktions-Image
- Pinnen Sie Versionen —
FROM node:10.16.3-alpinestattFROM node:10
# DSGVO und IT-Systeme — Technische Vorbereitung auf die Verordnung
FROM node:10-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:10-alpine
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
USER app
EXPOSE 3000
CMD ["node", "server.js"]
Image Scanning¶
Jedes Image muss vor dem Deployment ein Sicherheits-Scanning durchlaufen. Tools:
- Clair — Open Source, integriert mit CoreOS Quay Registry
- Trivy — schnell, einfach, scannt OS-Pakete und Anwendungsabhängigkeiten
- Anchore — Policy-basiertes Scanning mit benutzerdefinierten Regeln
- Docker Hub — automatisches Sicherheits-Scanning für kostenpflichtige Pläne
# Trivy Scan in CI Pipeline
$ trivy image myapp:latest
myapp:latest (alpine 3.8.4)
============================
Total: 3 (UNKNOWN: 0, LOW: 1, MEDIUM: 1, HIGH: 1, CRITICAL: 0)
+---------+------------------+----------+-------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION |
+---------+------------------+----------+-------------------+
| musl | CVE-2019-14697 | HIGH | 1.1.19-r10 |
| openssl | CVE-2018-0734 | MEDIUM | 1.0.2p-r0 |
| zlib | CVE-2018-14618 | LOW | 1.2.11-r1 |
+---------+------------------+----------+-------------------+
Nicht als Root ausführen¶
Überraschenderweise laufen viele Produktions-Container immer noch als Root. Das bedeutet, dass eine Container-Escape-Schwachstelle dem Angreifer Root-Zugriff auf den Host gibt.
- Fügen Sie immer eine
USER-Anweisung im Dockerfile hinzu - Kubernetes Pod Security Policies (PSP) können Non-Root auf Cluster-Ebene erzwingen
- Setzen Sie
readOnlyRootFilesystem: truewo möglich
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false
runAsUser:
rule: MustRunAsNonRoot
fsGroup:
rule: RunAsAny
volumes:
- 'configMap'
- 'emptyDir'
- 'secret'
- 'persistentVolumeClaim'
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
Network Policies — Mikrosegmentierung¶
Standardmäßig kann in Kubernetes jeder Pod mit jedem anderen Pod kommunizieren. Das ist ein Sicherheitsalptraum. Network Policies definieren, wer mit wem sprechen darf:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-server-policy
namespace: production
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: nginx-ingress
ports:
- port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- port: 5432
Diese Policy besagt: api-server akzeptiert Traffic nur von nginx-ingress auf Port 8080 und kann sich nur mit postgres auf Port 5432 verbinden. Kein anderer Traffic ist erlaubt.
Achtung: Network Policies erfordern ein CNI-Plugin, das sie unterstützt — Calico, Cilium, Weave Net. Das Standard-kubenet unterstützt sie nicht.
Secrets Management¶
Kubernetes Secrets werden standardmäßig unverschlüsselt in etcd gespeichert (Base64 ≠ Verschlüsselung). Lösungen:
- Encryption at Rest — Kubernetes 1.7+ unterstützt EncryptionConfiguration für die Verschlüsselung von Secrets in etcd
- HashiCorp Vault — Secrets außerhalb des Clusters auslagern, per Sidecar oder Init Container injizieren
- Sealed Secrets — Bitnami-Tool für verschlüsselte Secrets im Git-Repository
- RBAC — einschränken, wer Secrets auf Namespace-Ebene lesen kann
Runtime Security¶
Image Scanning erkennt bekannte Schwachstellen. Aber was ist mit Zero-Day-Exploits und anomalem Verhalten zur Laufzeit?
- Falco — Open-Source Runtime Security von Sysdig. Erkennt anomale Syscalls, unerwartete Prozesse, Zugriffe auf sensible Dateien.
- Seccomp Profiles — verfügbare Syscalls auf das für die Anwendung notwendige Minimum beschränken
- AppArmor/SELinux — Mandatory Access Control auf Kernel-Ebene
# Falco-Regel — Shell im Container erkennen
- rule: Terminal shell in container
desc: Detect a shell opened in a container
condition: >
spawned_process and container and
proc.name in (bash, sh, zsh)
output: >
Shell opened in container
(user=%user.name container=%container.name
shell=%proc.name parent=%proc.pname)
priority: WARNING
Supply Chain Security¶
Docker Hub enthält Tausende von Community-Images mit unbekannter Herkunft. Wie stellen Sie sicher, dass Sie ein vertrauenswürdiges Image herunterladen?
- Docker Content Trust — Image-Signierung mit Notary
- Private Registry — Harbor, GitLab Container Registry mit integriertem Scanning
- Admission Controllers — Kubernetes Webhook, der Pods ohne signiertes Image ablehnt
Defense in Depth — keine einzelne Schicht reicht aus¶
Container Security erfordert Maßnahmen auf jeder Ebene: sicheres Base Image, Scanning in der CI-Pipeline, Pod Security Policies, Network Policies, Secrets-Verschlüsselung, Runtime Monitoring. Keine einzelne Maßnahme ist ausreichend. Implementieren Sie sie schrittweise — beginnen Sie mit Non-Root-Containern und Image Scanning, fügen Sie dann weitere Schichten hinzu.
Brauchen Sie Hilfe bei der Implementierung?
Unsere Experten helfen Ihnen bei Design, Implementierung und Betrieb. Von der Architektur bis zur Produktion.
Kontaktieren Sie uns