feat: add Docker skills and rules
- Add docker-compose skill with patterns (575 lines) - Add docker-swarm skill with examples (756 lines) - Add docker-security skill (684 lines) - Add docker-monitoring skill (755 lines) - Add docker.md rules (548 lines) Total: 3318 lines of Docker documentation
This commit is contained in:
685
.kilo/skills/docker-security/SKILL.md
Normal file
685
.kilo/skills/docker-security/SKILL.md
Normal file
@@ -0,0 +1,685 @@
|
||||
# Skill: Docker Security
|
||||
|
||||
## Purpose
|
||||
|
||||
Comprehensive skill for Docker container security, vulnerability scanning, secrets management, and hardening best practices.
|
||||
|
||||
## Overview
|
||||
|
||||
Container security is essential for production deployments. Use this skill when scanning for vulnerabilities, configuring security settings, managing secrets, and implementing security best practices.
|
||||
|
||||
## When to Use
|
||||
|
||||
- Security hardening containers
|
||||
- Scanning images for vulnerabilities
|
||||
- Managing secrets and credentials
|
||||
- Configuring container isolation
|
||||
- Implementing least privilege
|
||||
- Security audits
|
||||
|
||||
## Security Layers
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Container Security Layers │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 1. Host Security │
|
||||
│ - Kernel hardening │
|
||||
│ - SELinux/AppArmor │
|
||||
│ - cgroups namespace │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 2. Container Runtime Security │
|
||||
│ - User namespace │
|
||||
│ - Seccomp profiles │
|
||||
│ - Capability dropping │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 3. Image Security │
|
||||
│ - Minimal base images │
|
||||
│ - Vulnerability scanning │
|
||||
│ - No secrets in images │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 4. Network Security │
|
||||
│ - Network policies │
|
||||
│ - TLS encryption │
|
||||
│ - Ingress controls │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 5. Application Security │
|
||||
│ - Input validation │
|
||||
│ - Authentication │
|
||||
│ - Authorization │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Image Security
|
||||
|
||||
### 1. Base Image Selection
|
||||
|
||||
```dockerfile
|
||||
# ✅ Good: Minimal, specific version
|
||||
FROM node:20-alpine
|
||||
|
||||
# ✅ Better: Distroless (minimal attack surface)
|
||||
FROM gcr.io/distroless/nodejs20-debian12
|
||||
|
||||
# ❌ Bad: Large base, latest tag
|
||||
FROM node:latest
|
||||
```
|
||||
|
||||
### 2. Multi-stage Builds
|
||||
|
||||
```dockerfile
|
||||
# Build stage
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
# Runtime stage
|
||||
FROM node:20-alpine
|
||||
RUN addgroup -g 1001 appgroup && \
|
||||
adduser -u 1001 -G appgroup -D appuser
|
||||
WORKDIR /app
|
||||
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
|
||||
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
|
||||
USER appuser
|
||||
CMD ["node", "dist/index.js"]
|
||||
```
|
||||
|
||||
### 3. Vulnerability Scanning
|
||||
|
||||
```bash
|
||||
# Scan with Trivy
|
||||
trivy image myapp:latest
|
||||
|
||||
# Scan with Docker Scout
|
||||
docker scout vulnerabilities myapp:latest
|
||||
|
||||
# Scan with Grype
|
||||
grype myapp:latest
|
||||
|
||||
# CI/CD integration
|
||||
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest
|
||||
```
|
||||
|
||||
### 4. No Secrets in Images
|
||||
|
||||
```dockerfile
|
||||
# ❌ Never do this
|
||||
ENV DATABASE_PASSWORD=password123
|
||||
COPY .env ./
|
||||
|
||||
# ✅ Use runtime secrets
|
||||
# Secrets are mounted at runtime
|
||||
RUN --mount=type=secret,id=db_password \
|
||||
export DB_PASSWORD=$(cat /run/secrets/db_password)
|
||||
```
|
||||
|
||||
## Container Runtime Security
|
||||
|
||||
### 1. Non-root User
|
||||
|
||||
```dockerfile
|
||||
# Create non-root user
|
||||
FROM alpine:3.18
|
||||
RUN addgroup -g 1001 appgroup && \
|
||||
adduser -u 1001 -G appgroup -D appuser
|
||||
WORKDIR /app
|
||||
COPY --chown=appuser:appgroup . .
|
||||
USER appuser
|
||||
CMD ["./app"]
|
||||
```
|
||||
|
||||
### 2. Read-only Filesystem
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
app:
|
||||
image: myapp:latest
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /var/cache
|
||||
```
|
||||
|
||||
### 3. Capability Dropping
|
||||
|
||||
```yaml
|
||||
# Drop all capabilities
|
||||
services:
|
||||
app:
|
||||
image: myapp:latest
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN # Only needed capabilities
|
||||
- SETGID
|
||||
- SETUID
|
||||
```
|
||||
|
||||
### 4. Security Options
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
image: myapp:latest
|
||||
security_opt:
|
||||
- no-new-privileges:true # Prevent privilege escalation
|
||||
- seccomp:default.json # Seccomp profile
|
||||
- apparmor:docker-default # AppArmor profile
|
||||
```
|
||||
|
||||
### 5. Resource Limits
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
image: myapp:latest
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1'
|
||||
memory: 1G
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
memory: 512M
|
||||
pids_limit: 100 # Limit process count
|
||||
```
|
||||
|
||||
## Secrets Management
|
||||
|
||||
### 1. Docker Secrets (Swarm)
|
||||
|
||||
```bash
|
||||
# Create secret
|
||||
echo "my_password" | docker secret create db_password -
|
||||
|
||||
# Create from file
|
||||
docker secret create jwt_secret ./secrets/jwt.txt
|
||||
```
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml (Swarm)
|
||||
services:
|
||||
api:
|
||||
image: myapp:latest
|
||||
secrets:
|
||||
- db_password
|
||||
- jwt_secret
|
||||
environment:
|
||||
- DB_PASSWORD_FILE=/run/secrets/db_password
|
||||
|
||||
secrets:
|
||||
db_password:
|
||||
external: true
|
||||
jwt_secret:
|
||||
external: true
|
||||
```
|
||||
|
||||
### 2. Docker Compose Secrets (Non-Swarm)
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
api:
|
||||
image: myapp:latest
|
||||
secrets:
|
||||
- db_password
|
||||
environment:
|
||||
- DB_PASSWORD_FILE=/run/secrets/db_password
|
||||
|
||||
secrets:
|
||||
db_password:
|
||||
file: ./secrets/db_password.txt
|
||||
```
|
||||
|
||||
### 3. Environment Variables (Development)
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml (development only)
|
||||
services:
|
||||
api:
|
||||
image: myapp:latest
|
||||
env_file:
|
||||
- .env # Add .env to .gitignore!
|
||||
```
|
||||
|
||||
```bash
|
||||
# .env (NEVER COMMIT)
|
||||
DATABASE_URL=postgres://...
|
||||
JWT_SECRET=secret123
|
||||
API_KEY=key123
|
||||
```
|
||||
|
||||
### 4. Reading Secrets in Application
|
||||
|
||||
```javascript
|
||||
// Node.js
|
||||
const fs = require('fs');
|
||||
|
||||
function getSecret(secretName, envName) {
|
||||
// Try file-based secret first (Docker secrets)
|
||||
const secretPath = `/run/secrets/${secretName}`;
|
||||
if (fs.existsSync(secretPath)) {
|
||||
return fs.readFileSync(secretPath, 'utf8').trim();
|
||||
}
|
||||
// Fallback to environment variable (development)
|
||||
return process.env[envName];
|
||||
}
|
||||
|
||||
const dbPassword = getSecret('db_password', 'DB_PASSWORD');
|
||||
```
|
||||
|
||||
## Network Security
|
||||
|
||||
### 1. Network Segmentation
|
||||
|
||||
```yaml
|
||||
# Separate networks for different access levels
|
||||
networks:
|
||||
frontend:
|
||||
driver: bridge
|
||||
|
||||
backend:
|
||||
driver: bridge
|
||||
internal: true # No external access
|
||||
|
||||
database:
|
||||
driver: bridge
|
||||
internal: true
|
||||
|
||||
services:
|
||||
web:
|
||||
networks:
|
||||
- frontend
|
||||
|
||||
api:
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
|
||||
db:
|
||||
networks:
|
||||
- database
|
||||
|
||||
cache:
|
||||
networks:
|
||||
- database
|
||||
```
|
||||
|
||||
### 2. Port Exposure
|
||||
|
||||
```yaml
|
||||
# ✅ Good: Only expose necessary ports
|
||||
services:
|
||||
api:
|
||||
ports:
|
||||
- "3000:3000" # API port only
|
||||
|
||||
db:
|
||||
# No ports exposed - only accessible inside network
|
||||
networks:
|
||||
- database
|
||||
|
||||
# ❌ Bad: Exposing database to host
|
||||
services:
|
||||
db:
|
||||
ports:
|
||||
- "5432:5432" # Security risk!
|
||||
```
|
||||
|
||||
### 3. TLS Configuration
|
||||
|
||||
```yaml
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./ssl/cert.pem:/etc/nginx/ssl/cert.pem:ro
|
||||
- ./ssl/key.pem:/etc/nginx/ssl/key.pem:ro
|
||||
configs:
|
||||
- source: nginx_config
|
||||
target: /etc/nginx/nginx.conf
|
||||
|
||||
configs:
|
||||
nginx_config:
|
||||
file: ./nginx.conf
|
||||
```
|
||||
|
||||
### 4. Ingress Controls
|
||||
|
||||
```yaml
|
||||
# Limit connections
|
||||
services:
|
||||
api:
|
||||
image: myapp:latest
|
||||
ports:
|
||||
- target: 3000
|
||||
published: 3000
|
||||
mode: host # Bypass ingress mesh for performance
|
||||
deploy:
|
||||
endpoint_mode: dnsrr
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
```
|
||||
|
||||
## Security Profiles
|
||||
|
||||
### 1. Seccomp Profile
|
||||
|
||||
```json
|
||||
// default-seccomp.json
|
||||
{
|
||||
"defaultAction": "SCMP_ACT_ERRNO",
|
||||
"architectures": ["SCMP_ARCH_X86_64"],
|
||||
"syscalls": [
|
||||
{
|
||||
"names": ["read", "write", "exit", "exit_group"],
|
||||
"action": "SCMP_ACT_ALLOW"
|
||||
},
|
||||
{
|
||||
"names": ["open", "openat", "close"],
|
||||
"action": "SCMP_ACT_ALLOW"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Use custom seccomp profile
|
||||
services:
|
||||
api:
|
||||
security_opt:
|
||||
- seccomp:./seccomp.json
|
||||
```
|
||||
|
||||
### 2. AppArmor Profile
|
||||
|
||||
```bash
|
||||
# Create AppArmor profile
|
||||
cat > /etc/apparmor.d/docker-myapp <<EOF
|
||||
#include <tunables/global>
|
||||
profile docker-myapp flags=(attach_disconnected,mediate_deleted) {
|
||||
#include <abstractions/base>
|
||||
|
||||
network inet tcp,
|
||||
network inet udp,
|
||||
|
||||
/app/** r,
|
||||
/app/** w,
|
||||
|
||||
deny /** rw,
|
||||
}
|
||||
EOF
|
||||
|
||||
# Load profile
|
||||
apparmor_parser -r /etc/apparmor.d/docker-myapp
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Use AppArmor profile
|
||||
services:
|
||||
api:
|
||||
security_opt:
|
||||
- apparmor:docker-myapp
|
||||
```
|
||||
|
||||
## Security Scanning
|
||||
|
||||
### 1. Image Vulnerability Scan
|
||||
|
||||
```bash
|
||||
# Trivy scan
|
||||
trivy image --severity HIGH,CRITICAL myapp:latest
|
||||
|
||||
# Docker Scout
|
||||
docker scout vulnerabilities myapp:latest
|
||||
|
||||
# Grype
|
||||
grype myapp:latest
|
||||
|
||||
# Output JSON for CI
|
||||
trivy image --format json --output results.json myapp:latest
|
||||
```
|
||||
|
||||
### 2. Base Image Updates
|
||||
|
||||
```bash
|
||||
# Check base image for updates
|
||||
docker pull node:20-alpine
|
||||
|
||||
# Rebuild with updated base
|
||||
docker build --no-cache -t myapp:latest .
|
||||
|
||||
# Scan new image
|
||||
trivy image myapp:latest
|
||||
```
|
||||
|
||||
### 3. Dependency Audit
|
||||
|
||||
```bash
|
||||
# Node.js
|
||||
npm audit
|
||||
npm audit fix
|
||||
|
||||
# Python
|
||||
pip-audit
|
||||
|
||||
# Go
|
||||
go list -m all | nancy
|
||||
|
||||
# General
|
||||
snyk test
|
||||
```
|
||||
|
||||
### 4. Secret Detection
|
||||
|
||||
```bash
|
||||
# Scan for secrets
|
||||
gitleaks --path . --verbose
|
||||
|
||||
# Pre-commit hook
|
||||
gitleaks protect --staged
|
||||
|
||||
# Docker image
|
||||
gitleaks --image myapp:latest
|
||||
```
|
||||
|
||||
## CI/CD Security Integration
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
```yaml
|
||||
# .github/workflows/security.yml
|
||||
name: Security Scan
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
scan:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: 'myapp:${{ github.sha }}'
|
||||
format: 'table'
|
||||
exit-code: '1'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
|
||||
- name: Run Gitleaks secret scan
|
||||
uses: gitleaks/gitleaks-action@v2
|
||||
with:
|
||||
args: --path=.
|
||||
```
|
||||
|
||||
### GitLab CI
|
||||
|
||||
```yaml
|
||||
# .gitlab-ci.yml
|
||||
security_scan:
|
||||
stage: test
|
||||
image: docker:24
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- docker build -t myapp:$CI_COMMIT_SHA .
|
||||
- trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:$CI_COMMIT_SHA
|
||||
- gitleaks --path . --verbose
|
||||
```
|
||||
|
||||
## Security Checklist
|
||||
|
||||
### Dockerfile Security
|
||||
|
||||
- [ ] Using minimal base image (alpine/distroless)
|
||||
- [ ] Specific version tags, not `latest`
|
||||
- [ ] Running as non-root user
|
||||
- [ ] No secrets in image
|
||||
- [ ] `.dockerignore` includes `.env`, `.git`, `.credentials`
|
||||
- [ ] COPY instead of ADD (unless needed)
|
||||
- [ ] Multi-stage build for smaller image
|
||||
- [ ] HEALTHCHECK defined
|
||||
|
||||
### Runtime Security
|
||||
|
||||
- [ ] Read-only filesystem
|
||||
- [ ] Capabilities dropped
|
||||
- [ ] No new privileges
|
||||
- [ ] Resource limits set
|
||||
- [ ] User namespace enabled (if available)
|
||||
- [ ] Seccomp/AppArmor profiles applied
|
||||
|
||||
### Network Security
|
||||
|
||||
- [ ] Only necessary ports exposed
|
||||
- [ ] Internal networks for sensitive services
|
||||
- [ ] TLS for external communication
|
||||
- [ ] Network segmentation
|
||||
|
||||
### Secrets Management
|
||||
|
||||
- [ ] No secrets in images
|
||||
- [ ] Using Docker secrets or external vault
|
||||
- [ ] `.env` files gitignored
|
||||
- [ ] Secret rotation implemented
|
||||
|
||||
### CI/CD Security
|
||||
|
||||
- [ ] Vulnerability scanning in pipeline
|
||||
- [ ] Secret detection pre-commit
|
||||
- [ ] Dependency audit automated
|
||||
- [ ] Base images updated regularly
|
||||
|
||||
## Remediation Priority
|
||||
|
||||
| Severity | Priority | Timeline |
|
||||
|----------|----------|----------|
|
||||
| Critical | P0 | Immediately (24h) |
|
||||
| High | P1 | Within 7 days |
|
||||
| Medium | P2 | Within 30 days |
|
||||
| Low | P3 | Next release |
|
||||
|
||||
## Security Tools
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| Trivy | Image vulnerability scanning |
|
||||
| Docker Scout | Docker's built-in scanner |
|
||||
| Grype | Vulnerability scanner |
|
||||
| Gitleaks | Secret detection |
|
||||
| Snyk | Dependency scanning |
|
||||
| Falco | Runtime security monitoring |
|
||||
| Anchore | Container security analysis |
|
||||
| Clair | Open-source vulnerability scanner |
|
||||
|
||||
## Common Vulnerabilities
|
||||
|
||||
### CVE Examples
|
||||
|
||||
```yaml
|
||||
# Check for specific CVE
|
||||
trivy image --vulnerabilities CVE-2021-44228 myapp:latest
|
||||
|
||||
# Ignore specific CVE (use carefully)
|
||||
trivy image --ignorefile .trivyignore myapp:latest
|
||||
|
||||
# .trivyignore
|
||||
CVE-2021-12345 # Known and accepted
|
||||
```
|
||||
|
||||
### Log4j Example (CVE-2021-44228)
|
||||
|
||||
```bash
|
||||
# Check for vulnerable versions
|
||||
docker images --format '{{.Repository}}:{{.Tag}}' | xargs -I {} \
|
||||
trivy image --vulnerabilities CVE-2021-44228 {}
|
||||
|
||||
# Update and rebuild
|
||||
FROM node:20-alpine
|
||||
# Ensure no vulnerable log4j dependency
|
||||
RUN npm audit fix
|
||||
```
|
||||
|
||||
## Incident Response
|
||||
|
||||
### Security Breach Steps
|
||||
|
||||
1. **Isolate**
|
||||
```bash
|
||||
# Stop container
|
||||
docker stop <container_id>
|
||||
|
||||
# Remove from network
|
||||
docker network disconnect app-network <container_id>
|
||||
```
|
||||
|
||||
2. **Preserve Evidence**
|
||||
```bash
|
||||
# Save container state
|
||||
docker commit <container_id> incident-container
|
||||
|
||||
# Export logs
|
||||
docker logs <container_id> > incident-logs.txt
|
||||
docker export <container_id> > incident-container.tar
|
||||
```
|
||||
|
||||
3. **Analyze**
|
||||
```bash
|
||||
# Inspect container
|
||||
docker inspect <container_id>
|
||||
|
||||
# Check image
|
||||
trivy image <image_name>
|
||||
|
||||
# Review process history
|
||||
docker history <image_name>
|
||||
```
|
||||
|
||||
4. **Remediate**
|
||||
```bash
|
||||
# Update base image
|
||||
docker pull node:20-alpine
|
||||
|
||||
# Rebuild
|
||||
docker build --no-cache -t myapp:fixed .
|
||||
|
||||
# Scan
|
||||
trivy image myapp:fixed
|
||||
```
|
||||
|
||||
## Related Skills
|
||||
|
||||
| Skill | Purpose |
|
||||
|-------|---------|
|
||||
| `docker-compose` | Local development setup |
|
||||
| `docker-swarm` | Production orchestration |
|
||||
| `docker-monitoring` | Security monitoring |
|
||||
| `docker-networking` | Network security |
|
||||
Reference in New Issue
Block a user