Static Security Analysis¶
Dockerfile Security Analysis¶
Key Security Issues to Look For¶
1. Running as Root User¶
# ❌ BAD - Running as root
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y nginx
CMD ["nginx", "-g", "daemon off;"]
# ✅ GOOD - Non-root user
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y nginx
RUN useradd -r -s /bin/false nginx-user
USER nginx-user
CMD ["nginx", "-g", "daemon off;"]
2. Secrets in Image Layers¶
# ❌ BAD - Hardcoded secrets
FROM node:14
ENV API_KEY=sk-1234567890abcdef
ENV DATABASE_PASSWORD=super-secret-password
COPY . /app
# ✅ GOOD - No secrets in Dockerfile
FROM node:14
# Secrets should be passed at runtime via K8s secrets
COPY . /app
3. Unnecessary Packages and Attack Surface¶
# ❌ BAD - Full OS with unnecessary packages
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y \
curl wget git vim nano ssh openssh-server
# ✅ GOOD - Minimal base image
FROM node:14-alpine
# Only install what's needed
RUN apk add --no-cache dumb-init
4. Improper File Permissions¶
# ❌ BAD - World-writable files
FROM alpine
COPY --chmod=777 app.sh /usr/local/bin/
COPY --chmod=666 config.json /etc/
# ✅ GOOD - Restrictive permissions
FROM alpine
COPY --chmod=755 app.sh /usr/local/bin/
COPY --chmod=644 config.json /etc/
5. Using Latest Tags¶
# ❌ BAD - Unpredictable base image
FROM node:latest
FROM ubuntu:latest
# ✅ GOOD - Specific versions
FROM node:14.21.3-alpine
FROM ubuntu:20.04
Kubernetes Manifest Security Analysis¶
Key Security Issues to Look For¶
1. Missing Security Context¶
# ❌ BAD - No security context
apiVersion: apps/v1
kind: Deployment
metadata:
name: insecure-app
spec:
template:
spec:
containers:
- name: app
image: nginx:1.20
# ✅ GOOD - Proper security context
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: app
image: nginx:1.20
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop:
- ALL
2. Privileged Containers¶
# ❌ BAD - Privileged container
containers:
- name: dangerous-app
image: app:1.0
securityContext:
privileged: true
# ✅ GOOD - Non-privileged with specific capabilities
containers:
- name: safe-app
image: app:1.0
securityContext:
privileged: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
3. Missing Resource Limits¶
# ❌ BAD - No resource limits
containers:
- name: resource-hog
image: app:1.0
# ✅ GOOD - Resource limits set
containers:
- name: limited-app
image: app:1.0
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
4. Secrets in Environment Variables¶
# ❌ BAD - Secrets in plain text env vars
containers:
- name: app
image: myapp:1.0
env:
- name: DB_PASSWORD
value: "super-secret-password"
- name: API_KEY
value: "sk-1234567890"
# ✅ GOOD - Using Kubernetes secrets
containers:
- name: app
image: myapp:1.0
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
- name: API_KEY
valueFrom:
secretKeyRef:
name: api-secret
key: api-key
5. Network Policies Missing¶
# ❌ BAD - No network restrictions
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
# No NetworkPolicy defined
# ✅ GOOD - With NetworkPolicy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-app-netpol
spec:
podSelector:
matchLabels:
app: web-app
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Tools for Static Analysis¶
1. Trivy (Recommended for exams)¶
# Scan Dockerfile
trivy config Dockerfile
# Scan Kubernetes manifests
trivy config k8s-manifests/
# Scan specific manifest
trivy config deployment.yaml
2. Checkov¶
# Install
pip install checkov
# Scan Dockerfile
checkov -f Dockerfile
# Scan Kubernetes manifests
checkov -d k8s-manifests/
3. Kubesec¶
# Online tool
curl -sSX POST --data-binary @deployment.yaml https://v2.kubesec.io/scan
# Local installation
kubesec scan deployment.yaml
4. Kube-score¶
# Install
kubectl krew install score
# Analyze manifest
kubectl score deployment.yaml
Common Exam Questions¶
Question Type 1: “Identify Security Issues”¶
Prompt: “Analyze the following Dockerfile and identify at least 3 security vulnerabilities”
Approach: 1. Look for root user usage 2. Check for hardcoded secrets 3. Verify base image tags 4. Check file permissions 5. Look for unnecessary packages
Question Type 2: “Fix Security Issues”¶
Prompt: “Fix the security issues in the following Kubernetes deployment manifest”
Approach: 1. Add securityContext 2. Set resource limits 3. Use secrets instead of plain env vars 4. Ensure non-root execution 5. Add readiness/liveness probes
Question Type 3: “Use Tool for Analysis”¶
Prompt: “Use trivy to scan the provided manifest and fix the HIGH severity issues”
Approach: 1. Run trivy scan 2. Identify HIGH severity findings 3. Apply fixes systematically 4. Re-scan to verify
Step-by-Step Solutions¶
Scenario 1: Dockerfile Analysis¶
Given Dockerfile:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl wget git
ENV SECRET_KEY=abc123
COPY app.py /app/
RUN chmod 777 /app/app.py
CMD ["python", "/app/app.py"]
Step 1: Identify Issues
# Run trivy scan
trivy config Dockerfile
Step 2: Issues Found
- Using latest
tag (unpredictable)
- Running as root user
- Hardcoded secret in ENV
- Overly permissive file permissions (777)
- Unnecessary packages installed
Step 3: Fixed Dockerfile
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3 && \
apt-get clean && rm -rf /var/lib/apt/lists/*
RUN useradd -r -s /bin/false appuser
COPY --chown=appuser:appuser --chmod=644 app.py /app/
USER appuser
CMD ["python3", "/app/app.py"]
Scenario 2: Kubernetes Manifest Analysis¶
Given Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 1
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web
image: nginx:latest
env:
- name: DB_PASSWORD
value: "secretpassword"
Step 1: Scan with Tools
trivy config deployment.yaml
kubesec scan deployment.yaml
Step 2: Issues Identified - No security context - Using latest tag - Secret in plain text env var - No resource limits - Missing health checks
Step 3: Fixed Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 1
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: web
image: nginx:1.21.6-alpine
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop:
- ALL
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
volumeMounts:
- name: tmp-volume
mountPath: /tmp
- name: var-cache
mountPath: /var/cache/nginx
volumes:
- name: tmp-volume
emptyDir: {}
- name: var-cache
emptyDir: {}
Remediation Examples¶
Security Context Best Practices¶
# Complete security context example
securityContext:
# Pod-level
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
securityContext:
# Container-level
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE # Only if needed
Resource Management¶
resources:
limits:
memory: "512Mi"
cpu: "500m"
ephemeral-storage: "1Gi"
requests:
memory: "256Mi"
cpu: "250m"
ephemeral-storage: "500Mi"
Secrets Management¶
# Create secret first
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
api-key: <base64-encoded-value>
db-password: <base64-encoded-value>
# Reference in deployment
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: app-secrets
key: api-key
Exam Tips¶
Time Management¶
- Quick Scan First: Use automated tools to identify obvious issues
- Prioritize: Focus on HIGH/CRITICAL severity issues first
- Systematic Approach: Check each category methodically
Common Commands to Remember¶
# Trivy scanning
trivy config .
trivy image nginx:latest
# Kubesec analysis
kubesec scan pod.yaml
# Kubectl dry-run for validation
kubectl apply --dry-run=client -f manifest.yaml
# Check security context
kubectl get pod -o jsonpath='{.spec.securityContext}'
Checklist for Quick Review¶
- [ ] Non-root user execution
- [ ] No hardcoded secrets
- [ ] Specific image tags (not latest)
- [ ] Resource limits set
- [ ] Security context configured
- [ ] Minimal attack surface
- [ ] Health checks present
- [ ] Network policies defined
Practice Exercises¶
Exercise 1: Fix This Dockerfile¶
FROM node:latest
RUN apt-get update && apt-get install -y vim curl wget git
ENV JWT_SECRET=mysecretkey123
COPY . /app
WORKDIR /app
RUN npm install
EXPOSE 3000
CMD ["npm", "start"]
Exercise 2: Secure This Deployment¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
template:
spec:
containers:
- name: api
image: myapi:latest
env:
- name: DATABASE_URL
value: "postgres://user:password@db:5432/mydb"
ports:
- containerPort: 8080
Solutions available upon request or can be worked through using the guidelines above.