Skip to content

Container_security

Container security is a critical aspect of modern DevOps practices, covering the entire container lifecycle from build to production.

┌─────────────────────────────────────────────────────────────────────────────┐
│ 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 │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
# BAD - Don't do this!
FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx
USER root
# GOOD - Secure Dockerfile
FROM ubuntu:22.04
# Set environment variables
ENV NGINX_VERSION=1.24.0
# Create non-root user
RUN groupadd --gid 1000 appgroup && \
useradd --uid 1000 --gid appgroup --shell /bin/bash --create-home appuser
# Install dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates \
nginx=${NGINX_VERSION}* \
&& rm -rf /var/lib/apt/lists/*
# Copy application
COPY --chown=appuser:appgroup /app /home/appuser/app
# Switch to non-root user
USER appuser
# Set working directory
WORKDIR /home/appuser/app
# Expose port
EXPOSE 8080
# Use exec form for CMD
CMD ["nginx", "-g", "daemon off;"]
Terminal window
# Using Trivy
trivy image myapp:latest
# Scan specific vulnerabilities
trivy image --severity HIGH,CRITICAL myapp:latest
# Scan with output formats
trivy image --format json --output results.json myapp:latest
trivy image --format sarif --output results.sarif myapp:latest
# Scan filesystem
trivy fs --security-checks vuln,config /path/to/project
# Using Docker Scout
docker scout cves myapp:latest
docker scout recommendations myapp:latest
security-context.yaml
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
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
seccompProfile:
type: RuntimeDefault
resources:
limits:
cpu: "500m"
memory: "256Mi"
requests:
cpu: "100m"
memory: "64Mi"
psa-enforce.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
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-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: app-network-policy
spec:
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: 53
secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: myapp-secrets
type: Opaque
stringData:
database-url: postgres://user:password@postgres:5432/mydb
api-key: "1234567890abcdef"
# Or use data: for base64 encoded values
data:
username: dXNlcg== # base64 encoded
pod-with-secrets.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
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-secrets
external-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: myapp-external-secret
spec:
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: key
falco-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: falco-config
namespace: falco
data:
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: WARNING
Terminal window
# Generate key pair
cosign generate-key-pair
# Sign an image
cosign sign myregistry.io/myapp:latest
# Verify signature
cosign verify myregistry.io/myapp:latest
# Verify with public key
cosign verify --key cosign.pub myregistry.io/myapp:latest
# Add annotations
cosign sign --key cosign.key --a version=1.0.0 myregistry.io/myapp:latest
policy.yaml
apiVersion: policy/v1beta1
kind: ClusterImagePolicy
metadata:
name: image-policy
spec:
images:
- glob: "ghcr.io/myorg/*"
authorities:
- key:
data: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
attestations:
- predicateType: cosign.sigstore.dev/attestation/v1
name: custom-attestation
┌─────────────────────────────────────────────────────────────────────────────┐
│ 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 │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

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