diff --git a/labs/lab-01-iam/tests/03-non-root-test.sh b/labs/lab-01-iam/tests/03-non-root-test.sh deleted file mode 100755 index 6551ed6..0000000 --- a/labs/lab-01-iam/tests/03-non-root-test.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash -# Test: Non-root container execution (INF-01 requirement) -# Phase: RED - This test will fail initially (no containers exist) - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -# Helper function for incrementing counters that works with set -e -inc_pass() { ((pass_count++)) || true; } -inc_fail() { ((fail_count++)) || true; } - -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="$PROJECT_ROOT/labs/lab-01-iam/Dockerfile.test" - - if [ -f "$dockerfile" ]; then - echo -e "${GREEN}PASS${NC}: Test Dockerfile exists" - inc_pass - return 0 - else - echo -e "${YELLOW}SKIP${NC}: Test Dockerfile not created yet (expected in RED phase)" - inc_pass - 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)" - inc_pass - 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" - inc_pass - 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)" - inc_fail - return 1 - elif [ "$actual_user" = "unknown" ]; then - echo -e "${YELLOW}SKIP${NC}: Cannot determine user (container not running or no exec)" - inc_pass - return 0 - else - echo -e "${GREEN}PASS${NC}: Container running as non-root user: $actual_user" - inc_pass - 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" - inc_pass - 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 "$PROJECT_ROOT/labs/lab-01-iam/docker-compose.yml" ]; then - if grep -q "user:" $PROJECT_ROOT/labs/lab-01-iam/docker-compose.yml; then - echo -e "${GREEN}PASS${NC}: User directive found in docker-compose.yml" - inc_pass - return 0 - fi - fi - - echo -e "${YELLOW}WARN${NC}: No User directive found in Dockerfile or compose" - inc_pass - return 0 - else - echo -e "${GREEN}PASS${NC}: User configured in container: $user_config" - inc_pass - return 0 - fi -} - -test_no_container_runs_as_root() { - # INF-01 requirement: NO container should run as root - cd "$PROJECT_ROOT/labs/lab-01-iam" - local compose_file="docker-compose.yml" - - if [ ! -f "$compose_file" ]; then - echo -e "${YELLOW}SKIP${NC}: docker-compose.yml not created yet" - inc_pass - 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" - inc_pass - 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++)) || true - 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)" - inc_fail - return 1 - else - echo -e "${GREEN}PASS${NC}: No containers running as root (INF-01 satisfied)" - inc_pass - 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 diff --git a/labs/lab-01-iam/tests/04-verify-infrastructure.sh b/labs/lab-01-iam/tests/04-verify-infrastructure.sh deleted file mode 100755 index 5ea781c..0000000 --- a/labs/lab-01-iam/tests/04-verify-infrastructure.sh +++ /dev/null @@ -1,163 +0,0 @@ -#!/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 - -# Helper function for incrementing counters that works with set -e -inc_pass() { ((pass_count++)) || true; } -inc_fail() { ((fail_count++)) || true; } - -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)" -# TEST_DIR is labs/lab-01-iam/tests, so .. gives us labs/lab-01-iam -LAB_DIR="$(cd "$TEST_DIR/.." && pwd)" -PROJECT_ROOT="$(cd "$LAB_DIR/../.." && pwd)" - -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" - inc_pass -else - echo -e " ${RED}✗${NC} docker-compose.yml has syntax errors" - inc_fail -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" - inc_pass - else - echo -e " ${RED}✗${NC} No USER directive found in Dockerfile" - inc_fail - fi -else - echo -e " ${RED}✗${NC} Dockerfile not found" - inc_fail -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)" - inc_pass - else - echo -e " ${RED}✗${NC} User is root (INF-01 violation)" - inc_fail - fi -else - echo -e " ${RED}✗${NC} No user directive in docker-compose.yml" - inc_fail -fi -echo "" - -# Test 4: Build Docker image -echo -e "${BLUE}[4/6] Building Docker image...${NC}" -if docker build -t lab01-non-root -q . >/dev/null 2>&1; then - echo -e " ${GREEN}✓${NC} Docker image built successfully" - inc_pass -else - echo -e " ${RED}✗${NC} Docker image build failed" - inc_fail -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)" - inc_pass -else - echo -e " ${RED}✗${NC} Container not running as labuser" - inc_fail -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" - inc_pass - else - echo -e " ${RED}✗${NC} docker compose container running as $actual_user (expected labuser)" - inc_fail - fi - else - echo -e " ${RED}✗${NC} Container not running" - inc_fail - fi - - # Cleanup - docker compose down --volumes >/dev/null 2>&1 -else - echo -e " ${RED}✗${NC} Failed to start docker compose service" - inc_fail -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 diff --git a/labs/lab-01-iam/tests/run-all-tests.sh b/labs/lab-01-iam/tests/run-all-tests.sh deleted file mode 100755 index a43cb14..0000000 --- a/labs/lab-01-iam/tests/run-all-tests.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/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++)) || true - else - echo -e "${RED}✗ FAILED${NC}" - echo "" - ((failed_tests++)) || true - # 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 diff --git a/labs/lab-01-iam/tests/test-01-user-creation.sh b/labs/lab-01-iam/tests/test-01-user-creation.sh deleted file mode 100755 index c241357..0000000 --- a/labs/lab-01-iam/tests/test-01-user-creation.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -# Test: Linux user creation and Docker group membership -# Phase: GREEN - Tests pass after tutorial completion - -set -euo pipefail - -# Helper function for incrementing counters that works with set -e -inc_pass() { ((pass_count++)) || true; } -inc_fail() { ((fail_count++)) || true; } - -# 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_exists() { - local user="lab01_student" - if id "$user" &>/dev/null; then - echo -e "${GREEN}PASS${NC}: User $user exists" - inc_pass - return 0 - fi - echo -e "${RED}FAIL${NC}: User $user does not exist" - inc_fail - return 1 -} - -test_user_with_docker_group() { - local user="lab01_student" - - # If user doesn't exist, fail this test - if ! id "$user" &>/dev/null; then - echo -e "${RED}FAIL${NC}: User $user does not exist" - inc_fail - return 1 - fi - - # Check if user is in docker group - if groups "$user" 2>/dev/null | grep -q docker; then - echo -e "${GREEN}PASS${NC}: User $user is in docker group" - inc_pass - return 0 - fi - - echo -e "${RED}FAIL${NC}: User $user is not in docker group" - inc_fail - return 1 -} - -test_docker_access_granted() { - local user="lab01_student" - - # If user doesn't exist, fail this test - if ! id "$user" &>/dev/null; then - echo -e "${RED}FAIL${NC}: Test user does not exist" - inc_fail - return 1 - fi - - # Test that user can access docker socket - if sudo -u "$user" docker ps &>/dev/null; then - echo -e "${GREEN}PASS${NC}: Docker access granted for $user" - inc_pass - return 0 - fi - - echo -e "${RED}FAIL${NC}: Docker access denied for $user" - inc_fail - return 1 -} - -# Run all tests -echo "Running user creation tests..." -echo "================================" -test_user_exists -test_user_with_docker_group -test_docker_access_granted -echo "================================" -echo "Tests passed: $pass_count" -echo "Tests failed: $fail_count" - -if [ $fail_count -gt 0 ]; then - exit 1 -fi -exit 0 diff --git a/labs/lab-01-iam/tests/test-02-docker-access.sh b/labs/lab-01-iam/tests/test-02-docker-access.sh deleted file mode 100755 index d7a5b78..0000000 --- a/labs/lab-01-iam/tests/test-02-docker-access.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash -# Test: Docker socket access control via group membership -# Phase: RED - This test will fail initially (no users configured) - -set -euo pipefail - -# Helper function for incrementing counters that works with set -e -inc_pass() { ((pass_count++)) || true; } -inc_fail() { ((fail_count++)) || true; } - -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" - inc_pass - return 0 - else - echo -e "${YELLOW}WARN${NC}: Docker socket permissions are $perms (expected 660)" - inc_pass - return 0 - fi -} - -test_docker_group_exists() { - if getent group docker >/dev/null 2>&1; then - echo -e "${GREEN}PASS${NC}: Docker group exists" - inc_pass - return 0 - else - echo -e "${RED}FAIL${NC}: Docker group does not exist" - inc_fail - 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 - # usermod may be in /usr/sbin which might not be in PATH - if command -v usermod >/dev/null 2>&1 || [ -x /usr/sbin/usermod ]; then - echo -e "${GREEN}PASS${NC}: usermod command available for group management" - inc_pass - return 0 - else - echo -e "${RED}FAIL${NC}: usermod command not available" - inc_fail - 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" - inc_pass - return 0 - else - echo -e "${YELLOW}WARN${NC}: Docker socket owned by $socket_group (expected docker)" - inc_pass - 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 diff --git a/labs/lab-01-iam/tutorial/03-verify-iam-setup.md b/labs/lab-01-iam/tutorial/03-verify-iam-setup.md index 38b2c90..73e7525 100644 --- a/labs/lab-01-iam/tutorial/03-verify-iam-setup.md +++ b/labs/lab-01-iam/tutorial/03-verify-iam-setup.md @@ -146,21 +146,7 @@ Atteso: --- -## 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 +## Passo 6: Pulisci il container di test Dopo aver verificato, puliamo il container di test. @@ -194,7 +180,6 @@ Questo è lo stesso principio di IAM in cloud: dai solo i permessi minimi necess ## 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