docs(02): create phase 2 plans (3 plans)
This commit is contained in:
504
.planning/phases/02-lab-01-iam-sicurezza/02-03-PLAN.md
Normal file
504
.planning/phases/02-lab-01-iam-sicurezza/02-03-PLAN.md
Normal file
@@ -0,0 +1,504 @@
|
||||
---
|
||||
phase: 02-lab-01-iam-sicurezza
|
||||
plan: 03
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: [02-01, 02-02]
|
||||
files_modified:
|
||||
- labs/lab-01-iam/Dockerfile
|
||||
- labs/lab-01-iam/docker-compose.yml
|
||||
- labs/lab-01-iam/tests/04-verify-infrastructure.sh
|
||||
autonomous: true
|
||||
requirements: [LAB-01, INF-01, TEST-01]
|
||||
user_setup: []
|
||||
must_haves:
|
||||
truths:
|
||||
- "docker-compose.yml defines services with non-root user directive (INF-01)"
|
||||
- "Dockerfile creates non-root user and switches before CMD (INF-01)"
|
||||
- "Test scripts validate non-root execution (INF-01)"
|
||||
- "Infrastructure follows test-driven approach (GREEN phase of TDI)"
|
||||
artifacts:
|
||||
- path: "labs/lab-01-iam/Dockerfile"
|
||||
provides: "Non-root container image definition"
|
||||
min_lines: 15
|
||||
- path: "labs/lab-01-iam/docker-compose.yml"
|
||||
provides: "Service orchestration with user directive"
|
||||
min_lines: 20
|
||||
- path: "labs/lab-01-iam/tests/04-verify-infrastructure.sh"
|
||||
provides: "Infrastructure verification script"
|
||||
min_lines: 25
|
||||
key_links:
|
||||
- from: "docker-compose.yml"
|
||||
to: "Dockerfile"
|
||||
via: "build context and image reference"
|
||||
pattern: "build:.*\\..*Dockerfile"
|
||||
- from: "tests/04-verify-infrastructure.sh"
|
||||
to: "docker-compose.yml, Dockerfile"
|
||||
via: "Infrastructure validation"
|
||||
pattern: "docker-compose.*-f.*docker-compose.yml"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Create Docker infrastructure (Dockerfile and docker-compose.yml) that implements non-root container execution (INF-01). Following TDD methodology, infrastructure is created AFTER tests exist, and tests should now pass (GREEN phase).
|
||||
|
||||
Purpose: Implement minimum infrastructure to satisfy LAB-01 and INF-01 requirements while ensuring all containers run as non-root.
|
||||
Output: Dockerfile with non-root user, docker-compose.yml with user directive, and infrastructure verification test.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/home/luca/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@/home/luca/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/02-lab-01-iam-sicurezza/02-RESEARCH.md
|
||||
@.planning/phases/02-lab-01-iam-sicurezza/02-VALIDATION.md
|
||||
@CLAUDE.md
|
||||
|
||||
# From RESEARCH.md - Non-Root Container Pattern
|
||||
|
||||
```dockerfile
|
||||
# Source: Docker security best practices
|
||||
FROM alpine:3.19
|
||||
|
||||
# Create non-root user with specific UID/GID for consistency
|
||||
RUN addgroup -g 1000 appgroup && \
|
||||
adduser -D -u 1000 -G appgroup appuser
|
||||
|
||||
# Switch to non-root user BEFORE any operations
|
||||
USER appuser
|
||||
|
||||
# Verify non-root execution
|
||||
CMD ["sh", "-c", "echo 'Running as:' && whoami"]
|
||||
```
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml with user directive
|
||||
services:
|
||||
test-container:
|
||||
image: alpine:3.19
|
||||
user: "1000:1000" # UID:GID for non-root
|
||||
command: ["sh", "-c", "whoami && sleep 3600"]
|
||||
```
|
||||
|
||||
# From RESEARCH.md - Verification Methods
|
||||
|
||||
```bash
|
||||
# Method 1: Execute whoami inside container
|
||||
docker exec <container_name> whoami
|
||||
# Expected output: appuser (NOT root)
|
||||
|
||||
# Method 2: Inspect container configuration
|
||||
docker inspect <container_name> --format='{{.State.User}}'
|
||||
|
||||
# Method 3: Check process on host
|
||||
docker top <container_name>
|
||||
# Look at USER column - should show UID (e.g., 1000), NOT 0 (root)
|
||||
```
|
||||
|
||||
# Common Pitfalls to Avoid
|
||||
|
||||
- Running containers as root (violates INF-01)
|
||||
- Using `--privileged` flag (defeats container isolation)
|
||||
- Skipping verification of non-root execution
|
||||
- Forgetting `user:` directive in docker-compose.yml
|
||||
|
||||
# TDD Methodology - GREEN Phase
|
||||
|
||||
Now that tests exist (Wave 0), implement MINIMUM infrastructure to make them pass:
|
||||
1. docker-compose.yml with `user:` directive
|
||||
2. Dockerfile with `USER` directive
|
||||
3. Run tests to verify GREEN phase
|
||||
4. Do NOT over-engineer - minimum to pass tests is sufficient
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Create Dockerfile with non-root user</name>
|
||||
<files>labs/lab-01-iam/Dockerfile</files>
|
||||
<behavior>
|
||||
- Base image: alpine:3.19 (small, secure)
|
||||
- Creates non-root user with UID/GID 1000
|
||||
- Switches to non-root user with USER directive
|
||||
- CMD demonstrates non-root execution with whoami
|
||||
- Follows INF-01 requirement (no root execution)
|
||||
</behavior>
|
||||
<action>
|
||||
Create Dockerfile that implements non-root container execution:
|
||||
|
||||
```dockerfile
|
||||
# Lab 01 - IAM & Sicurezza
|
||||
# Dockerfile per container non-root (INF-01 requirement)
|
||||
#
|
||||
# Questo Dockerfile dimostra come creare un container che gira
|
||||
# come utente non-root, seguendo il principio del minimo privilegio.
|
||||
|
||||
FROM alpine:3.19
|
||||
|
||||
# Label per metadata
|
||||
LABEL maintainer="Lab 01 - IAM & Sicurezza"
|
||||
LABEL description="Container non-root per dimostrare permessi IAM"
|
||||
LABEL version="1.0"
|
||||
|
||||
# Crea utente non-root con UID/GID specifici per consistenza
|
||||
# UID 1000 e GID 1000 sono comuni per utenti non-root
|
||||
RUN addgroup -g 1000 labuser && \
|
||||
adduser -D -u 1000 -G labuser labuser
|
||||
|
||||
# Imposta la working directory (creata con adduser -D)
|
||||
WORKDIR /home/labuser
|
||||
|
||||
# Crea un file semplice per verificare i permessi di scrittura
|
||||
RUN echo "Questo file e stato creato durante la build" > /home/labuser/test.txt && \
|
||||
chown labuser:labuser /home/labuser/test.txt
|
||||
|
||||
# PASSA A UTENTE NON-ROOT PRIMA DI QUALSIASI OPERAZIONE
|
||||
# Questo e il punto chiave per INF-01: nessun processo gira come root
|
||||
USER labuser
|
||||
|
||||
# Verifica che il container gira come utente non-root
|
||||
CMD ["sh", "-c", "\
|
||||
echo '========================================' && \
|
||||
echo 'Lab 01 - IAM & Sicurezza' && \
|
||||
echo 'Container non-root verification (INF-01)' && \
|
||||
echo '========================================' && \
|
||||
echo '' && \
|
||||
echo 'Utente corrente:' && \
|
||||
whoami && \
|
||||
echo '' && \
|
||||
echo 'UID:' && \
|
||||
id -u && \
|
||||
echo '' && \
|
||||
echo 'GID:' && \
|
||||
id -g && \
|
||||
echo '' && \
|
||||
echo 'Gruppi:' && \
|
||||
groups && \
|
||||
echo '' && \
|
||||
echo 'Home directory:' && \
|
||||
pwd && \
|
||||
echo '' && \
|
||||
echo 'Contenuto di test.txt (permessi scrittura):' && \
|
||||
cat test.txt && \
|
||||
echo '' && \
|
||||
echo '========================================' && \
|
||||
echo 'Se vedi \"labuser\" sopra, INF-01 e soddisfatto!' && \
|
||||
echo '========================================' && \
|
||||
echo '' && \
|
||||
echo 'Container in esecuzione. Premi Ctrl-C per uscire.' && \
|
||||
sleep 3600 \
|
||||
"]
|
||||
```
|
||||
|
||||
Key implementation points:
|
||||
- Base image Alpine 3.19 (minimal, secure)
|
||||
- Creates `labuser` with UID/GID 1000
|
||||
- USER directive switches to non-root BEFORE CMD
|
||||
- CMD demonstrates and verifies non-root execution
|
||||
- Follows INF-01 requirement strictly
|
||||
- Labels for metadata and documentation
|
||||
- Working directory set to user's home
|
||||
- Test file to verify write permissions
|
||||
|
||||
TDD Context: This is the GREEN phase - tests already exist (from Wave 0), this Dockerfile should make those tests pass.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd labs/lab-01-iam && docker build -t lab01-non-root . && docker run --rm lab01-non-root | grep -q "labuser" && echo "PASS: Container runs as non-root" || echo "FAIL: Container not running as labuser"</automated>
|
||||
</verify>
|
||||
<done>Dockerfile creates non-root container verified by whoami output</done>
|
||||
</task>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 2: Create docker-compose.yml with user directive</name>
|
||||
<files>labs/lab-01-iam/docker-compose.yml</files>
|
||||
<behavior>
|
||||
- Defines service with local image build
|
||||
- Specifies user directive (1000:1000) for non-root execution
|
||||
- Includes container_name for easy reference
|
||||
- Follows INF-01 requirement (no root)
|
||||
- Enables test scripts to verify configuration
|
||||
</behavior>
|
||||
<action>
|
||||
Create docker-compose.yml that enforces non-root execution:
|
||||
|
||||
```yaml
|
||||
# Lab 01 - IAM & Sicurezza
|
||||
# Docker Compose configuration per container non-root
|
||||
#
|
||||
# Questo file definisce i servizi per il lab, assicurandosi che
|
||||
# TUTTI i container girino come utente non-root (INF-01).
|
||||
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
# Container di test per verificare l'esecuzione non-root
|
||||
lab01-test:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: lab01-non-root:latest
|
||||
container_name: lab01-iam-test
|
||||
# CRITICO: user directive assicura esecuzione non-root (INF-01)
|
||||
# Format: UID:GID
|
||||
# 1000:1000 corrisponde all'utente labuser creato nel Dockerfile
|
||||
user: "1000:1000"
|
||||
# Non esponiamo porte (non necessario per questo lab)
|
||||
# Le porte private non devono essere esposte sull'host (best practice)
|
||||
restart: unless-stopped
|
||||
# Nessun volume mount necessario per questo lab semplice
|
||||
# I volumi saranno introdotti nei lab successivi
|
||||
healthcheck:
|
||||
# Healthcheck per verificare che il container sia sano
|
||||
test: ["CMD", "sh", "-c", "whoami | grep -q labuser"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 5s
|
||||
|
||||
# Nessuna rete definita - useremo la default bridge network
|
||||
# Le reti custom isolate saranno introdotte nel Lab 02 (Network & VPC)
|
||||
|
||||
# Nessun volume definito - i volumi saranno introdotti nel Lab 04 (Storage & S3)
|
||||
```
|
||||
|
||||
Key implementation points:
|
||||
- Service definition with local build context
|
||||
- `user: "1000:1000"` directive enforces non-root execution
|
||||
- Container name matches test expectations
|
||||
- Healthcheck verifies non-root user
|
||||
- Comments explain why no volumes/networks (future labs)
|
||||
- Follows docker-compose V3.8 syntax
|
||||
- No ports exposed (security best practice)
|
||||
|
||||
TDD Context: Tests from Wave 0 check for user directive - this configuration should satisfy those tests.
|
||||
|
||||
INF-01 Compliance:
|
||||
- User directive explicitly set
|
||||
- Healthcheck verifies non-root execution
|
||||
- No possibility of root execution
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd labs/lab-01-iam && docker-compose config > /dev/null 2>&1 && echo "PASS: docker-compose.yml is valid" || echo "FAIL: docker-compose.yml has errors"</automated>
|
||||
</verify>
|
||||
<done>docker-compose.yml defines service with non-root user directive</done>
|
||||
</task>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 3: Create infrastructure verification script</name>
|
||||
<files>labs/lab-01-iam/tests/04-verify-infrastructure.sh</files>
|
||||
<behavior>
|
||||
- Test 1: docker-compose.yml is valid YAML
|
||||
- Test 2: Dockerfile builds successfully
|
||||
- Test 3: Service has user directive set
|
||||
- Test 4: Built container runs as non-root
|
||||
- Test 5: All INF-01 requirements satisfied
|
||||
</behavior>
|
||||
<action>
|
||||
Create infrastructure verification script (TDD GREEN phase verification):
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Infrastructure Verification: Lab 01
|
||||
# Verifies that docker-compose.yml and Dockerfile satisfy all requirements
|
||||
# This is the GREEN phase check - tests should pass after infrastructure implementation
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$TEST_DIR/../.." && pwd)"
|
||||
LAB_DIR="$PROJECT_ROOT/labs/lab-01-iam"
|
||||
|
||||
cd "$LAB_DIR"
|
||||
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo -e "${BLUE}Lab 01 Infrastructure Verification${NC}"
|
||||
echo -e "${BLUE}GREEN Phase Check${NC}"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo ""
|
||||
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
|
||||
# Test 1: docker-compose.yml is valid
|
||||
echo -e "${BLUE}[1/6] Checking docker-compose.yml syntax...${NC}"
|
||||
if docker-compose config >/dev/null 2>&1; then
|
||||
echo -e " ${GREEN}✓${NC} docker-compose.yml is valid YAML"
|
||||
((pass_count++))
|
||||
else
|
||||
echo -e " ${RED}✗${NC} docker-compose.yml has syntax errors"
|
||||
((fail_count++))
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Test 2: Dockerfile exists and is readable
|
||||
echo -e "${BLUE}[2/6] Checking Dockerfile...${NC}"
|
||||
if [ -f "Dockerfile" ]; then
|
||||
echo -e " ${GREEN}✓${NC} Dockerfile exists"
|
||||
|
||||
# Check for USER directive
|
||||
if grep -q "^USER" Dockerfile; then
|
||||
user_line=$(grep "^USER" Dockerfile)
|
||||
echo -e " ${GREEN}✓${NC} USER directive found: $user_line"
|
||||
((pass_count++))
|
||||
else
|
||||
echo -e " ${RED}✗${NC} No USER directive found in Dockerfile"
|
||||
((fail_count++))
|
||||
fi
|
||||
else
|
||||
echo -e " ${RED}✗${NC} Dockerfile not found"
|
||||
((fail_count++))
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Test 3: docker-compose.yml has user directive
|
||||
echo -e "${BLUE}[3/6] Checking docker-compose.yml user directive...${NC}"
|
||||
if grep -q "user:" docker-compose.yml; then
|
||||
user_value=$(grep "user:" docker-compose.yml | head -1 | sed 's/.*user: *//' | tr -d '"')
|
||||
echo -e " ${GREEN}✓${NC} user directive found: $user_value"
|
||||
|
||||
# Verify it's not root (0:0)
|
||||
if [[ "$user_value" != *"0:0"* ]] && [[ "$user_value" != *"root"* ]]; then
|
||||
echo -e " ${GREEN}✓${NC} User is not root (INF-01 compliant)"
|
||||
((pass_count++))
|
||||
else
|
||||
echo -e " ${RED}✗${NC} User is root (INF-01 violation)"
|
||||
((fail_count++))
|
||||
fi
|
||||
else
|
||||
echo -e " ${RED}✗${NC} No user directive in docker-compose.yml"
|
||||
((fail_count++))
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Test 4: Build Docker image
|
||||
echo -e "${BLUE}[4/6] Building Docker image...${NC}"
|
||||
if docker build -t lab01-non-root -q Dockerfile >/dev/null 2>&1; then
|
||||
echo -e " ${GREEN}✓${NC} Docker image built successfully"
|
||||
((pass_count++))
|
||||
else
|
||||
echo -e " ${RED}✗${NC} Docker image build failed"
|
||||
((fail_count++))
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Test 5: Verify container runs as non-root
|
||||
echo -e "${BLUE}[5/6] Verifying non-root execution...${NC}"
|
||||
if docker run --rm lab01-non-root whoami 2>/dev/null | grep -q "labuser"; then
|
||||
echo -e " ${GREEN}✓${NC} Container runs as non-root user (labuser)"
|
||||
((pass_count++))
|
||||
else
|
||||
echo -e " ${RED}✗${NC} Container not running as labuser"
|
||||
((fail_count++))
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Test 6: Verify docker-compose service
|
||||
echo -e "${BLUE}[6/6] Verifying docker-compose service...${NC}"
|
||||
# Start container in detached mode
|
||||
if docker-compose up -d >/dev/null 2>&1; then
|
||||
echo -e " ${GREEN}✓${NC} docker-compose service started"
|
||||
|
||||
# Wait for container to be ready
|
||||
sleep 3
|
||||
|
||||
# Check container is running
|
||||
if docker ps --format "{{.Names}}" | grep -q "^lab01-iam-test$"; then
|
||||
echo -e " ${GREEN}✓${NC} Container is running"
|
||||
|
||||
# Verify user
|
||||
actual_user=$(docker exec lab01-iam-test whoami 2>/dev/null || echo "unknown")
|
||||
if [ "$actual_user" = "labuser" ]; then
|
||||
echo -e " ${GREEN}✓${NC} docker-compose container runs as non-root"
|
||||
((pass_count++))
|
||||
else
|
||||
echo -e " ${RED}✗${NC} docker-compose container running as $actual_user (expected labuser)"
|
||||
((fail_count++))
|
||||
fi
|
||||
else
|
||||
echo -e " ${RED}✗${NC} Container not running"
|
||||
((fail_count++))
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
docker-compose down --volumes >/dev/null 2>&1
|
||||
else
|
||||
echo -e " ${RED}✗${NC} Failed to start docker-compose service"
|
||||
((fail_count++))
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Summary
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo -e "${BLUE}Verification Summary${NC}"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo "Passed: $pass_count/6"
|
||||
echo "Failed: $fail_count/6"
|
||||
echo ""
|
||||
|
||||
if [ $fail_count -eq 0 ]; then
|
||||
echo -e "${GREEN}All checks passed!${NC}"
|
||||
echo -e "${GREEN}GREEN phase complete - infrastructure satisfies tests${NC}"
|
||||
echo ""
|
||||
echo "Next: Run full test suite"
|
||||
echo " bash labs/lab-01-iam/tests/run-all-tests.sh"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}Some checks failed${NC}"
|
||||
echo -e "${RED}Infrastructure needs fixes before tests will pass${NC}"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
Key implementation points:
|
||||
- Validates docker-compose.yml syntax
|
||||
- Verifies USER directive in Dockerfile
|
||||
- Verifies user directive in docker-compose.yml
|
||||
- Builds and tests Docker image
|
||||
- Starts container with docker-compose and verifies execution
|
||||
- Proper cleanup after testing
|
||||
- Clear pass/fail indicators
|
||||
|
||||
TDD Context: This script confirms the GREEN phase - infrastructure implementation makes tests pass.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>chmod +x labs/lab-01-iam/tests/04-verify-infrastructure.sh && cd labs/lab-01-iam && bash ../tests/04-verify-infrastructure.sh</automated>
|
||||
</verify>
|
||||
<done>Infrastructure verification script confirms all requirements satisfied</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. Dockerfile creates non-root user with USER directive
|
||||
2. docker-compose.yml specifies user directive for service
|
||||
3. docker-compose config validates without errors
|
||||
4. Docker build succeeds without warnings
|
||||
5. Container execution verified as non-root (whoami, docker inspect, docker top)
|
||||
6. All Wave 0 tests now pass (GREEN phase of TDD)
|
||||
7. INF-01 requirement satisfied: no container runs as root
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
1. Dockerfile follows non-root best practices from RESEARCH.md
|
||||
2. docker-compose.yml enforces non-root execution via user directive
|
||||
3. Infrastructure verification confirms all requirements met
|
||||
4. Tests from Wave 0 (02-01-PLAN.md) now pass
|
||||
5. LAB-01 requirement satisfied: students can configure users and Docker permissions
|
||||
6. INF-01 requirement satisfied: no container runs as root
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/02-lab-01-iam-sicurezza/02-03-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user