Docker kontejnery běží v produkci. Kubernetes orchestruje stovky podů. Ale kdo kontroluje, že base image neobsahuje kritickou CVE? Že kontejner neběží jako root? Že pod nemá přístup k host filesystem? Kontejnerová bezpečnost je v roce 2018 kritické téma.
Bezpečnost začíná u base image¶
Většina bezpečnostních problémů kontejnerů pochází z base image. Typický node:10 image je založený na Debianu a obsahuje stovky balíčků — včetně těch s known vulnerabilities.
- Používejte Alpine varianty —
node:10-alpinemá ~5 MB vs ~900 MB plného Debian image. Méně balíčků = méně attack surface. - Multi-stage builds — build dependencies nepatří do produkčního image
- Pinujte verze —
FROM node:10.16.3-alpinemístoFROM node:10
# Multi-stage build — bezpečný produkční image
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¶
Každý image musí projít bezpečnostním skenováním před nasazením. Nástroje:
- Clair — open-source, integrovaný s CoreOS Quay registry
- Trivy — rychlý, jednoduchý, skenuje OS packages i application dependencies
- Anchore — policy-based scanning s custom pravidly
- Docker Hub — automatický security scan pro paid plány
# Trivy scan v 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 |
+---------+------------------+----------+-------------------+
Neběžte jako root¶
Překvapivě mnoho produkčních kontejnerů stále běží jako root. To znamená, že container escape vulnerability dá útočníkovi root přístup na host.
- Vždy přidejte
USERinstrukci v Dockerfile - Kubernetes Pod Security Policies (PSP) mohou vynutit non-root na úrovni clusteru
- Nastavte
readOnlyRootFilesystem: truekde je to možné
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 — mikrosegmentace¶
Ve výchozím nastavení může v Kubernetes každý pod komunikovat s každým. To je bezpečnostní noční můra. Network Policies definují, kdo smí mluvit s kým:
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
Tato policy říká: api-server přijímá traffic pouze od nginx-ingress na portu 8080 a smí se připojit pouze k postgres na portu 5432. Žádný jiný traffic není povolen.
Pozor: Network Policies vyžadují CNI plugin, který je podporuje — Calico, Cilium, Weave Net. Výchozí kubenet je nepodporuje.
Secrets management¶
Kubernetes Secrets jsou ve výchozím stavu uloženy v etcd nešifrovaně (base64 ≠ šifrování). Řešení:
- Encryption at rest — Kubernetes 1.7+ podporuje EncryptionConfiguration pro šifrování secrets v etcd
- HashiCorp Vault — externalizujte secrets mimo cluster, injektujte přes sidecar nebo init container
- Sealed Secrets — Bitnami nástroj pro šifrované secrets v Git repozitáři
- RBAC — omezte, kdo může číst secrets na namespace úrovni
Runtime security¶
Image scanning zachytí known vulnerabilities. Ale co zero-day exploity a anomální chování za běhu?
- Falco — open-source runtime security od Sysdig. Detekuje anomální syscalls, neočekávané procesy, přístupy k citlivým souborům.
- Seccomp profiles — omezení dostupných syscalls na minimum nutné pro aplikaci
- AppArmor/SELinux — mandatory access control na úrovni kernelu
# Falco pravidlo — detekce shell v kontejneru
- 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 obsahuje tisíce community images s neznámým původem. Jak zajistit, že stahujete důvěryhodný image?
- Docker Content Trust — image signing pomocí Notary
- Private registry — Harbor, GitLab Container Registry s integrovaným scanningem
- Admission controllers — Kubernetes webhook, který odmítne pod bez podepsaného image
Defense in depth — žádná jedna vrstva nestačí¶
Kontejnerová bezpečnost vyžaduje opatření na každé úrovni: bezpečný base image, scanning v CI pipeline, Pod Security Policies, Network Policies, secrets encryption, runtime monitoring. Žádné jednotlivé opatření není dostatečné. Implementujte je postupně — začněte non-root kontejnery a image scanningem, pak přidávejte další vrstvy.