| name | container-security |
| description | Container and Kubernetes security hardening, image scanning, runtime protection, and supply chain security. Use when securing Docker containers, Kubernetes clusters, scanning images for vulnerabilities, or implementing runtime security controls. |
| metadata | {"tags":["security","containers","kubernetes","docker","falco"],"version":"1.0.0"} |
Container Security
Comprehensive container and Kubernetes security: image hardening, runtime protection, supply chain security, and cluster hardening.
"Containers are only as secure as the images they run and the clusters that orchestrate them."
🎯 When to Use
- Securing Docker containers and images
- Hardening Kubernetes clusters
- Scanning container images for vulnerabilities
- Implementing runtime security (Falco, Sysdig)
- Supply chain security (Sigstore, SLSA)
- Pod Security Standards enforcement
- Network policies for microservices
🐳 Docker Security
Image Hardening
# Multi-stage build for minimal attack surface
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main .
# Distroless final image
FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app/main /main
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/main"]
# Security best practices
FROM node:20-alpine
# Run as non-root
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
# Install only production dependencies
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# Copy application with correct ownership
COPY --chown=nodejs:nodejs . /app
WORKDIR /app
USER nodejs
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js || exit 1
EXPOSE 3000
CMD ["node", "server.js"]
Docker Security Options
docker run \
--read-only \
--security-opt=no-new-privileges:true \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--memory=512m \
--memory-swap=512m \
--cpus=1.0 \
--pids-limit=100 \
--user 1000:1000 \
myapp:latest
docker network create --internal --subnet 172.18.0.0/16 isolated-network
Image Scanning
trivy image myapp:latest
trivy image --severity HIGH,CRITICAL myapp:latest
trivy image --format sarif -o report.sarif myapp:latest
snyk container test myapp:latest
snyk container test --severity-threshold=high myapp:latest
clairctl report myapp:latest
grype myapp:latest
grype myapp:latest -o sarif > grype-report.sarif
Dockerfile Security Audit
dockerfilelint Dockerfile
hadolint Dockerfile
checkov -f Dockerfile --framework dockerfile
☸️ Kubernetes Security
RBAC Configuration
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: production
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-role
namespace: production
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["app-config"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-rolebinding
namespace: production
subjects:
- kind: ServiceAccount
name: app-sa
namespace: production
roleRef:
kind: Role
name: app-role
apiGroup: rbac.authorization.k8s.io
Pod Security Standards
apiVersion: v1
kind: Pod
metadata:
name: secure-app
namespace: production
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
limits:
memory: "256Mi"
cpu: "500m"
requests:
memory: "128Mi"
cpu: "250m"
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /cache
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
Network Policies
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-to-db
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 5432
Secrets Management
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: app-secrets
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: aws-secrets-manager
target:
name: app-secrets
creationPolicy: Owner
data:
- secretKey: DATABASE_URL
remoteRef:
key: production/app
property: database_url
- secretKey: API_KEY
remoteRef:
key: production/app
property: api_key
grep -r "password:" ./k8s/
grep -r "secret:" ./k8s/
grep -r "token:" ./k8s/
kubeseal --format=yaml < secret.yaml > sealed-secret.yaml
🔒 Supply Chain Security
Image Signing & Verification
cosign generate-key-pair
cosign sign --key cosign.key myregistry/myapp:latest
cosign verify --key cosign.pub myregistry/myapp:latest
cosign attest --predicate slsa-provenance.json --type slsaprovenance myregistry/myapp:latest
slsa-verifier verify-image myregistry/myapp:latest \
--source-uri github.com/myorg/myrepo \
--print-provenance
SBOM Generation
syft myapp:latest -o spdx-json > sbom.spdx.json
syft myapp:latest -o cyclonedx-json > sbom.cyclonedx.json
trivy image --format cyclonedx -o sbom.cyclonedx.json myapp:latest
grype myapp:latest -o cyclonedx-json > sbom.cyclonedx.json
Admission Controllers
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels
spec:
validationFailureAction: enforce
rules:
- name: check-for-labels
match:
resources:
kinds:
- Pod
validate:
message: "All pods must have app and version labels"
pattern:
metadata:
labels:
app: "?*"
version: "?*"
---
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8spspprivilegedcontainer
spec:
crd:
spec:
names:
kind: K8sPSPPrivilegedContainer
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spspprivilegedcontainer
violation[{"msg": msg}] {
c := input.review.object.spec.containers[_]
c.securityContext.privileged
msg := sprintf("Privileged container is not allowed: %v", [c.name])
}
🛡️ Runtime Security
Falco
- rule: Terminal Shell in Container
desc: Detect shell execution inside a container
condition: spawned_process and container and shell_procs
output: "Shell spawned in container (user=%user.name container=%container.name)"
priority: WARNING
- rule: Privilege Escalation
desc: Detect privilege escalation via setuid/setgid
condition: spawned_process and (setuid or setgid)
output: "Privilege escalation detected (user=%user.name command=%proc.cmdline)"
priority: CRITICAL
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
--set driver.kind=modern_ebpf \
--set tty=true
kubectl logs -l app=falco -n falco | grep "Warning\|Critical"
Runtime Monitoring
sysdig -p"%evt.time %proc.name %fd.name" evt.type=open
kubectl get pods --all-namespaces -o json | jq '.items[].spec.containers[].securityContext'
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, securityContext: .spec.securityContext, containers: [.spec.containers[] | {name: .name, securityContext: .securityContext}]}'
📋 Security Checklist
Image Security
Kubernetes Security
Runtime Security
🛠️ Tools Reference
| Tool | Purpose |
|---|
| Trivy | Container image & filesystem scanning |
| Grype | Vulnerability scanner for containers |
| Snyk | Container & dependency scanning |
| Clair | Static vulnerability analysis |
| Cosign | Container image signing (Sigstore) |
| Syft | SBOM generation |
| Falco | Runtime threat detection |
| Sysdig | Container monitoring & forensics |
| kube-bench | CIS Kubernetes benchmark |
| kube-hunter | Kubernetes penetration testing |
| Kyverno | Kubernetes policy engine |
| OPA Gatekeeper | Policy enforcement |
| Sealed Secrets | Encrypt secrets for GitOps |
| External Secrets Operator | Sync secrets from external providers |
📚 References