Files
microdao-daarion/security/hardening/docker.md
Apple cba2ff47f3 📚 docs(security): Add comprehensive Security chapter
## New Security Documentation Structure

/security/
├── README.md                    # Security overview & contacts
├── forensics-checklist.md       # Incident investigation guide
├── persistence-scan.sh          # Quick persistence detector
├── runtime-detector.sh          # Mining/suspicious process detector
└── hardening/
    ├── docker.md                # Docker security baseline
    ├── kubernetes.md            # K8s policies (future reference)
    └── cloud.md                 # Hetzner-specific hardening

## Key Components

### Forensics Checklist
- Process analysis commands
- Persistence mechanism detection
- Network connection analysis
- File system inspection
- Authentication audit
- Decision matrix for threat response

### Scripts
- persistence-scan.sh: Cron, systemd, executables, SSH keys
- runtime-detector.sh: Mining process detection with --kill option

### Hardening Guides
- Docker: Secure compose template, Dockerfile best practices
- Kubernetes: NetworkPolicy, PodSecurityStandard, Falco rules
- Cloud: Egress firewall, SSH hardening, fail2ban, monitoring

## Post-Incident Documentation
Based on lessons learned from Incidents #1 and #2 (Jan 2026)

Co-authored-by: Cursor Agent <agent@cursor.sh>
2026-01-09 02:08:13 -08:00

311 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🐳 Docker Security Hardening — DAARION
**Версія:** 1.0.0
**Принцип:** Майнінг можливий тільки там, де дозволений **outbound + CPU без контролю**
---
## 📋 Security Checklist
### Must-Have (Обов'язково)
| Налаштування | docker-compose | Пояснення |
|--------------|----------------|-----------|
| Read-only filesystem | `read_only: true` | Запобігає запису malware |
| Drop capabilities | `cap_drop: [ALL]` | Мінімальні привілеї |
| No new privileges | `security_opt: [no-new-privileges:true]` | Блокує privilege escalation |
| CPU limit | `cpus: '1.0'` | Обмежує crypto mining |
| Memory limit | `memory: 512M` | Запобігає DoS |
| Non-root user | `user: "1001:1001"` | Не root в контейнері |
| No privileged | `privileged: false` | Завжди! |
---
## 🛡️ Secure docker-compose Template
```yaml
version: '3.8'
services:
secure-service:
image: your-image:tag
container_name: secure-service
# ============================================
# SECURITY HARDENING
# ============================================
# 1. Restart policy (use "no" until verified)
restart: "no" # Change to "unless-stopped" after verification
# 2. Network binding (localhost only for internal services)
ports:
- "127.0.0.1:8080:8080"
# 3. Read-only root filesystem
read_only: true
# 4. Temporary filesystems (for apps that need write)
tmpfs:
- /tmp:size=64M,mode=1777
- /app/cache:size=128M,mode=1777
# 5. Drop ALL capabilities
cap_drop:
- ALL
# 6. Add only what's needed (rarely needed)
# cap_add:
# - NET_BIND_SERVICE # Only if port < 1024
# 7. Security options
security_opt:
- no-new-privileges:true
# 8. Resource limits
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
# 9. Process limits
pids_limit: 100
# 10. Disable privileged mode
privileged: false
# 11. Non-root user
user: "1001:1001"
# 12. Health check
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
# 13. Logging limits
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# 14. Labels for audit
labels:
- "security.hardened=true"
- "security.reviewed=2026-01-09"
networks:
default:
driver: bridge
driver_opts:
com.docker.network.bridge.enable_icc: "false" # Disable inter-container communication
```
---
## 🔧 Secure Dockerfile Template
```dockerfile
# ============================================
# Stage 1: Builder
# ============================================
FROM node:20-alpine AS builder
WORKDIR /app
# Copy only package files first (cache optimization)
COPY package*.json ./
RUN npm ci --only=production --ignore-scripts
COPY . .
RUN npm run build
# ============================================
# Stage 2: Production (minimal)
# ============================================
FROM node:20-alpine AS production
# Security: Create non-root user
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup
WORKDIR /app
# Security: Remove unnecessary tools
RUN apk del --purge wget curl busybox-extras && \
rm -rf /var/cache/apk/* /tmp/* /var/tmp/*
# Copy from builder
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
# Security: Restrictive permissions
RUN chmod -R 500 /app && \
chmod 400 /app/package.json
# Switch to non-root
USER appuser
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD node -e "require('http').get('http://localhost:8080/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
EXPOSE 8080
CMD ["node", "dist/server.js"]
```
---
## 🚫 Anti-Patterns (НЕ робіть)
```yaml
# ❌ NEVER DO THIS:
services:
insecure:
privileged: true # ❌ Full host access
ports:
- "8080:8080" # ❌ Binds to 0.0.0.0 (public)
volumes:
- /:/host # ❌ Full host filesystem
- /var/run/docker.sock:/var/run/docker.sock # ❌ Docker escape
cap_add:
- SYS_ADMIN # ❌ Too powerful
- NET_ADMIN # ❌ Network manipulation
restart: unless-stopped # ❌ Without verification
# No resource limits # ❌ Crypto mining possible
# No read_only # ❌ Malware can persist
# No user specification # ❌ Runs as root
```
---
## 📊 Security Scanning
### Pre-deployment scan
```bash
# Install Trivy
brew install trivy # macOS
apt install trivy # Ubuntu
# Scan image for vulnerabilities
trivy image --severity HIGH,CRITICAL your-image:tag
# Scan with detailed output
trivy image --format json -o scan-report.json your-image:tag
# Scan Dockerfile
trivy config Dockerfile
```
### CI/CD Integration
```yaml
# .github/workflows/security-scan.yml
name: Security Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build image
run: docker build -t app:${{ github.sha }} .
- name: Run Trivy scan
uses: aquasecurity/trivy-action@master
with:
image-ref: 'app:${{ github.sha }}'
format: 'table'
exit-code: '1'
severity: 'HIGH,CRITICAL'
```
---
## 🔍 Runtime Monitoring
### Container inspection
```bash
# Check container security settings
docker inspect --format='
Privileged: {{.HostConfig.Privileged}}
ReadonlyRootfs: {{.HostConfig.ReadonlyRootfs}}
User: {{.Config.User}}
CapDrop: {{.HostConfig.CapDrop}}
CapAdd: {{.HostConfig.CapAdd}}
' container_name
```
### Resource monitoring
```bash
# Real-time stats
docker stats container_name
# CPU limit check
docker inspect --format='{{.HostConfig.NanoCpus}}' container_name
# Memory limit check
docker inspect --format='{{.HostConfig.Memory}}' container_name
```
---
## 📝 DAARION-specific Rules
### Services that MUST have hardening:
| Service | Priority | Notes |
|---------|----------|-------|
| daarion-web | 🔴 Critical | Post-incident, see Dockerfile.secure |
| dagi-gateway | 🔴 Critical | Public-facing |
| dagi-router | 🟡 High | Core routing |
| All others | 🟡 High | Apply baseline |
### Network rules:
```yaml
# Internal services: bind to localhost
ports:
- "127.0.0.1:PORT:PORT"
# Public services: use Nginx reverse proxy
# Never expose directly to 0.0.0.0
```
---
## ✅ Verification Checklist
Before deploying any container:
- [ ] Image scanned with Trivy (no HIGH/CRITICAL)
- [ ] `read_only: true` set
- [ ] `cap_drop: [ALL]` set
- [ ] `security_opt: [no-new-privileges:true]` set
- [ ] CPU/memory limits set
- [ ] Non-root user configured
- [ ] Health check defined
- [ ] Restart policy is "no" for new deployments
- [ ] Port bound to 127.0.0.1 (unless public)
- [ ] No privileged mode
- [ ] No dangerous volume mounts