From 87dbdb4f93575bfeafc3d4ce96bc5a785ab11ec4 Mon Sep 17 00:00:00 2001 From: Luca Sacchi Ricciardi Date: Tue, 24 Mar 2026 21:55:00 +0100 Subject: [PATCH] docs(02): create phase 2 plans (3 plans) --- .planning/ROADMAP.md | 8 +- .../02-lab-01-iam-sicurezza/02-01-PLAN.md | 808 ++++++++ .../02-lab-01-iam-sicurezza/02-02-PLAN.md | 1843 +++++++++++++++++ .../02-lab-01-iam-sicurezza/02-03-PLAN.md | 504 +++++ 4 files changed, 3161 insertions(+), 2 deletions(-) create mode 100644 .planning/phases/02-lab-01-iam-sicurezza/02-01-PLAN.md create mode 100644 .planning/phases/02-lab-01-iam-sicurezza/02-02-PLAN.md create mode 100644 .planning/phases/02-lab-01-iam-sicurezza/02-03-PLAN.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 8621354..689b152 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -12,7 +12,7 @@ | Phase | Plans Complete | Status | Completed | |-------|----------------|--------|-----------| | 1. Setup & Git Foundation | 0/2 | Planning complete | - | -| 2. Lab 01 - IAM & Sicurezza | 0/3 | Not started | - | +| 2. Lab 01 - IAM & Sicurezza | 0/3 | Planning complete | - | | 3. Lab 02 - Network & VPC | 0/3 | Not started | - | | 4. Lab 03 - Compute & EC2 | 0/3 | Not started | - | | 5. Lab 04 - Storage & S3 | 0/3 | Not started | - | @@ -80,7 +80,11 @@ 4. Lab include Tutorial passo-passo, How-to Guides, Reference, e Explanation (Framework Diátaxis completo) 5. Studente può eseguire comando di verifica finale ("double check") per validare il lavoro svolto -**Plans:** TBD +**Plans:** 3 + +- [ ] [02-01-PLAN.md](.planning/phases/02-lab-01-iam-sicurezza/02-01-PLAN.md) — Create test infrastructure (Wave 0: test-01-user-creation.sh, test-02-docker-access.sh, 03-non-root-test.sh, 99-final-verification.sh, run-all-tests.sh) +- [ ] [02-02-PLAN.md](.planning/phases/02-lab-01-iam-sicurezza/02-02-PLAN.md) — Create Diátaxis documentation (Tutorial: 3 parts, How-to Guides: 3 guides, Reference: 3 documents, Explanation: IAM parallels) +- [ ] [02-03-PLAN.md](.planning/phases/02-lab-01-iam-sicurezza/02-03-PLAN.md) — Create infrastructure (Dockerfile with non-root user, docker-compose.yml with user directive, infrastructure verification) --- diff --git a/.planning/phases/02-lab-01-iam-sicurezza/02-01-PLAN.md b/.planning/phases/02-lab-01-iam-sicurezza/02-01-PLAN.md new file mode 100644 index 0000000..b9323f1 --- /dev/null +++ b/.planning/phases/02-lab-01-iam-sicurezza/02-01-PLAN.md @@ -0,0 +1,808 @@ +--- +phase: 02-lab-01-iam-sicurezza +plan: 01 +type: execute +wave: 0 +depends_on: [] +files_modified: + - labs/lab-01-iam/tests/test-01-user-creation.sh + - labs/lab-01-iam/tests/test-02-docker-access.sh + - labs/lab-01-iam/tests/03-non-root-test.sh + - labs/lab-01-iam/tests/99-final-verification.sh + - labs/lab-01-iam/tests/run-all-tests.sh +autonomous: true +requirements: [TEST-01, TEST-05, INF-01] +user_setup: [] +must_haves: + truths: + - "Test scripts exist and can validate user creation and Docker access" + - "Test scripts verify non-root container execution (INF-01)" + - "Final verification script runs all checks for student self-validation" + - "Test harness can be executed with single command" + artifacts: + - path: "labs/lab-01-iam/tests/test-01-user-creation.sh" + provides: "User and group creation validation" + min_lines: 40 + - path: "labs/lab-01-iam/tests/test-02-docker-access.sh" + provides: "Docker socket access control validation" + min_lines: 30 + - path: "labs/lab-01-iam/tests/03-non-root-test.sh" + provides: "Non-root container verification (INF-01)" + min_lines: 35 + - path: "labs/lab-01-iam/tests/99-final-verification.sh" + provides: "Final double-check command for students" + min_lines: 25 + - path: "labs/lab-01-iam/tests/run-all-tests.sh" + provides: "Test suite orchestration" + min_lines: 15 + key_links: + - from: "run-all-tests.sh" + to: "test-01-user-creation.sh, test-02-docker-access.sh, 03-non-root-test.sh, 99-final-verification.sh" + via: "Sequential execution with exit code handling" + pattern: "bash.*tests/.*\\.sh" +--- + + +Create test infrastructure following TDD methodology (RED phase first). Test scripts validate user creation, Docker socket access control, and non-root container execution before any implementation exists. + +Purpose: Enable Test-Driven Infrastructure (TDI) by writing failing tests first, then implementing infrastructure to make them pass. +Output: Four test scripts (user creation, Docker access, non-root verification, final check) plus test orchestration script. + + + +@/home/luca/.claude/get-shit-done/workflows/execute-plan.md +@/home/luca/.claude/get-shit-done/templates/summary.md + + + +@.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 + +# Key patterns from RESEARCH.md + +## TDD Methodology for Infrastructure +```bash +# RED Phase: Test should fail initially (no infrastructure exists) +# GREEN Phase: Implement minimum infrastructure to pass tests +# REFACTOR Phase: Optimize without breaking tests + +# Example test structure from RESEARCH.md: +test_unauthorized_access() { + sudo useradd -m -s /bin/bash test_user 2>/dev/null || true + if sudo -u test_user docker ps &>/dev/null; then + echo "FAIL: test_user can access docker without being in docker group" + return 1 + else + echo "PASS: test_user correctly denied access" + return 0 + fi +} +``` + +## INF-01 Verification Pattern +```bash +# From RESEARCH.md - Non-root container verification +for service in $(docker-compose ps --services); do + container_name=$(docker-compose ps -q $service) + actual_user=$(docker exec $container_name whoami 2>/dev/null) + if [ "$actual_user" = "root" ]; then + echo "FAIL: $service running as root" + exit 1 + fi +done +echo "PASS: All containers running as non-root" +``` + +## Common Pitfalls to Handle +- Group membership requires re-login (use `groups` command for testing) +- Test as non-privileged user (root bypasses Docker socket permissions) +- Verify with multiple methods: `docker exec whoami`, `docker inspect`, `docker top` + +## Test Framework from RESEARCH.md +- Framework: BASH (Bourne Again Shell) >= 4.0 +- No config file needed - inline test functions +- Quick run: `bash labs/lab-01-iam/tests/quick-test.sh` +- Full suite: `bash labs/lab-01-iam/tests/run-all-tests.sh` + + + + + + Task 1: Create user creation test script + labs/lab-01-iam/tests/test-01-user-creation.sh + + - Test 1: Non-existent user returns appropriate failure + - Test 2: User not in docker group cannot access Docker socket + - Test 3: User can be added to docker group + - Test 4: Group membership verified with `groups` command + + +Create test script for Linux user and group management: + +```bash +#!/bin/bash +# Test: Linux user creation and Docker group membership +# Phase: RED - This test will fail initially (no users configured) + +set -euo pipefail + +# Color output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +pass_count=0 +fail_count=0 + +test_user_not_exists() { + local user="lab01_student" + if id "$user" &>/dev/null; then + echo -e "${YELLOW}SKIP${NC}: User $user already exists" + return 0 + fi + echo -e "${GREEN}PASS${NC}: User $user does not exist (test environment clean)" + ((pass_count++)) + return 0 +} + +test_user_without_docker_group() { + local user="lab01_student" + # Create test user if doesn't exist + if ! id "$user" &>/dev/null; then + sudo useradd -m -s /bin/bash "$user" 2>/dev/null || true + fi + + # Check if user is in docker group + if groups "$user" 2>/dev/null | grep -q docker; then + echo -e "${RED}FAIL${NC}: User $user is in docker group (should not be yet)" + ((fail_count++)) + return 1 + fi + + echo -e "${GREEN}PASS${NC}: User $user is not in docker group" + ((pass_count++)) + return 0 +} + +test_docker_access_denied() { + local user="lab01_student" + + # Test that user cannot access docker socket + if sudo -u "$user" docker ps &>/dev/null; then + echo -e "${RED}FAIL${NC}: User $user can access docker without docker group membership" + ((fail_count++)) + return 1 + fi + + echo -e "${GREEN}PASS${NC}: Docker access correctly denied for $user" + ((pass_count++)) + return 0 +} + +# Run all tests +echo "Running user creation tests..." +echo "================================" +test_user_not_exists +test_user_without_docker_group +test_docker_access_denied +echo "================================" +echo "Tests passed: $pass_count" +echo "Tests failed: $fail_count" + +if [ $fail_count -gt 0 ]; then + exit 1 +fi +exit 0 +``` + +Key implementation points: +- Use `groups` command to verify group membership (handles re-login issue) +- Run Docker commands as test user with `sudo -u` +- Test the negative case first (user without access) +- Return proper exit codes (0=pass, 1=fail) + + + chmod +x labs/lab-01-iam/tests/test-01-user-creation.sh && bash labs/lab-01-iam/tests/test-01-user-creation.sh + + Script exists, is executable, and tests user/group creation behavior + + + + Task 2: Create Docker access control test script + labs/lab-01-iam/tests/test-02-docker-access.sh + + - Test 1: User in docker group can execute docker ps + - Test 2: User in docker group can run basic containers + - Test 3: Socket permissions are correctly set (660 or stricter) + - Test 4: Group membership propagation is verified + + +Create test script for Docker socket access control: + +```bash +#!/bin/bash +# Test: Docker socket access control via group membership +# Phase: RED - This test will fail initially (no users configured) + +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +pass_count=0 +fail_count=0 + +test_socket_permissions() { + local socket="/var/run/docker.sock" + local perms=$(stat -c "%a" "$socket" 2>/dev/null || echo "000") + + # Socket should be 660 or stricter (no world-readable/writable) + if [ "$perms" = "660" ] || [ "$perms" = "600" ]; then + echo -e "${GREEN}PASS${NC}: Docker socket permissions are $perms" + ((pass_count++)) + return 0 + else + echo -e "${YELLOW}WARN${NC}: Docker socket permissions are $perms (expected 660)" + ((pass_count++)) + return 0 + fi +} + +test_docker_group_exists() { + if getent group docker >/dev/null 2>&1; then + echo -e "${GREEN}PASS${NC}: Docker group exists" + ((pass_count++)) + return 0 + else + echo -e "${RED}FAIL${NC}: Docker group does not exist" + ((fail_count++)) + return 1 + fi +} + +test_user_can_add_to_docker_group() { + local user="lab01_student" + + # This test verifies the MECHANISM, not that it's done yet + if command -v usermod >/dev/null 2>&1; then + echo -e "${GREEN}PASS${NC}: usermod command available for group management" + ((pass_count++)) + return 0 + else + echo -e "${RED}FAIL${NC}: usermod command not available" + ((fail_count++)) + return 1 + fi +} + +test_docker_accessible_by_group() { + # Check that docker group members can access the socket + local socket_group=$(stat -c "%G" /var/run/docker.sock 2>/dev/null || echo "unknown") + + if [ "$socket_group" = "docker" ]; then + echo -e "${GREEN}PASS${NC}: Docker socket owned by docker group" + ((pass_count++)) + return 0 + else + echo -e "${YELLOW}WARN${NC}: Docker socket owned by $socket_group (expected docker)" + ((pass_count++)) + return 0 + fi +} + +# Run all tests +echo "Running Docker access control tests..." +echo "======================================" +test_socket_permissions +test_docker_group_exists +test_user_can_add_to_docker_group +test_docker_accessible_by_group +echo "======================================" +echo "Tests passed: $pass_count" +echo "Tests failed: $fail_count" + +if [ $fail_count -gt 0 ]; then + exit 1 +fi +exit 0 +``` + +Key implementation points: +- Verify socket ownership and permissions +- Check docker group exists +- Validate group management commands available +- Test mechanism for adding users to docker group + + + chmod +x labs/lab-01-iam/tests/test-02-docker-access.sh && bash labs/lab-01-iam/tests/test-02-docker-access.sh + + Script validates Docker socket access control mechanisms + + + + Task 3: Create non-root container verification script (INF-01) + labs/lab-01-iam/tests/03-non-root-test.sh + + - Test 1: Container configured with USER directive runs as non-root + - Test 2: docker exec whoami returns non-root user + - Test 3: docker inspect shows User field set + - Test 4: docker top shows non-root UID (not 0) + + +Create test script for non-root container verification (INF-01 requirement): + +```bash +#!/bin/bash +# Test: Non-root container execution (INF-01 requirement) +# Phase: RED - This test will fail initially (no containers exist) + +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +pass_count=0 +fail_count=0 + +# Container name to test +CONTAINER_NAME="lab01-test-container" + +test_non_root_dockerfile_exists() { + local dockerfile="labs/lab-01-iam/Dockerfile.test" + + if [ -f "$dockerfile" ]; then + echo -e "${GREEN}PASS${NC}: Test Dockerfile exists" + ((pass_count++)) + return 0 + else + echo -e "${YELLOW}SKIP${NC}: Test Dockerfile not created yet (expected in RED phase)" + ((pass_count++)) + return 0 + fi +} + +test_container_runs_as_non_root() { + # Check if container exists + if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + echo -e "${YELLOW}SKIP${NC}: Container ${CONTAINER_NAME} does not exist yet (expected in RED phase)" + ((pass_count++)) + return 0 + fi + + # Check if container is running + if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + echo -e "${YELLOW}SKIP${NC}: Container ${CONTAINER_NAME} not running" + ((pass_count++)) + return 0 + fi + + # Method 1: docker exec whoami + local actual_user=$(docker exec "${CONTAINER_NAME}" whoami 2>/dev/null || echo "unknown") + + if [ "$actual_user" = "root" ]; then + echo -e "${RED}FAIL${NC}: Container running as root (whoami)" + ((fail_count++)) + return 1 + elif [ "$actual_user" = "unknown" ]; then + echo -e "${YELLOW}SKIP${NC}: Cannot determine user (container not running or no exec)" + ((pass_count++)) + return 0 + else + echo -e "${GREEN}PASS${NC}: Container running as non-root user: $actual_user" + ((pass_count++)) + return 0 + fi +} + +test_container_user_configured() { + if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + echo -e "${YELLOW}SKIP${NC}: Container not created yet" + ((pass_count++)) + return 0 + fi + + # Method 2: docker inspect for User field + local user_config=$(docker inspect --format='{{.Config.User}}' "${CONTAINER_NAME}" 2>/dev/null || echo "") + + if [ -z "$user_config" ]; then + # Check compose file for user directive (may override Dockerfile) + if [ -f "labs/lab-01-iam/docker-compose.yml" ]; then + if grep -q "user:" labs/lab-01-iam/docker-compose.yml; then + echo -e "${GREEN}PASS${NC}: User directive found in docker-compose.yml" + ((pass_count++)) + return 0 + fi + fi + + echo -e "${YELLOW}WARN${NC}: No User directive found in Dockerfile or compose" + ((pass_count++)) + return 0 + else + echo -e "${GREEN}PASS${NC}: User configured in container: $user_config" + ((pass_count++)) + return 0 + fi +} + +test_no_container_runs_as_root() { + # INF-01 requirement: NO container should run as root + local compose_file="labs/lab-01-iam/docker-compose.yml" + + if [ ! -f "$compose_file" ]; then + echo -e "${YELLOW}SKIP${NC}: docker-compose.yml not created yet" + ((pass_count++)) + return 0 + fi + + # Get all services from compose file + local services=$(docker-compose -f "$compose_file" ps --services 2>/dev/null || echo "") + + if [ -z "$services" ]; then + echo -e "${YELLOW}SKIP${NC}: No services defined yet" + ((pass_count++)) + return 0 + fi + + local root_containers=0 + while IFS= read -r service; do + if [ -n "$service" ]; then + local container_name=$(docker-compose -f "$compose_file" ps -q "$service" 2>/dev/null || echo "") + if [ -n "$container_name" ]; then + local user=$(docker exec "$container_name" whoami 2>/dev/null || echo "unknown") + if [ "$user" = "root" ]; then + echo -e "${RED}FAIL${NC}: Service $service running as root" + ((root_containers++)) + fi + fi + fi + done <<< "$services" + + if [ $root_containers -gt 0 ]; then + echo -e "${RED}FAIL${NC}: $root_containers container(s) running as root (INF-01 violation)" + ((fail_count++)) + return 1 + else + echo -e "${GREEN}PASS${NC}: No containers running as root (INF-01 satisfied)" + ((pass_count++)) + return 0 + fi +} + +# Run all tests +echo "Running non-root container tests (INF-01)..." +echo "============================================" +test_non_root_dockerfile_exists +test_container_runs_as_non_root +test_container_user_configured +test_no_container_runs_as_root +echo "============================================" +echo "Tests passed: $pass_count" +echo "Tests failed: $fail_count" + +if [ $fail_count -gt 0 ]; then + exit 1 +fi +exit 0 +``` + +Key implementation points: +- INF-01 requirement: NO container runs as root +- Multiple verification methods (whoami, inspect, compose check) +- Handle not-yet-created infrastructure gracefully (skip with warning) +- Check all services in docker-compose.yml for compliance + + + chmod +x labs/lab-01-iam/tests/03-non-root-test.sh && bash labs/lab-01-iam/tests/03-non-root-test.sh + + Script verifies INF-01: no container runs as root + + + + Task 4: Create final verification script (double-check for students) + labs/lab-01-iam/tests/99-final-verification.sh + + - Test 1: All previous tests can be run + - Test 2: Student can verify their work end-to-end + - Test 3: Clear PASS/FAIL report for all requirements + - Test 4: Exit code indicates overall success/failure + + +Create final verification script for student self-check: + +```bash +#!/bin/bash +# Final Verification: Lab 01 - IAM & Sicurezza +# This is the "double check" command students run to verify their work +# Usage: bash tests/99-final-verification.sh + +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}Lab 01 - IAM & Sicurezza${NC}" +echo -e "${BLUE}Final Verification (Double Check)${NC}" +echo -e "${BLUE}========================================${NC}" +echo "" + +# Track overall results +all_passed=true + +# Test 1: User and group configuration +echo -e "${BLUE}[1/5] Checking user and group configuration...${NC}" +if id lab01_student &>/dev/null; then + echo -e " ${GREEN}✓${NC} User lab01_student exists" + if groups lab01_student 2>/dev/null | grep -q docker; then + echo -e " ${GREEN}✓${NC} User lab01_student is in docker group" + else + echo -e " ${RED}✗${NC} User lab01_student is NOT in docker group" + all_passed=false + fi +else + echo -e " ${YELLOW}○${NC} User lab01_student does not exist (not created yet)" + all_passed=false +fi +echo "" + +# Test 2: Docker access control +echo -e "${BLUE}[2/5] Checking Docker access control...${NC}" +if sudo -u lab01_student docker ps &>/dev/null; then + echo -e " ${GREEN}✓${NC} lab01_student can access Docker socket" +else + echo -e " ${RED}✗${NC} lab01_student cannot access Docker socket" + echo -e " ${YELLOW} Hint: User may need to re-login for group membership to take effect${NC}" + all_passed=false +fi +echo "" + +# Test 3: Non-root container execution (INF-01) +echo -e "${BLUE}[3/5] Checking non-root container execution (INF-01)...${NC}" +compose_file="labs/lab-01-iam/docker-compose.yml" +if [ ! -f "$compose_file" ]; then + echo -e " ${YELLOW}○${NC} docker-compose.yml not found" + all_passed=false +else + echo -e " ${GREEN}✓${NC} docker-compose.yml exists" + + # Check for user directive in services + if grep -A 10 "services:" "$compose_file" | grep -q "user:"; then + echo -e " ${GREEN}✓${NC} Services configured with non-root user directive" + else + echo -e " ${RED}✗${NC} No user directive found in docker-compose.yml" + all_passed=false + fi + + # If containers are running, verify they're not root + if docker-compose -f "$compose_file" ps --services 2>/dev/null | grep -q .; then + local root_count=0 + while IFS= read -r service; do + [ -z "$service" ] && continue + local container=$(docker-compose -f "$compose_file" ps -q "$service" 2>/dev/null || echo "") + if [ -n "$container" ]; then + local user=$(docker exec "$container" whoami 2>/dev/null || echo "unknown") + if [ "$user" = "root" ]; then + echo -e " ${RED}✗${NC} Service $service running as ROOT (INF-01 violation)" + ((root_count++)) + fi + fi + done <<< "$(docker-compose -f "$compose_file" ps --services 2>/dev/null)" + + if [ $root_count -eq 0 ]; then + echo -e " ${GREEN}✓${NC} All running containers are non-root" + else + all_passed=false + fi + else + echo -e " ${YELLOW}○${NC} No containers running (start with docker-compose up)" + fi +fi +echo "" + +# Test 4: Documentation completeness (Diátaxis) +echo -e "${BLUE}[4/5] Checking documentation (Diátaxis framework)...${NC}" +doc_count=0 +for doc_type in "tutorial" "how-to-guides" "reference" "explanation"; do + if [ -d "labs/lab-01-iam/$doc_type" ]; then + local md_files=$(find "labs/lab-01-iam/$doc_type" -name "*.md" 2>/dev/null | wc -l) + if [ "$md_files" -gt 0 ]; then + echo -e " ${GREEN}✓${NC} $doc_type: $md_files document(s)" + ((doc_count++)) + else + echo -e " ${YELLOW}○${NC} $doc_type: directory exists but empty" + fi + else + echo -e " ${RED}✗${NC} $doc_type: missing" + fi +done + +if [ $doc_count -eq 4 ]; then + echo -e " ${GREEN}✓${NC} All 4 Diátaxis document types present" +else + echo -e " ${YELLOW}○${NC} $doc_count/4 Diátaxis document types present" + all_passed=false +fi +echo "" + +# Test 5: IAM parallels documentation +echo -e "${BLUE}[5/5] Checking IAM parallels explanation...${NC}" +explanation_file="labs/lab-01-iam/explanation/docker-iam-parallels.md" +if [ -f "$explanation_file" ]; then + if grep -qi "IAM.*Linux\|Linux.*IAM" "$explanation_file"; then + echo -e " ${GREEN}✓${NC} IAM parallels documented" + else + echo -e " ${YELLOW}○${NC} Explanation exists but IAM parallels unclear" + fi + + if grep -qi "differenza\|difference" "$explanation_file"; then + echo -e " ${GREEN}✓${NC} Local vs cloud differences documented" + else + echo -e " ${YELLOW}○${NC} Local vs cloud differences not clearly documented" + fi +else + echo -e " ${RED}✗${NC} IAM parallels explanation not found" + all_passed=false +fi +echo "" + +# Final summary +echo -e "${BLUE}========================================${NC}" +if [ "$all_passed" = true ]; then + echo -e "${GREEN}ALL CHECKS PASSED${NC}" + echo -e "${GREEN}Lab 01 is complete!${NC}" + echo -e "${BLUE}========================================${NC}" + exit 0 +else + echo -e "${RED}SOME CHECKS FAILED${NC}" + echo -e "${YELLOW}Review the output above and complete the missing items${NC}" + echo -e "${BLUE}========================================${NC}" + exit 1 +fi +``` + +Key implementation points: +- Student-friendly double-check command +- Clear visual indicators (✓ pass, ✗ fail, ○ skip) +- Tests all phase requirements: LAB-01, INF-01, DOCT-01/02/03/04, PARA-01/03 +- Exit code 0 for all-pass, 1 for any failure +- Helpful hints for common issues (re-login for group membership) + + + chmod +x labs/lab-01-iam/tests/99-final-verification.sh && bash labs/lab-01-iam/tests/99-final-verification.sh + + Student can run single command to verify all lab requirements are met + + + + Task 5: Create test orchestration script + labs/lab-01-iam/tests/run-all-tests.sh + + - Test 1: Script executes all test files in sequence + - Test 2: Script stops on first failure (fail-fast) + - Test 3: Script aggregates results and provides summary + - Test 4: Script can be run from project root + + +Create test orchestration script: + +```bash +#!/bin/bash +# Test Suite Runner: Lab 01 - IAM & Sicurezza +# Runs all tests in sequence and provides summary +# Usage: bash labs/lab-01-iam/tests/run-all-tests.sh + +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +BLUE='\033[0;34m' +NC='\033[0m' + +TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$TEST_DIR/../.." && pwd)" + +cd "$PROJECT_ROOT" + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}Lab 01 Test Suite${NC}" +echo -e "${BLUE}========================================${NC}" +echo "" + +# Array of test files in order +declare -a tests=( + "$TEST_DIR/test-01-user-creation.sh" + "$TEST_DIR/test-02-docker-access.sh" + "$TEST_DIR/03-non-root-test.sh" +) + +total_tests=${#tests[@]} +passed_tests=0 +failed_tests=0 + +for i in "${!tests[@]}"; do + test_num=$((i + 1)) + test_file="${tests[$i]}" + test_name=$(basename "$test_file") + + echo -e "${BLUE}[$test_num/$total_tests] Running $test_name...${NC}" + + if bash "$test_file"; then + echo -e "${GREEN}✓ PASSED${NC}" + echo "" + ((passed_tests++)) + else + echo -e "${RED}✗ FAILED${NC}" + echo "" + ((failed_tests++)) + # Fail-fast: stop on first failure + break + fi +done + +# Summary +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}Test Suite Summary${NC}" +echo -e "${BLUE}========================================${NC}" +echo "Passed: $passed_tests/$total_tests" +echo "Failed: $failed_tests/$total_tests" +echo "" + +if [ $failed_tests -eq 0 ]; then + echo -e "${GREEN}All tests passed!${NC}" + echo "" + echo "Run final verification:" + echo " bash labs/lab-01-iam/tests/99-final-verification.sh" + echo -e "${BLUE}========================================${NC}" + exit 0 +else + echo -e "${RED}Some tests failed${NC}" + echo -e "${BLUE}========================================${NC}" + exit 1 +fi +``` + +Key implementation points: +- Fail-fast approach (stops on first failure for TDD RED phase) +- Executes tests in dependency order +- Provides summary and next steps +- Can be run from any directory (uses absolute paths) + + + chmod +x labs/lab-01-iam/tests/run-all-tests.sh && bash labs/lab-01-iam/tests/run-all-tests.sh + + Orchestration script runs all tests and provides summary + + + + + +1. All test scripts are executable (chmod +x) +2. Test scripts can run individually and return proper exit codes +3. Test orchestration script executes all tests in sequence +4. Test scripts follow TDD RED phase (will fail before implementation exists) +5. All tests handle missing infrastructure gracefully (skip with warning) + + + +1. Test infrastructure is in place before any implementation (Wave 0 complete) +2. All requirement IDs (TEST-01, TEST-05, INF-01) have test coverage +3. Tests follow bash scripting best practices (set -euo pipefail, proper exit codes) +4. Student can run individual tests or full suite +5. Final verification script provides clear pass/fail report for all lab requirements + + + +After completion, create `.planning/phases/02-lab-01-iam-sicurezza/02-01-SUMMARY.md` + diff --git a/.planning/phases/02-lab-01-iam-sicurezza/02-02-PLAN.md b/.planning/phases/02-lab-01-iam-sicurezza/02-02-PLAN.md new file mode 100644 index 0000000..369b11f --- /dev/null +++ b/.planning/phases/02-lab-01-iam-sicurezza/02-02-PLAN.md @@ -0,0 +1,1843 @@ +--- +phase: 02-lab-01-iam-sicurezza +plan: 02 +type: execute +wave: 1 +depends_on: [02-01] +files_modified: + - labs/lab-01-iam/tutorial/01-create-linux-users.md + - labs/lab-01-iam/tutorial/02-docker-group-permissions.md + - labs/lab-01-iam/tutorial/03-verify-iam-setup.md + - labs/lab-01-iam/how-to-guides/add-user-to-docker-group.md + - labs/lab-01-iam/how-to-guides/verify-non-root-container.md + - labs/lab-01-iam/how-to-guides/reset-docker-permissions.md + - labs/lab-01-iam/reference/docker-socket-permissions.md + - labs/lab-01-iam/reference/linux-users-groups.md + - labs/lab-01-iam/reference/iam-parallels.md + - labs/lab-01-iam/explanation/docker-iam-parallels.md +autonomous: true +requirements: [LAB-01, DOCT-01, DOCT-02, DOCT-03, DOCT-04, DOCT-05, PARA-01, PARA-03, PARA-04] +user_setup: [] +must_haves: + truths: + - "Student can follow step-by-step tutorial to create Linux users with Docker permissions" + - "Tutorial follows 'little often' principle with small incremental steps" + - "How-to guides exist for common procedures independent of tutorial flow" + - "Reference documents provide technical specifications without explanation" + - "Explanation document draws clear parallels between Docker permissions and AWS IAM" + artifacts: + - path: "labs/lab-01-iam/tutorial/01-create-linux-users.md" + provides: "Step-by-step user creation guide" + min_lines: 60 + - path: "labs/lab-01-iam/tutorial/02-docker-group-permissions.md" + provides: "Docker group permissions tutorial" + min_lines: 60 + - path: "labs/lab-01-iam/tutorial/03-verify-iam-setup.md" + provides: "Verification and testing tutorial" + min_lines: 40 + - path: "labs/lab-01-iam/how-to-guides/add-user-to-docker-group.md" + provides: "Procedure for adding user to docker group" + min_lines: 30 + - path: "labs/lab-01-iam/how-to-guides/verify-non-root-container.md" + provides: "Non-root container verification procedure" + min_lines: 25 + - path: "labs/lab-01-iam/how-to-guides/reset-docker-permissions.md" + provides: "Permission reset procedure" + min_lines: 30 + - path: "labs/lab-01-iam/reference/docker-socket-permissions.md" + provides: "Docker socket technical specifications" + min_lines: 40 + - path: "labs/lab-01-iam/reference/linux-users-groups.md" + provides: "Linux user management reference" + min_lines: 40 + - path: "labs/lab-01-iam/reference/iam-parallels.md" + provides: "IAM parallelism quick reference" + min_lines: 30 + - path: "labs/lab-01-iam/explanation/docker-iam-parallels.md" + provides: "Conceptual mapping between Docker and IAM" + min_lines: 80 + key_links: + - from: "tutorial/*.md" + to: "how-to-guides/*.md, reference/*.md" + via: "Cross-references for deeper dives" + pattern: "\\[.*\\]\\(\\../how-to-guides/.*\\)" + - from: "explanation/docker-iam-parallels.md" + to: "reference/iam-parallels.md" + via: "Quick reference table for concepts" + pattern: "See \\[.*\\]\\(\\../reference/iam-parallels.md\\)" +--- + + +Create complete Diátaxis documentation (Tutorial, How-to Guides, Reference, Explanation) for Lab 01 - IAM & Sicurezza. Students learn Linux user management and Docker permissions through step-by-step tutorials, with supporting documentation for procedures and technical specs. + +Purpose: Teach IAM concepts through local Linux user management and Docker socket permissions, drawing direct parallels to AWS IAM. +Output: 10 documentation files covering all 4 Diátaxis quadrants. + + + +@/home/luca/.claude/get-shit-done/workflows/execute-plan.md +@/home/luca/.claude/get-shit-done/templates/summary.md + + + +@.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 + +# Diátaxis Framework from CLAUDE.md + +## 2.1 Output Didattico a 4 Quadranti +1. **Tutorials:** Guida passo-passo incrementale (*little often*) per guidare l'allievo. +2. **How-to Guides:** Procedure specifiche (es. "Come generare chiavi SSH", "Come ripulire i volumi Docker"). +3. **Reference:** Specifiche tecniche nude e crude (mappe IP, tabelle porte esposte, spiegazione direttive `docker-compose`). +4. **Explanation:** Il raccordo concettuale (parallelismo tra l'ambiente locale simulato e i veri servizi Cloud managed). + +## IAM Parallels from RESEARCH.md + +| Concepto Linux | AWS IAM Equivalente | Spiegazione | +|----------------|---------------------|-------------| +| Utente Linux (`student1`) | IAM User | Identità che può autenticarsi | +| Gruppo Linux (`docker`) | IAM Group | Collezione di utenti con stessi permessi | +| Permessi file/socket | IAM Policy | Regole che definiscono cosa è permesso | +| `/var/run/docker.sock` | Service Endpoint | Risorsa protetta da controlli accesso | +| `sudo` elevation | IAM Role Assumption | Temporanea elevazione privilegi | + +## Common Pitfalls from RESEARCH.md +- Group membership requires re-login (use `newgrp docker` OR `su - user`) +- Testing as wrong user (root bypasses permissions) +- Socket permissions may change after Docker daemon restart + +## Tone Guidelines +- Direct, simple language (Italian) +- No emojis +- Technically accurate +- Step-by-step with verification at each step + + + + + + Task 1: Create Tutorial - Part 1: Linux Users + labs/lab-01-iam/tutorial/01-create-linux-users.md + +Create tutorial following Diátaxis framework - step-by-step, incremental, with verification: + +```markdown +# Tutorial: Creare Utenti Linux per il Lab IAM + +In questo tutorial creerai utenti Linux con permessi limitati per simulare utenti IAM in un ambiente cloud. Imparerai a creare utenti, verificare i permessi e gestire l'appartenenza ai gruppi. + +## Obiettivo +Creare un utente Linux `lab01_student` che non ha accesso iniziale a Docker, simulando un utente cloud senza permessi. + +## Prerequisiti +- Accesso a un terminale Linux con privilegi sudo +- Docker Engine installato e in esecuzione +- Comandi base: `useradd`, `groups`, `id` + +--- + +## Passo 1: Verifica l'ambiente + +Prima di creare utenti, verifichiamo che l'ambiente sia pronto. + +Esegui: +```bash +# Verifica che Docker sia in esecuzione +sudo systemctl status docker + +# Verifica che il gruppo docker esista +getent group docker +``` + +Atteso: +- Docker deve essere "active (running)" +- Il gruppo docker deve essere mostrato + +Se qualcosa non funziona, consulta [Troubleshooting](#troubleshooting). + +--- + +## Passo 2: Crea un nuovo utente Linux + +Creiamo un utente che simulerà un utente cloud senza permessi IAM. + +Esegui: +```bash +# Crea l'utente lab01_student +sudo useradd -m -s /bin/bash lab01_student + +# Verifica che l'utente sia stato creato +id lab01_student +``` + +Atteso: +``` +uid=1001(lab01_student) gid=1001(lab01_student) gruppi=1001(lab01_student) +``` + +Spiegazione: +- `-m` crea la home directory +- `-s /bin/bash` imposta la shell di default +- L'utente ha solo il proprio gruppo iniziale + +--- + +## Passo 3: Verifica i gruppi dell'utente + +Controlliamo a quali gruppi appartiene l'utente. + +Esegui: +```bash +groups lab01_student +``` + +Atteso: +``` +lab01_student : lab01_student +``` + +Nota: L'utente NON è nel gruppo `docker`. Questo è corretto simuliamo un utente senza permessi. + +--- + +## Passo 4: Verifica che l'utente NON può accedere a Docker + +Prova a eseguire un comando Docker come l'utente `lab01_student`. + +Esegui: +```bash +# Esegui docker ps come lab01_student +sudo -u lab01_student docker ps +``` + +Atteso: +``` +permission denied while trying to connect to the Docker daemon socket +``` + +Questo è il comportamento corretto! L'utente non ha ancora permessi Docker. + +--- + +## Passo 5: Imposta una password per l'utente (opzionale) + +Se vuoi poter fare login come questo utente: + +Esegui: +```bash +sudo passwd lab01_student +``` + +Inserisci una password quando richiesto. + +--- + +## Verifica + +Hai completato questo tutorial quando: +- [ ] L'utente `lab01_student` esiste +- [ ] L'utente NON è nel gruppo docker +- [ ] L'utente NON può eseguire comandi docker +- [ ] Il comando `groups lab01_student` mostra solo il proprio gruppo + +## Prossimo Passo + +Nel [prossimo tutorial](./02-docker-group-permissions.md) imparerai a dare permessi Docker all'utente tramite i gruppi. + +--- + +## Troubleshooting + +**Problema: `useradd: user 'lab01_student' already exists`** + +Soluzione: +```bash +# Elimina l'utente esistente e ricrealo +sudo userdel -r lab01_student +sudo useradd -m -s /bin/bash lab01_student +``` + +**Problema: Docker non è in esecuzione** + +Soluzione: +```bash +sudo systemctl start docker +sudo systemctl enable docker +``` + +**Problema: Il gruppo docker non esiste** + +Soluzione: +```bash +sudo groupadd docker +``` +``` + +Key points: +- Step-by-step with verification after each step +- "Little often" - small steps, frequent verification +- Clear expected output +- Troubleshooting section +- Links to next tutorial + + + test -f labs/lab-01-iam/tutorial/01-create-linux-users.md && grep -q "Passo 1\|Passo 2\|Passo 3" labs/lab-01-iam/tutorial/01-create-linux-users.md && wc -l labs/lab-01-iam/tutorial/01-create-linux-users.md | awk '{if($1>=60) print "PASS"; else print "FAIL: Tutorial too short ("$1" lines, expected 60+)"}' + + Tutorial Part 1 created with step-by-step user creation guide + + + + Task 2: Create Tutorial - Part 2: Docker Group Permissions + labs/lab-01-iam/tutorial/02-docker-group-permissions.md + +Create second tutorial covering Docker group permissions: + +```markdown +# Tutorial: Permessi Docker tramite Gruppi Linux + +In questo tutorial imparerai come dare permessi Docker a un utente tramite l'appartenenza al gruppo `docker`. Questo simula l'assegnazione di policy IAM a un utente cloud. + +## Obiettivo +Aggiungere l'utente `lab01_student` al gruppo `docker`, permettendo l'accesso al socket Docker. + +## Prerequisiti +- Completato [Tutorial 1: Creare Utenti Linux](./01-create-linux-users.md) +- L'utente `lab01_student` esiste e NON è nel gruppo docker + +--- + +## Passo 1: Verifica lo stato corrente + +Prima di modificare i permessi, verifichiamo lo stato attuale. + +Esegui: +```bash +# Verifica i gruppi dell'utente +groups lab01_student + +# Verifica i permessi del socket Docker +ls -l /var/run/docker.sock +``` + +Atteso: +- `groups` mostra solo `lab01_student` (NON docker) +- Il socket Docker ha permessi `srw-rw----` ed è di proprietà `root:docker` + +Spiegazione: Il socket Docker (`/var/run/docker.sock`) è accessibile solo a `root` e ai membri del gruppo `docker`. + +--- + +## Passo 2: Aggiungi l'utente al gruppo docker + +Ora aggiungiamo l'utente al gruppo per dargli accesso Docker. + +Esegui: +```bash +# Aggiungi lab01_student al gruppo docker +sudo usermod -aG docker lab01_student + +# Verifica l'appartenenza al gruppo +groups lab01_student +``` + +Atteso: +``` +lab01_student : lab01_student docker +``` + +Nota: Il gruppo `docker` ora appare nell'elenco! + +Spiegazione: +- `-aG` significa "append" (aggiunge senza rimuovere altri gruppi) e "group" (modifica i gruppi) +- Questo è equivalente ad assegnare una policy IAM a un utente cloud + +--- + +## Passo 3: Importante - Login necessario + +I gruppi vengono valutati al momento del login. La sessione corrente dell'utente non vedrà ancora il nuovo gruppo. + +Per verificare il gruppo membership (senza dover fare login): +```bash +# Questo mostra i gruppi anche se non sono ancora attivi nella sessione +groups lab01_student +``` + +Per rendere attivi i nuovi gruppi, l'utente deve fare una di queste operazioni: +1. Fare logout e login +2. Eseguire `newgrp docker` +3. Eseguire `su - lab01_student` + +--- + +## Passo 4: Verifica l'accesso Docker + +Ora verifichiamo che l'utente può accedere a Docker. + +Esegui: +```bash +# Metodo 1: Usa newgrp per attivare il gruppo nella sessione corrente +sudo -u lab01_student -i docker ps +``` + +Atteso: +``` +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +``` + +Il comando funziona! L'utente ora ha accesso Docker. + +--- + +## Passo 5: Verifica con un container di test + +Facciamo partire un container semplice per confermare che tutto funziona. + +Esegui: +```bash +# Esegui un container Alpine come lab01_student +sudo -u lab01_student -i docker run --rm alpine:3.19 whoami +``` + +Atteso: +``` +root +``` + +Nota: Il container mostra "root" perché questo è l'utente di default DENTRO il container (non è l'utente che ha lanciato il comando). Nel [Tutorial 3](./03-verify-iam-setup.md) imparerai a far girare i container come utente non-root. + +--- + +## Parallelismo con AWS IAM + +| Operazione Locale | AWS IAM Equivalente | +|-------------------|---------------------| +| `usermod -aG docker user` | `AttachUserPolicy` o `AddUserToGroup` | +| Utente nel gruppo `docker` | Utente IAM con policy permessive | +| Accesso al socket Docker | Accesso alle API AWS | + +--- + +## Verifica + +Hai completato questo tutorial quando: +- [ ] L'utente `lab01_student` è nel gruppo docker +- [ ] L'utente può eseguire `docker ps` +- [ ] L'utente può fare partire container +- [ ] Capisci il parallelismo con IAM User + Policy + +## Prossimo Passo + +Nel [prossimo tutorial](./03-verify-iam-setup.md) imparerai a verificare l'intera configurazione e a far girare container non-root. + +--- + +## Troubleshooting + +**Problema: L'utente non può ancora eseguire docker ps** + +Soluzione 1: Verifica di aver usato `sudo -u lab01_student -i` +```bash +# Il flag -i è importante per caricare l'ambiente corretto +sudo -u lab01_student -i docker ps +``` + +Soluzione 2: Verifica che l'utente sia nel gruppo +```bash +groups lab01_student +# Se non vedi "docker", ripeti il Passo 2 +``` + +**Problema: Il socket Docker ha permessi errati** + +Soluzione: +```bash +# Correggi i permessi del socket +sudo chmod 660 /var/run/docker.sock +sudo chown root:docker /var/run/docker.sock +``` + +**Problema: `usermod: user 'lab01_student' does not exist`** + +Soluzione: Prima crea l'utente seguendo il [Tutorial 1](./01-create-linux-users.md). +``` + +Key points: +- Explain the group membership evaluation timing issue +- Show parallelism with AWS IAM +- Multiple troubleshooting scenarios +- Clear verification steps + + + test -f labs/lab-01-iam/tutorial/02-docker-group-permissions.md && grep -q "IAM\|AWS\|Parallelismo" labs/lab-01-iam/tutorial/02-docker-group-permissions.md && wc -l labs/lab-01-iam/tutorial/02-docker-group-permissions.md | awk '{if($1>=60) print "PASS"; else print "FAIL: Tutorial too short ("$1" lines, expected 60+)"}' + + Tutorial Part 2 created with Docker group permissions guide + + + + Task 3: Create Tutorial - Part 3: Verification and Non-Root Containers + labs/lab-01-iam/tutorial/03-verify-iam-setup.md + +Create third tutorial covering verification and non-root containers: + +```markdown +# Tutorial: Verifica Configurazione IAM e Container Non-Root + +In questo tutorial verificherai l'intera configurazione IAM e imparerai a far girare container come utente non-root, seguendo il principio del minimo privilegio. + +## Obiettivo +Verificare che la configurazione IAM funzioni e far girare container come utente non-root (INF-01). + +## Prerequisiti +- Completati [Tutorial 1](./01-create-linux-users.md) e [Tutorial 2](./02-docker-group-permissions.md) +- L'utente `lab01_student` esiste ed è nel gruppo docker + +--- + +## Passo 1: Esegui lo script di verifica + +Il lab include uno script automatizzato per verificare tutto. + +Esegui: +```bash +bash labs/lab-01-iam/tests/99-final-verification.sh +``` + +Questo comando controllerà: +1. Configurazione utenti e gruppi +2. Accesso Docker +3. Esecuzione container non-root +4. Documentazione completa +5. Parallelismi IAM + +Se tutti i check sono verdi, sei pronto per procedere! + +--- + +## Passo 2: Verifica manuale - Accesso Docker + +Verifichiamo manualmente che l'utente possa accedere a Docker. + +Esegui: +```bash +# Verifica che docker ps funzioni +sudo -u lab01_student -i docker ps + +# Verifica informazioni sul sistema Docker +sudo -u lab01_student -i docker info +``` + +Entrambi i comandi dovrebbero funzionare senza errori. + +--- + +## Passo 3: Crea un container NON-ROOT + +Ora creiamo un container che gira come utente non-root, seguendo il principio del minimo privilegio. + +Esegui: +```bash +cd labs/lab-01-iam + +# Crea un Dockerfile di test +cat > Dockerfile.test << 'EOF' +FROM alpine:3.19 + +# Crea un utente non-root +RUN addgroup -g 1000 appgroup && \ + adduser -D -u 1000 -G appgroup appuser + +# Passa all'utente non-root +USER appuser + +# Verifica che il container gira come appuser +CMD ["sh", "-c", "whoami && sleep 3600"] +EOF +``` + +Spiegazione: +- Creiamo un utente `appuser` con UID 1000 +- Passiamo a questo utente con `USER` +- Il container ora girerà come `appuser`, non come `root` + +--- + +## Passo 4: Build e run del container + +Ora costruiamo e facciamo partire il container. + +Esegui: +```bash +# Costruisci l'immagine +sudo -u lab01_student -i docker build -f Dockerfile.test -t test-non-root . + +# Fai partire il container +sudo -u lab01_student -i docker run --name lab01-test-container -d test-non-root +``` + +Atteso: +- Build completa senza errori +- Container ID viene mostrato + +--- + +## Passo 5: Verifica che il container NON gira come root + +Verifichiamo l'utente del container in tre modi. + +Esegui: +```bash +# Metodo 1: docker exec whoami +docker exec lab01-test-container whoami +``` + +Atteso: +``` +appuser +``` + +Esegui: +```bash +# Metodo 2: docker inspect +docker inspect lab01-test-container --format='{{.Config.User}}' +``` + +Atteso: +``` +appuser +``` + +Esegui: +```bash +# Metodo 3: docker top (mostra il processo sull'host) +docker top lab01-test-container +``` + +Atteso: +- La colonna USER mostra `1000` (non `0`) + +--- + +## Passo 6: Verifica INF-01 - Nessun container root + +Il requisito INF-01 richiede che NESSUN container giri come root. + +Esegui: +```bash +bash labs/lab-01-iam/tests/03-non-root-test.sh +``` + +Questo script verificherà tutti i container e garantirà che nessuno giri come root. + +--- + +## Passo 7: Pulisci il container di test + +Dopo aver verificato, puliamo il container di test. + +Esegui: +```bash +# Ferma e rimuovi il container +docker stop lab01-test-container +docker rm lab01-test-container + +# Rimuovi l'immagine +docker rmi test-non-root +``` + +--- + +## Principio del Minimo Privilegio + +Perché NON usare root nei container? + +| Rischio Root | Mitigazione Non-Root | +|--------------|----------------------| +| Container compromesso = host compromesso | Utente limitato = danno contenuto | +| Container può leggere/scrivere qualsiasi file sull'host | Container può solo accedere ai suoi file | +| Escalation privilegi possibile | Privilegi già limitati | + +Questo è lo stesso principio di IAM in cloud: dai solo i permessi minimi necessari. + +--- + +## Verifica + +Hai completato questo tutorial quando: +- [ ] Lo script di verifica passa senza errori +- [ ] Il container di test gira come utente non-root +- [ ] Tutti e tre i metodi di verifica mostrano lo stesso utente non-root +- [ ] Capisci perché INF-01 è importante per la sicurezza + +--- + +## Troubleshooting + +**Problema: `docker exec` mostra "root"** + +Soluzione: Verifica che il Dockerfile abbia la direttiva `USER` +```bash +# Verifica che USER sia nel Dockerfile +grep USER Dockerfile.test +# Dovrebbe mostrare: USER appuser +``` + +**Problema: `docker top` mostra UID 0** + +Soluzione: Il container potrebbe essere stato configurato con docker-compose. Verifica: +```bash +# Verifica la direttiva user in docker-compose +grep -A 5 "user:" labs/lab-01-iam/docker-compose.yml +``` + +**Problema: Il test INF-01 fallisce** + +Soluzione: Assicurati che TUTTI i container abbiano la direttiva USER o user: +```bash +# Controlla tutti i container +docker ps --format "{{.Names}}" | xargs -I {} sh -c 'echo "Container: {}" && docker inspect --format="{{.Config.User}}" {}' +``` +``` + +Key points: +- Multiple verification methods for non-root execution +- Clear explanation of security principle +- Automated test integration +- Comprehensive troubleshooting + + + test -f labs/lab-01-iam/tutorial/03-verify-iam-setup.md && grep -q "INF-01\|minimo privilegio\|non-root" labs/lab-01-iam/tutorial/03-verify-iam-setup.md && wc -l labs/lab-01-iam/tutorial/03-verify-iam-setup.md | awk '{if($1>=40) print "PASS"; else print "FAIL: Tutorial too short ("$1" lines, expected 40+)"}' + + Tutorial Part 3 created with verification and non-root container guide + + + + Task 4: Create How-to Guides + labs/lab-01-iam/how-to-guides/add-user-to-docker-group.md, labs/lab-01-iam/how-to-guides/verify-non-root-container.md, labs/lab-01-iam/how-to-guides/reset-docker-permissions.md + +Create three how-to guides for common procedures: + +**File 1: labs/lab-01-iam/how-to-guides/add-user-to-docker-group.md** +```markdown +# How-To: Aggiungere un Utente al Gruppo Docker + +Guida rapida per aggiungere un utente Linux al gruppo Docker e dargli accesso al socket. + +## Comando Rapido + +```bash +# Aggiungi utente esistente al gruppo docker +sudo usermod -aG docker nome_utente +``` + +## Verifica + +```bash +# Verifica l'appartenenza al gruppo +groups nome_utente + +# Verifica l'accesso docker +sudo -u nome_utente -i docker ps +``` + +## Nota Importante + +I gruppi vengono valutati al login. Per attivare il nuovo gruppo immediatamente: + +```bash +# Opzione 1: newgrp (attiva solo per questo comando) +sudo -u nome_utente -i docker ps + +# Opzione 2: su - (nuova sessione login) +su - nome_utente +docker ps + +# Opzione 3: logout/login (sessione interattiva) +``` + +## Rimuovi Utente dal Gruppo Docker + +```bash +# Rimuovi utente dal gruppo docker +sudo gpasswd -d nome_utente docker + +# Oppure modifica i gruppi supplementari +sudo usermod -G nome_utente nome_utente +``` + +## Vedi Anche + +- [Tutorial: Permessi Docker tramite Gruppi](../tutorial/02-docker-group-permissions.md) +- [Reference: Permessi Socket Docker](../reference/docker-socket-permissions.md) +``` + +**File 2: labs/lab-01-iam/how-to-guides/verify-non-root-container.md** +```markdown +# How-To: Verificare che un Container Giri come Non-Root + +Guida rapida per verificare che un container non giri come utente root (requisito INF-01). + +## Metodo 1: docker exec whoami + +```bash +docker exec whoami +``` + +Se mostra `root`, il container NON è conforme a INF-01. + +## Metodo 2: docker inspect + +```bash +docker inspect --format='{{.Config.User}}' +``` + +- Se vuoto, il container gira come root (default) +- Se mostra un UID/nome, il container gira come quell'utente + +## Metodo 3: docker top + +```bash +docker top +``` + +Guarda la colonna USER: +- `0` o `root` = NON conforme +- Altri UID (es. `1000`) = CONFORME + +## Verifica Tutti i Container + +```bash +# Verifica tutti i container in esecuzione +docker ps --format "{{.Names}}" | while read container; do + echo "Container: $container" + docker exec $container whoami 2>/dev/null || echo "N/A" +done +``` + +## Verifica con docker-compose + +```bash +# Verifica tutti i servizi nel compose file +docker-compose ps --services | while read service; do + container=$(docker-compose ps -q $service) + echo "Service: $service, User: $(docker exec $container whoami)" +done +``` + +## Vedi Anche + +- [Tutorial: Container Non-Root](../tutorial/03-verify-iam-setup.md) +- [Test: Script Non-Root](../tests/03-non-root-test.sh) +``` + +**File 3: labs/lab-01-iam/how-to-guides/reset-docker-permissions.md** +```markdown +# How-To: Reset dei Permessi Docker + +Guida per ripristinare i permessi del socket Docker e risolvere problemi di accesso. + +## Reset dei Permessi del Socket + +```bash +# Ferma il demone Docker +sudo systemctl stop docker + +# Ripristina la proprietà del socket +sudo chown root:docker /var/run/docker.sock + +# Ripristina i permessi (660 = rw-rw----) +sudo chmod 660 /var/run/docker.sock + +# Riavvia Docker +sudo systemctl start docker +``` + +## Verifica + +```bash +# Verifica i permessi del socket +ls -l /var/run/docker.sock +``` + +Atteso: `srw-rw---- 1 root docker ...` + +## Ricrea il Gruppo Docker + +Se il gruppo docker è stato eliminato: + +```bash +# Crea il gruppo docker +sudo groupadd docker + +# Riavvia Docker per assicurarti che il socket appartenga al gruppo +sudo systemctl restart docker +``` + +## Risoluzione Problemi Comuni + +### Problema: "Got permission denied while trying to connect" + +**Causa:** Utente non nel gruppo docker o permessi socket errati + +**Soluzione:** +```bash +# Verifica gruppi utente +groups $USER + +# Aggiungi al gruppo se necessario +sudo usermod -aG docker $USER + +# Verifica permessi socket +ls -l /var/run/docker.sock + +# Correggi se necessario +sudo chmod 660 /var/run/docker.sock +sudo chown root:docker /var/run/docker.sock +``` + +### Problema: Socket non esiste + +**Causa:** Docker non è in esecuzione + +**Soluzione:** +```bash +# Avvia Docker +sudo systemctl start docker + +# Verifica che il socket sia stato creato +ls -l /var/run/docker.sock +``` + +### Problema: Group membership non attiva + +**Causa:** I gruppi vengono valutati al login + +**Soluzione:** +```bash +# Attiva il gruppo per la sessione corrente +newgrp docker + +# Oppure fai login di nuovo +su - $USER +``` + +## Reset Completo dell'Ambiente + +Per reset completo dell'ambiente Docker tra i lab: + +```bash +# Usa lo script di reset +bash scripts/reset-env.sh + +# Oppure reset manuale +docker stop $(docker ps -aq) +docker rm $(docker ps -aq) +docker system prune -a +``` + +## Vedi Anche + +- [How-To: Ambiente Reset](../../how-to-guides/reset-docker-environment.md) +- [Tutorial: Permessi Docker](../tutorial/02-docker-group-permissions.md) +``` + +Key points: +- Procedure-focused, not step-by-step learning +- Command-first structure +- Links to tutorials and reference +- Troubleshooting common issues + + + test -f labs/lab-01-iam/how-to-guides/add-user-to-docker-group.md && test -f labs/lab-01-iam/how-to-guides/verify-non-root-container.md && test -f labs/lab-01-iam/how-to-guides/reset-docker-permissions.md && grep -q "##" labs/lab-01-iam/how-to-guides/*.md | wc -l | awk '{if($1>=9) print "PASS"; else print "FAIL: How-to guides need more sections"}' + + Three how-to guides created for common procedures + + + + Task 5: Create Reference Documents + labs/lab-01-iam/reference/docker-socket-permissions.md, labs/lab-01-iam/reference/linux-users-groups.md, labs/lab-01-iam/reference/iam-parallels.md + +Create three reference documents with technical specifications: + +**File 1: labs/lab-01-iam/reference/docker-socket-permissions.md** +```markdown +# Reference: Permessi del Socket Docker + +Specifiche tecniche del socket Docker Unix domain socket e controllo accessi. + +## Percorso del Socket + +``` +/var/run/docker.sock +``` + +## Permessi Standard + +``` +srw-rw---- 1 root docker 0 Mar 24 20:00 /var/run/docker.sock +``` + +| Campo | Valore | Significato | +|-------|--------|-------------| +| Tipo | `s` | Socket Unix domain | +| Permessi | `rw-rw----` (660) | Owner e gruppo possono leggere/scrivere | +| Owner | `root` | Il demone Docker gira come root | +| Gruppo | `docker` | Membri del gruppo docker possono accedere | +| Altro | `---` | Nessun altro permesso | + +## Controllo Accessi + +L'accesso al socket è controllato dai permessi file system standard Linux: + +### Chi puo accedere? + +| Utente | Accesso | Motivo | +|--------|---------|--------| +| root | Si | Proprietario del socket | +| Membri del gruppo docker | Si | Permesso gruppo (rw) | +| Altri utenti | No | Nessun permesso | + +### Verifica Permessi + +```bash +# Mostra permessi dettagliati +stat -c "%a %U %G %n" /var/run/docker.sock +# Output: 660 root docker /var/run/docker.sock + +# Verifica gruppo del socket +stat -c "%G" /var/run/docker.sock +# Output: docker + +# Verifica proprietario +stat -c "%U" /var/run/docker.sock +# Output: root +``` + +## Modifica Permessi + +```bash +# Modifica permessi (non raccomandato: 666 permette accesso a tutti) +sudo chmod 660 /var/run/docker.sock + +# Modifica gruppo +sudo chown root:docker /var/run/docker.sock + +# Modifica proprietario (non raccomandato) +sudo chown $USER /var/run/docker.sock +``` + +⚠️ **WARNING:** Non usare mai `chmod 666` o `777` sul socket Docker. Questo elimina tutti i controlli di accesso. + +## Docker Daemon e Socket + +### Allocazione Socket + +Il demone Docker crea il socket all'avvio: + +```bash +# Avvia demone (crea/ricrea socket) +sudo systemctl start docker + +# Riavvia per ripristinare permessi +sudo systemctl restart docker +``` + +### Rootless Docker + +Con rootless Docker, il socket si trova in: + +``` +$XDG_RUNTIME_DIR/docker.sock +# Tipicamente: /run/user/1000/docker.sock +``` + +## Troubleshooting + +| Problema | Diagnosi | Soluzione | +|----------|----------|-----------| +| Permission denied | Utente non in gruppo docker | `sudo usermod -aG docker $USER` | +| Socket non trovato | Docker non in esecuzione | `sudo systemctl start docker` | +| Permessi errati | chmod eseguito sul socket | `sudo systemctl restart docker` | +| Gruppo errato | Chown sul socket | `sudo chown root:docker /var/run/docker.sock` | + +## Comandi Rapidi + +```bash +# Verifica permessi attuali +ls -l /var/run/docker.sock + +# Verifica chi puo accedere +namei -l /var/run/docker.sock + +# Trova processi con handle al socket +sudo lsof /var/run/docker.sock +``` + +## Vedi Anche + +- [Reference: Utenti e Gruppi Linux](./linux-users-groups.md) +- [Explanation: Parallelismi IAM](../explanation/docker-iam-parallels.md) +``` + +**File 2: labs/lab-01-iam/reference/linux-users-groups.md** +```markdown +# Reference: Utenti e Gruppi Linux + +Specifiche tecniche per la gestione utenti e gruppi in Linux per il lab IAM. + +## Comandi Utente + +### useradd - Crea utente + +```bash +sudo useradd -m -s /bin/bash nome_utente +``` + +| Flag | Significato | +|------|-------------| +| `-m` | Crea home directory | +| `-s /bin/bash` | Imposta shell di login | +| `-G group1,group2` | Aggiunge a gruppi supplementari | +| `-u 1000` | Specifica UID | + +### usermod - Modifica utente + +```bash +# Aggiungi a gruppo (append) +sudo usermod -aG docker nome_utente + +# Modifica shell +sudo usermod -s /bin/zsh nome_utente + +# Modifica gruppi supplementari (sovrascrive) +sudo usermod -G docker,nome_utente nome_utente +``` + +⚠️ **IMPORTANTE:** Usa `-aG` (append) per aggiungere a un gruppo senza rimuovere gli altri. + +### userdel - Elimina utente + +```bash +# Elimina utente (mantieni home) +sudo userdel nome_utente + +# Elimina utente e home directory +sudo userdel -r nome_utente +``` + +### passwd - Imposta password + +```bash +# Imposta password per utente +sudo passwd nome_utente + +# Cambia la tua password +passwd +``` + +## Comandi Gruppo + +### groupadd - Crea gruppo + +```bash +sudo groupadd docker +``` + +### groupmod - Modifica gruppo + +```bash +# Rinomina gruppo +sudo groupmod -n nuovo_nome vecchio_nome + +# Modifica GID +sudo groupmod -g 1001 docker +``` + +### gpasswd - Gestisci membri gruppo + +```bash +# Aggiungi utente al gruppo +sudo gpasswd -a utente gruppo + +# Rimuovi utente dal gruppo +sudo gpasswd -d utente gruppo + +# Imposta amministratori gruppo +sudo gpasswd -A utente1,utente2 gruppo +``` + +### groupdel - Elimina gruppo + +```bash +sudo groupdelete docker +``` + +## Comandi Informazione + +### id - Mostra info utente + +```bash +# Mostra UID, GID e gruppi dell'utente corrente +id + +# Mostra info di un utente specifico +id nome_utente + +# Solo UID +id -u nome_utente + +# Solo gruppi +id -G nome_utente +``` + +Output esempio: +``` +uid=1001(lab01_student) gid=1001(lab01_student) groups=1001(lab01_student),999(docker) +``` + +### groups - Mostra gruppi utente + +```bash +# Gruppi dell'utente corrente +groups + +# Gruppi di un utente specifico +groups nome_utente +``` + +### getent - Query database di sistema + +```bash +# Verifica che un gruppo esista +getent group docker + +# Output: docker:x:999:utente1,utente2 +# nome:x:GID:lista_membri + +# Verifica che un utente esista +getent passwd nome_utente + +# Output: nome_utente:x:1001:1001:,,,:/home/nome_utente:/bin/bash +# nome:x:UID:GID:commento:home:shell +``` + +## File di Configurazione + +### /etc/passwd + +```bash +# Visualizza tutti gli utenti +cat /etc/passwd + +# Aggiungi utente manualmente (non raccomandato) +echo "utente:x:1001:1001::/home/utente:/bin/bash" | sudo tee -a /etc/passwd +``` + +Formato: +``` +username:x:UID:GID:commento:home:shell +``` + +### /etc/group + +```bash +# Visualizza tutti i gruppi +cat /etc/group + +# Aggiungi gruppo manualmente +echo "docker:x:999:utente1,utente2" | sudo tee -a /etc/group +``` + +Formato: +``` +gruppo:x:GID:lista_membri +``` + +### /etc/shadow + +```bash +# Password e scadenza (richiede root) +sudo cat /etc/shadow +``` + +## Valutazione Gruppi al Login + +I gruppi vengono valutati quando l'utente fa login: + +| Momento | Gruppi Valutati | +|---------|-----------------| +| Avvio sistema | No | +| Login interattivo | Si | +| `su - utente` | Si (nuovo login) | +| `newgrp group` | Si (solo sessione corrente) | +| `sudo -u utente cmd` | No (gruppi dell'utente originale) | +| Aggiunta gruppo con usermod | No (fino al prossimo login) | + +## UID/GID Standard + +| UID/GID | Utente/Gruppo | +|---------|---------------| +| 0 | root | +| 1-999 | Utenti di sistema | +| 1000-60000 | Utenti normali | +| 999 | docker (tipico) | + +## Comandi Rapidi + +```bash +# Lista tutti gli utenti umani +cat /etc/passwd | grep ':[1-9][0-9][0-9][0-9]:' + +# Lista tutti i gruppi +cat /etc/group | cut -d: -f1 + +# Utenti in un gruppo +members gruppo +# Oppure: +getent group gruppo | cut -d: -f4 +``` + +## Vedi Anche + +- [Reference: Permessi Socket Docker](./docker-socket-permissions.md) +- [How-To: Aggiungi Utente al Gruppo Docker](../how-to-guides/add-user-to-docker-group.md) +``` + +**File 3: labs/lab-01-iam/reference/iam-parallels.md** +```markdown +# Reference: Parallelismi Docker e AWS IAM + +Tabella di riferimento rapido per i parallelismi tra concetti Docker/Linux e AWS IAM. + +## Tabella Parallelismi + +| Concetto Locale | AWS IAM Equivalente | Descrizione | +|-----------------|---------------------|-------------| +| Utente Linux (`student1`) | IAM User | Identità che può autenticarsi | +| Gruppo Linux (`docker`) | IAM Group | Collezione di utenti con stessi permessi | +| Permessi file/socket | IAM Policy | Regole che definiscono cosa è permesso | +| `/var/run/docker.sock` | Service Endpoint | Risorsa protetta da controlli accesso | +| `sudo` elevation | IAM Role Assumption | Temporanea elevazione privilegi | +| `usermod -aG docker` | `AttachUserPolicy` | Assegna permessi a utente | +| Appartenenza gruppo `docker` | Policy attachment | Permessi attivi per utente | + +## Comandi a Confronto + +### Creazione Utente + +| Operazione Locale | Comando AWS | +|-------------------|-------------| +| `sudo useradd -m user` | `aws iam create-user --user-name user` | +| `sudo passwd user` | `aws iam create-login-profile --user-name user --password Pass123!` | + +### Gestione Permessi + +| Operazione Locale | Comando AWS | +|-------------------|-------------| +| `sudo usermod -aG docker user` | `aws iam attach-user-policy --user-name user --policy-arn arn:aws:iam::aws:policy/PowerUserAccess` | +| `sudo gpasswd -d user docker` | `aws iam detach-user-policy --user-name user --policy-arn arn:aws:iam::aws:policy/PowerUserAccess` | + +### Verifica Permessi + +| Operazione Locale | Comando AWS | +|-------------------|-------------| +| `groups user` | `aws iam list-attached-user-policies --user-name user` | +| `id user` | `aws iam get-user --user-name user` | +| `sudo -u user docker ps` | `aws sts get-caller-identity` | + +### Elevazione Privilegi + +| Operazione Locale | Comando AWS | +|-------------------|-------------| +| `sudo command` | Assumere IAM Role | +| `su - root` | `aws sts assume-role` | + +## Differenze Chiave + +| Aspetto | Locale | Cloud AWS | +|---------|--------|-----------| +| Autenticazione | Password, SSH key | Access key, Secret key, Session token | +| Autorizzazione | Gruppi Linux, permessi file | IAM Policies, JSON document | +| Scope | Singolo host | Account AWS intero | +| Audit | `last`, `/var/log/auth.log` | CloudTrail | +| MFA | Non disponibile | Disponibile | + +## Modelli di Policy + +### Modello Allow + +**Locale:** +```bash +# Utente nel gruppo docker puo accedere al socket +sudo usermod -aG docker utente +``` + +**AWS:** +```json +{ + "Effect": "Allow", + "Action": "docker:*", + "Resource": "*" +} +``` + +### Modello Deny + +**Locale:** +```bash +# Utente NON nel gruppo docker non puo accedere +# (default deny) +``` + +**AWS:** +```json +{ + "Effect": "Deny", + "Action": "docker:*", + "Resource": "*" +} +``` + +## Best Practices Comuni + +| Best Practice | Locale | Cloud | +|---------------|--------|-------| +| Minimo privilegio | Utenti non-root | IAM Policies restrittive | +| Separazione doveri | Gruppi distinti | Gruppi IAM distinti | +| Audit logging | auth.log | CloudTrail | +| Rotazione credenziali | `chage` | Rotate access keys | + +## Comandi Utili + +```bash +# Verifica membri gruppo docker +getent group docker + +# Simulazione:_lista politiche IAM +aws iam list-attached-user-policies --user-name user + +# Verifica permessi socket +ls -l /var/run/docker.sock + +# Simulazione:_simula accesso AWS +aws sts get-caller-identity +``` + +## Vedi Anche + +- [Explanation: Docker IAM Parallels](../explanation/docker-iam-parallels.md) +- [Tutorial: Permessi Docker](../tutorial/02-docker-group-permissions.md) +``` + +Key points: +- Pure reference material (no tutorial content) +- Tables and specifications +- Command comparisons +- Quick reference format + + + test -f labs/lab-01-iam/reference/docker-socket-permissions.md && test -f labs/lab-01-iam/reference/linux-users-groups.md && test -f labs/lab-01-iam/reference/iam-parallels.md && grep -q "|" labs/lab-01-iam/reference/*.md | wc -l | awk '{if($1>=15) print "PASS"; else print "FAIL: Reference docs need more tables"}' + + Three reference documents created with technical specifications + + + + Task 6: Create Explanation Document (IAM Parallels) + labs/lab-01-iam/explanation/docker-iam-parallels.md + +Create explanation document that connects local Docker concepts to cloud IAM: + +```markdown +# Explanation: Parallelismi tra Docker Permissions e AWS IAM + +In questo documento esploreremo come i permessi Docker e la gestione utenti Linux simulano i concetti di Identity and Access Management (IAM) nei cloud provider come AWS. Comprendere questi parallelismi ti aiuterà a trasferire le conoscenze acquisite localmente agli ambienti cloud reali. + +## Cos'è IAM? + +**IAM (Identity and Access Management)** è il framework che controlla: +- **Identity:** Chi sei (autenticazione) +- **Access:** Cosa puoi fare (autorizzazione) + +AWS IAM, Azure IAM, Google Cloud IAM sono tutti basati sullo stesso concetto fondamentale: le identità hanno permessi specifici su risorse specifiche. + +--- + +## Il Parallelismo Fondamentale + +### Utente Linux = IAM User + +| Locale | Cloud | +|--------|-------| +| Un utente Linux (`lab01_student`) | Un IAM User (`alice`) | +| Può fare login al sistema | Può fare login ad AWS | +| Ha UID univoco | Ha User ID univoco (AIDAI...) | +| Appartiene a gruppi | Appartiene a IAM Groups | + +**Similitudine:** Entrambi rappresentano un'identità umana o di servizio che può autenticarsi. + +**Differenza:** Gli utenti Linux sono locali a una singola macchina, gli IAM Users sono globali all'account AWS. + +### Gruppo Linux = IAM Group + +| Locale | Cloud | +|--------|-------| +| Gruppo `docker` | IAM Group `Developers` | +| Membri ereditano permessi del gruppo | Membri ereditano policies del gruppo | +| Utente può essere in multipli gruppi | Utente può essere in multipli gruppi | +| `groups user` mostra membrianze | `aws iam list-groups-for-user` | + +**Similitudine:** I gruppi rendono facile gestire i permessi per molti utenti. Aggiungi un utente al gruppo e ha automaticamente tutti i permessi del gruppo. + +**Differenza:** I gruppi Linux sono definiti localmente, i gruppi IAM sono definiti centralmente e possono avere utenti跨-region. + +### Socket Docker = Service Endpoint + +| Locale | Cloud | +|--------|-------| +| `/var/run/docker.sock` | AWS API endpoint (`https://ec2.amazonaws.com`) | +| Accessibile solo con permessi corretti | Accessibile solo con credenziali valide | +| `chmod 660` limita l'accesso | IAM policies limitano l'accesso | + +**Similitudine:** Entrambe sono risorse protette che richiedono autorizzazione per essere utilizzate. + +**Differenza:** Il socket Docker è un file Unix locale, gli API endpoint sono servizi web remoti. + +### Permessi File = IAM Policy + +| Locale | Cloud | +|--------|-------| +| `rw-rw----` su socket | JSON policy con `Effect: Allow/Deny` | +| Utente deve essere nel gruppo `docker` | Utente deve avere policy permessiva | +| `chmod` cambia permessi | `AttachUserPolicy` assegna policy | + +**Similitudine:** Entrambi definiscono regole esplicite su chi puo fare cosa. + +**Differenza:** I permessi Linux sono semplici (read/write/execute), le IAM policies sono espressioni complesse con condizioni, wildcard, e resource-level permissions. + +--- + +## Esempio Pratico: Setup di un Nuovo Sviluppatore + +### Scenario Locale + +```bash +# 1. Crea utente per il nuovo sviluppatore +sudo useradd -m -s /bin/bash mario_rossi + +# 2. Aggiungi al gruppo docker (permette di lanciare container) +sudo usermod -aG docker mario_rossi + +# 3. Verifica +groups mario_rossi +# Output: mario_rossi : mario_rossi docker + +# 4. Mario ora puo lanciare container +sudo -u mario_rossi docker run alpine whoami +``` + +### Scenario Cloud AWS (Equivalente) + +```bash +# 1. Crea IAM User per il nuovo sviluppatore +aws iam create-user --user-name mario_rossi + +# 2. Crea gruppo per sviluppatori (se non esiste) +aws iam create-group --group-name Developers + +# 3. Allega policy al gruppo (permette di usare EC2/containers) +aws iam attach-group-policy \ + --group-name Developers \ + --policy-arn arn:aws:iam::aws:policy/PowerUserAccess + +# 4. Aggiungi utente al gruppo +aws iam add-user-to-group \ + --group-name Developers \ + --user-name mario_rossi + +# 5. Verifica +aws iam list-groups-for-user --user-name mario_rossi +# Output: Groups: [Developers] + +# 6. Mario ora puo lanciare istanze EC2 (equivalente a container) +aws ec2 run-instances --image-id ami-12345 ... +``` + +**Parallelismo:** +- Entrambi iniziano creando un'identità +- Entrambi usano gruppi per gestire i permessi +- Entrambi verificano l'appartenenza al gruppo +- Entrambi ora possono lanciare risorse (container/EC2) + +--- + +## Il Principio del Minimo Privilegio + +### Locale: Non-Root Containers + +**Perché non root?** +- Root in container = root sull'host (se vulnerabilità kernel) +- Root puo leggere/scrivere qualsiasi file +- Root puo modificare configurazioni di sistema + +**Soluzione locale:** +```dockerfile +# Dockerfile con utente non-root +FROM alpine:3.19 +RUN adduser -D -u 1000 appuser +USER appuser +CMD ["sh", "-c", "whoami"] +``` + +**Verifica:** +```bash +docker exec container whoami +# Output: appuser (NON root) +``` + +### Cloud: IAM Policies Restrittive + +**Perché policy minime?** +- Chiave compromessa = danno limitato +- Principio di least privilege +- Audit e compliance requirements + +**Soluzione cloud:** +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:PutObject" + ], + "Resource": "arn:aws:s3:::my-bucket/*" + } + ] +} +``` + +**Verifica:** +```bash +# Simula accesso dell'utente +aws iam simulate-principal-policy \ + --policy-source-arn arn:aws:iam::123456789012:user/mario_rossi \ + --action-names s3:DeleteBucket \ + # Output: Decision: Deny (policy non permette DeleteBucket) +``` + +**Parallelismo:** +- Entrambi limitano cosa l'identità puo fare +- Entrambi riducono la superficie di attacco +- Entrambi sono verificabili tramite test + +--- + +## Differenze tra Locale e Cloud + +### 1. Scope dei Permessi + +| Locale | Cloud | +|--------|-------| +| Permessi validi solo su questa macchina | Permessi validi per tutto l'account AWS | +| Utente locale accede solo a risorse locali | IAM user accede a risorse globali | +| Gruppi definiti in `/etc/group` | Gruppi definiti in IAM (centralizzato) | + +**Implicazione:** Nel cloud, un utente con permessi S3 puo accedere a tutti i bucket S3 nell'account, non solo a quelli "vicini" come nel filesystem locale. + +### 2. Complessità delle Policy + +| Locale | Cloud | +|--------|-------| +| Semplice: lettura/scrittura/esecuzione | Complesso: conditions, IP restrictions, MFA | +| Basato su owner/group/other | Basato su JSON con wildcards | +| Binario: o hai permesso o no | Granulare: resource-level, tag-based, time-based | + +**Esempio Cloud (non possibile localmente):** +```json +{ + "Effect": "Allow", + "Action": "s3:*", + "Resource": "*", + "Condition": { + "IpAddress": { + "aws:SourceIp": ["203.0.113.0/24"] + }, + "DateGreaterThan": { + "aws:CurrentTime": "2024-01-01T00:00:00Z" + }, + "Bool": { + "aws:MultiFactorAuthPresent": "true" + } + } +} +``` + +**Implicazione:** Le IAM policies sono piu potenti ma anche piu complesse da capire e debuggare. + +### 3. Audit e Logging + +| Locale | Cloud | +|--------|-------| +| `/var/log/auth.log` per login sudo | CloudTrail per tutte le chiamate API | +| `last` mostra ultimi login | IAM Access Analyzer mostra attivita | +| Manuale correlare eventi | Ricerche automatiche su CloudTrail Logs | + +**Implicazione:** Nel cloud hai audit trail automatico, completo e ricercabile. Localmente devi configurare e mantenere i log. + +### 4. Autenticazione + +| Locale | Cloud | +|--------|-------| +| Password, SSH key | Access Key ID, Secret Access Key, Session Token | +| Password scade mai (default) | Access keys devono essere ruotate regolarmente | +| MFA non disponibile | MFA obbligatorio per root/users in molte organizzazioni | + +**Implicazione:** Nel cloud, l'autenticazione e piu sicura di default (rotazione automatica, MFA, sessioni temporanee). + +--- + +## Comandi Equivalenti: Quick Reference + +| Operazione | Locale | Cloud AWS | +|------------|--------|-----------| +| **Crea utente** | `sudo useradd -m user` | `aws iam create-user --user-name user` | +| **Aggiungi a gruppo** | `sudo usermod -aG docker user` | `aws iam add-user-to-group --group-name Developers --user-name user` | +| **Verifica permessi** | `groups user` | `aws iam list-attached-user-policies --user-name user` | +| **Test accesso** | `sudo -u user docker ps` | `aws sts get-caller-identity` | +| **Eleva privilegi** | `sudo command` | `aws sts assume-role` | +| **Revoca permessi** | `sudo gpasswd -d user docker` | `aws iam detach-user-policy --user-name user --policy-arn ...` | +| **Elimina utente** | `sudo userdel user` | `aws iam delete-user --user-name user` | + +--- + +## Best Practices Transferibili + +### 1. Mai Usare Root per Lavoro Normale + +**Locale:** +```bash +# SBAGLIATO: Log in come root +ssh root@server + +# GIUSTO: Log in come utente normale, usa sudo quando serve +ssh user@server +sudo command +``` + +**Cloud:** +```bash +# SBAGLIATO: Usa root account AWS (l'email con cui ti sei registrato) +# Mai usare root account per operazioni quotidiane + +# GIUSTO: Crea IAM User con permessi limitati +aws iam create-user --user-name daily-ops-user +aws iam attach-user-policy --user-name daily-ops-user --policy-arn ... +``` + +### 2. Usa Gruppi per Gestire Permessi + +**Locale:** +```bash +# Invece di dare permessi a ogni singolo utente +sudo usermod -aG docker user1 +sudo usermod -aG docker user2 +sudo usermod -aG docker user3 + +# Tutti automaticamente ereditano i permessi del gruppo docker +``` + +**Cloud:** +```bash +# Invece di attachare policy a ogni singolo utente +aws iam create-group --group-name Developers +aws iam attach-group-policy --group-name Developers --policy-arn ... +aws iam add-user-to-group --group-name Developers --user-name user1 +aws iam add-user-to-group --group-name Developers --user-name user2 + +# Tutti automaticamente ereditano le policies del gruppo Developers +``` + +### 3. Verifica i Permessi + +**Locale:** +```bash +# Verifica che l'utente abbia i permessi corretti +groups user +id user +sudo -u user docker ps +``` + +**Cloud:** +```bash +# Verifica che l'utente abbia le policies corrette +aws iam list-attached-user-policies --user-name user +aws iam simulate-principal-policy --policy-source-arn ... --action-names s3:GetObject +``` + +--- + +## Conclusione + +I concetti che hai imparato in questo lab - utenti, gruppi, permessi - si applicano direttamente ad AWS IAM e altri cloud provider. La differenza principale e la scala e la complessita: nel cloud, questi concetti sono potenziati con condizioni granulari, audit automatico, e credenziali ruotabili. + +Quando lavorerai con AWS IAM, ricorda: +- IAM User = Utente Linux (identità) +- IAM Group = Gruppo Linux (raccolta di utenti con stessi permessi) +- IAM Policy = Permessi file/socket (regole di accesso) +- Service Endpoint = Socket Docker (risorsa protetta) + +Comprendendo questi parallelismi, sarai in grado di applicare le conoscenze locali al cloud con fiducia. + +--- + +## Approfondimenti + +- [AWS IAM Documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) +- [IAM Best Practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) +- [Tutorial: Permessi Docker](../tutorial/02-docker-group-permissions.md) +- [Reference: Tabella Parallelismi](../reference/iam-parallels.md) +``` + +Key points: +- Clear explanation of IAM concepts +- Side-by-side comparisons +- Practical examples +- Best practices transferable to cloud +- Links to AWS documentation +- Covers PARA-01 (Docker mapped to IAM), PARA-03 (differences documented), PARA-04 (commands shown) + + + test -f labs/lab-01-iam/explanation/docker-iam-parallels.md && grep -q "IAM\|AWS\|differenza\|difference" labs/lab-01-iam/explanation/docker-iam-parallels.md && wc -l labs/lab-01-iam/explanation/docker-iam-parallels.md | awk '{if($1>=80) print "PASS"; else print "FAIL: Explanation too short ("$1" lines, expected 80+)"}' + + Explanation document created with IAM parallels and local-cloud differences + + + + + +1. All 4 Diátaxis document types exist: tutorial/, how-to-guides/, reference/, explanation/ +2. Tutorial follows "little often" principle (small incremental steps) +3. How-to guides are procedure-focused (not tutorial-style) +4. Reference documents are technical specifications without tutorial content +5. Explanation document draws clear parallels between Docker and IAM (PARA-01, PARA-03, PARA-04) +6. All documents use Italian language without emojis +7. All documents have cross-references to related content + + + +1. Tutorial has 3 parts covering user creation, Docker permissions, and verification +2. How-to guides cover common procedures independent of tutorial flow +3. Reference documents provide technical specifications in quick-reference format +4. Explanation document clearly maps Docker concepts to AWS IAM concepts +5. All requirement IDs satisfied: LAB-01, DOCT-01, DOCT-02, DOCT-03, DOCT-04, DOCT-05, PARA-01, PARA-03, PARA-04 + + + +After completion, create `.planning/phases/02-lab-01-iam-sicurezza/02-02-SUMMARY.md` + diff --git a/.planning/phases/02-lab-01-iam-sicurezza/02-03-PLAN.md b/.planning/phases/02-lab-01-iam-sicurezza/02-03-PLAN.md new file mode 100644 index 0000000..567d531 --- /dev/null +++ b/.planning/phases/02-lab-01-iam-sicurezza/02-03-PLAN.md @@ -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" +--- + + +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. + + + +@/home/luca/.claude/get-shit-done/workflows/execute-plan.md +@/home/luca/.claude/get-shit-done/templates/summary.md + + + +@.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 whoami +# Expected output: appuser (NOT root) + +# Method 2: Inspect container configuration +docker inspect --format='{{.State.User}}' + +# Method 3: Check process on host +docker top +# 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 + + + + + + Task 1: Create Dockerfile with non-root user + labs/lab-01-iam/Dockerfile + + - 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) + + +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. + + + 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" + + Dockerfile creates non-root container verified by whoami output + + + + Task 2: Create docker-compose.yml with user directive + labs/lab-01-iam/docker-compose.yml + + - 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 + + +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 + + + 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" + + docker-compose.yml defines service with non-root user directive + + + + Task 3: Create infrastructure verification script + labs/lab-01-iam/tests/04-verify-infrastructure.sh + + - 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 + + +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. + + + chmod +x labs/lab-01-iam/tests/04-verify-infrastructure.sh && cd labs/lab-01-iam && bash ../tests/04-verify-infrastructure.sh + + Infrastructure verification script confirms all requirements satisfied + + + + + +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 + + + +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 + + + +After completion, create `.planning/phases/02-lab-01-iam-sicurezza/02-03-SUMMARY.md` +