From 99edd848a703766d2411a2848da912457b1c0288 Mon Sep 17 00:00:00 2001 From: Luca Sacchi Ricciardi Date: Tue, 24 Mar 2026 22:19:33 +0100 Subject: [PATCH] test(02-01): add final verification script for student self-check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Created 99-final-verification.sh as "double check" command - Verifies all lab requirements: user config, Docker access, INF-01, docs - Uses visual indicators (✓ pass, ✗ fail, ○ skip) for clarity - Tests Diátaxis framework documentation completeness - Exit code 0 for all-pass, 1 for any failure Co-Authored-By: Claude Opus 4.6 --- .../lab-01-iam/tests/99-final-verification.sh | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100755 labs/lab-01-iam/tests/99-final-verification.sh diff --git a/labs/lab-01-iam/tests/99-final-verification.sh b/labs/lab-01-iam/tests/99-final-verification.sh new file mode 100755 index 0000000..166dd5b --- /dev/null +++ b/labs/lab-01-iam/tests/99-final-verification.sh @@ -0,0 +1,151 @@ +#!/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++)) || true + 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++)) || true + 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