Container_security
Chapter 53: Container Security
Section titled “Chapter 53: Container Security”Container security is a critical aspect of modern DevOps practices, covering the entire container lifecycle from build to production.
Container Security Overview
Section titled “Container Security Overview”┌─────────────────────────────────────────────────────────────────────────────┐│ Container Security Layers │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌───────────────────────────────────────────────────────────────────┐ ││ │ Security at Each Layer │ ││ │ │ ││ │ ┌─────────────────────────────────────────────────────────────┐ │ ││ │ │ Build Time │ │ ││ │ │ - Secure base images │ │ ││ │ │ - Dependency scanning │ │ ││ │ │ - Code scanning │ │ ││ │ │ - Signing images │ │ ││ │ └─────────────────────────────────────────────────────────────┘ │ ││ │ │ │ ││ │ ▼ │ ││ │ ┌─────────────────────────────────────────────────────────────┐ │ ││ │ │ Registry Time │ │ ││ │ │ - Private registries │ │ ││ │ │ - Access control │ │ ││ │ │ - Image scanning │ │ ││ │ │ - Signed images │ │ ││ │ └─────────────────────────────────────────────────────────────┘ │ ││ │ │ │ ││ │ ▼ │ ││ │ ┌─────────────────────────────────────────────────────────────┐ │ ││ │ │ Deploy Time │ │ ││ │ │ - Kubernetes policies │ │ ││ │ │ - Resource limits │ │ ││ │ │ - Security contexts │ │ ││ │ │ - Network policies │ │ ││ │ └─────────────────────────────────────────────────────────────┘ │ ││ │ │ │ ││ │ ▼ │ ││ │ ┌─────────────────────────────────────────────────────────────┐ │ ││ │ │ Runtime Time │ │ ││ │ │ - Runtime security │ │ ││ │ │ - Falco monitoring │ │ ││ │ │ - Image stream │ │ ││ │ │ - Secrets management │ │ ││ │ └─────────────────────────────────────────────────────────────┘ │ ││ │ │ ││ └───────────────────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────────────────┘Image Security
Section titled “Image Security”Dockerfile Best Practices
Section titled “Dockerfile Best Practices”# BAD - Don't do this!FROM ubuntu:latestRUN apt-get update && apt-get install -y nginxUSER root
# GOOD - Secure DockerfileFROM ubuntu:22.04
# Set environment variablesENV NGINX_VERSION=1.24.0
# Create non-root userRUN groupadd --gid 1000 appgroup && \ useradd --uid 1000 --gid appgroup --shell /bin/bash --create-home appuser
# Install dependenciesRUN apt-get update && \ apt-get install -y --no-install-recommends \ ca-certificates \ nginx=${NGINX_VERSION}* \ && rm -rf /var/lib/apt/lists/*
# Copy applicationCOPY --chown=appuser:appgroup /app /home/appuser/app
# Switch to non-root userUSER appuser
# Set working directoryWORKDIR /home/appuser/app
# Expose portEXPOSE 8080
# Use exec form for CMDCMD ["nginx", "-g", "daemon off;"]Scanning Images
Section titled “Scanning Images”# Using Trivytrivy image myapp:latest
# Scan specific vulnerabilitiestrivy image --severity HIGH,CRITICAL myapp:latest
# Scan with output formatstrivy image --format json --output results.json myapp:latesttrivy image --format sarif --output results.sarif myapp:latest
# Scan filesystemtrivy fs --security-checks vuln,config /path/to/project
# Using Docker Scoutdocker scout cves myapp:latestdocker scout recommendations myapp:latestKubernetes Security
Section titled “Kubernetes Security”Security Context
Section titled “Security Context”apiVersion: v1kind: Podmetadata: name: secure-podspec: 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 seccompProfile: type: RuntimeDefault
resources: limits: cpu: "500m" memory: "256Mi" requests: cpu: "100m" memory: "64Mi"Pod Security Standards
Section titled “Pod Security Standards”apiVersion: policy/v1beta1kind: PodSecurityPolicymetadata: name: restricted annotations: seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'runtime/default' apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'spec: privileged: false allowPrivilegeEscalation: false requiredDropCapabilities: - ALL volumes: - 'configMap' - 'emptyDir' - 'projected' - 'secret' - 'downwardAPI' - 'persistentVolumeClaim' hostNetwork: false hostIPC: false hostPID: false runAsUser: rule: 'MustRunAsNonRoot' seLinux: rule: 'RunAsAny' supplementalGroups: rule: 'RunAsAny' fsGroup: rule: 'RunAsAny'Network Policies
Section titled “Network Policies”apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: app-network-policyspec: podSelector: matchLabels: app: myapp policyTypes: - Ingress - Egress
ingress: - from: - podSelector: matchLabels: role: frontend ports: - protocol: TCP port: 8080 - from: - namespaceSelector: matchLabels: name: monitoring ports: - protocol: TCP port: 9090
egress: - to: - podSelector: matchLabels: role: database ports: - protocol: TCP port: 5432 - to: - namespaceSelector: {} ports: - protocol: TCP port: 53 - protocol: UDP port: 53Secrets Management
Section titled “Secrets Management”Kubernetes Secrets
Section titled “Kubernetes Secrets”apiVersion: v1kind: Secretmetadata: name: myapp-secretstype: OpaquestringData: database-url: postgres://user:password@postgres:5432/mydb api-key: "1234567890abcdef" # Or use data: for base64 encoded valuesdata: username: dXNlcg== # base64 encodedUsing Secrets in Pods
Section titled “Using Secrets in Pods”apiVersion: v1kind: Podmetadata: name: myappspec: containers: - name: myapp image: myapp:latest env: - name: DATABASE_URL valueFrom: secretKeyRef: name: myapp-secrets key: database-url - name: API_KEY valueFrom: secretKeyRef: name: myapp-secrets key: api-key volumeMounts: - name: secret-volume mountPath: /etc/secrets readOnly: true volumes: - name: secret-volume secret: secretName: myapp-secretsExternal Secrets Operator
Section titled “External Secrets Operator”apiVersion: external-secrets.io/v1beta1kind: ExternalSecretmetadata: name: myapp-external-secretspec: refreshInterval: 1h secretStoreRef: name: vault-backend kind: SecretStore target: name: myapp-secrets creationPolicy: Owner data: - secretKey: database-url remoteRef: key: database/creds property: url - secretKey: api-key remoteRef: key: api/keys property: keyRuntime Security
Section titled “Runtime Security”Falco Configuration
Section titled “Falco Configuration”apiVersion: v1kind: ConfigMapmetadata: name: falco-config namespace: falcodata: falco.yaml: | time_format_iso_year: true json_output: true rules_file: - /etc/falco/falco-rules.yaml - /etc/falco/falco-rules.local.yaml
engine: kind: modules ebpf: probe: ""
syscall_event_drops: threshold: 0.1
falco-rules.yaml: | - rule: Detect shell in container desc: > Notice shell spawn inside a container condition: > evt.type = execve and container.id != host and (evt.arg.shell = 1 or evt.arg.cmd = /bin/sh) output: > Shell spawn in container (user=%user.name container_id=%container.id image=%container.image.repository) priority: WARNINGImage Signing
Section titled “Image Signing”Using Cosign
Section titled “Using Cosign”# Generate key paircosign generate-key-pair
# Sign an imagecosign sign myregistry.io/myapp:latest
# Verify signaturecosign verify myregistry.io/myapp:latest
# Verify with public keycosign verify --key cosign.pub myregistry.io/myapp:latest
# Add annotationscosign sign --key cosign.key --a version=1.0.0 myregistry.io/myapp:latestPolicy Controller
Section titled “Policy Controller”apiVersion: policy/v1beta1kind: ClusterImagePolicymetadata: name: image-policyspec: images: - glob: "ghcr.io/myorg/*" authorities: - key: data: | -----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY----- attestations: - predicateType: cosign.sigstore.dev/attestation/v1 name: custom-attestationSupply Chain Security
Section titled “Supply Chain Security”┌─────────────────────────────────────────────────────────────────────────────┐│ Container Supply Chain Security │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌───────────────────────────────────────────────────────────────────┐ ││ │ SBOM (Software Bill of Materials) │ ││ │ │ ││ │ Generate SBOM: │ ││ │ - syft myapp:latest -o json │ ││ │ - docker scout sbom myapp:latest │ ││ │ - trivy fs --sbom /path/to/project │ ││ │ │ ││ │ SBOM Formats: │ ││ │ - SPDX │ ││ │ - CycloneDX │ ││ │ - SWID │ ││ │ │ ││ └───────────────────────────────────────────────────────────────────┘ ││ ││ ┌───────────────────────────────────────────────────────────────────┐ ││ │ SLSA Compliance │ ││ │ │ ││ │ Level 0: No guarantees │ ││ │ Level 1: SBOM exists │ ││ │ Level 2: Build process documented │ ││ │ Level 3: Build hardened and verified │ ││ │ │ ││ └───────────────────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────────────────┘Summary
Section titled “Summary”In this chapter, you learned:
- Security Layers: Build, registry, deploy, runtime
- Image Security: Dockerfile best practices, scanning
- Kubernetes Security: Security contexts, pod security, network policies
- Secrets Management: Kubernetes secrets, external secrets operator
- Runtime Security: Falco monitoring
- Image Signing: Cosign, policy controller
- Supply Chain: SBOM, SLSA compliance