From cfbdb1efc8ebb12ee7ffe03b30c55d348ac44bca Mon Sep 17 00:00:00 2001 From: Luca Sacchi Ricciardi Date: Fri, 3 Apr 2026 17:39:58 +0200 Subject: [PATCH] test(06-01): create test infrastructure for Lab 05 Database & RDS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test Scripts (7 files, 1000+ lines): - 01-database-creation-test.sh: PostgreSQL creation and initialization - 02-private-network-test.sh: Private network isolation (INF-02) - 03-persistence-test.sh: Data persistence verification (INF-04) - 04-security-test.sh: Security compliance (INF-01, INF-02, INF-03) - 99-final-verification.sh: End-to-end student verification - run-all-tests.sh: Test orchestration with fail-fast - quick-test.sh: Quick validation (< 30s) Tests verify: - PostgreSQL in private network → RDS in VPC - Named volume → EBS volume - Resource limits → DB instance class - All INF requirements (01-04) Co-Authored-By: Claude Opus 4.6 --- .../tests/01-database-creation-test.sh | 141 +++++++++ .../tests/02-private-network-test.sh | 151 ++++++++++ .../tests/03-persistence-test.sh | 198 +++++++++++++ .../lab-05-database/tests/04-security-test.sh | 177 ++++++++++++ .../tests/99-final-verification.sh | 272 ++++++++++++++++++ labs/lab-05-database/tests/quick-test.sh | 111 +++++++ labs/lab-05-database/tests/run-all-tests.sh | 93 ++++++ 7 files changed, 1143 insertions(+) create mode 100755 labs/lab-05-database/tests/01-database-creation-test.sh create mode 100755 labs/lab-05-database/tests/02-private-network-test.sh create mode 100755 labs/lab-05-database/tests/03-persistence-test.sh create mode 100755 labs/lab-05-database/tests/04-security-test.sh create mode 100755 labs/lab-05-database/tests/99-final-verification.sh create mode 100755 labs/lab-05-database/tests/quick-test.sh create mode 100755 labs/lab-05-database/tests/run-all-tests.sh diff --git a/labs/lab-05-database/tests/01-database-creation-test.sh b/labs/lab-05-database/tests/01-database-creation-test.sh new file mode 100755 index 0000000..e1e9706 --- /dev/null +++ b/labs/lab-05-database/tests/01-database-creation-test.sh @@ -0,0 +1,141 @@ +#!/bin/bash +# Lab 05 - Database & RDS +# Test 01: Database Creation and Initialization +# Verifica che PostgreSQL sia creato e inizializzato correttamente + +set -euo pipefail + +# Colori per output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Contatori +pass_count=0 +fail_count=0 +skip_count=0 + +# Funzioni helper +inc_pass() { ((pass_count++)) || true; } +inc_fail() { ((fail_count++)) || true; } +inc_skip() { ((skip_count++)) || true; } + +echo "==========================================" +echo "Lab 05 - Test 01: Database Creation" +echo "==========================================" +echo "" + +# Verifica che docker-compose.yml esista +echo -n "[TEST] Verifica docker-compose.yml esista... " +if [ -f "docker-compose.yml" ]; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${YELLOW}SKIP${NC} (docker-compose.yml non trovato)" + inc_skip + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 0 +fi + +# Verifica che il servizio database sia definito +echo -n "[TEST] Verifica servizio 'database' definito... " +if grep -q "database:" docker-compose.yml; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (servizio 'database' non trovato)" + inc_fail +fi + +# Verifica che l'immagine sia PostgreSQL +echo -n "[TEST] Verifica immagine PostgreSQL... " +if grep -q "image: postgres" docker-compose.yml; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (immagine PostgreSQL non trovata)" + inc_fail +fi + +# Verifica variabili ambiente PostgreSQL +echo -n "[TEST] Verifica POSTGRES_DB definito... " +if grep -q "POSTGRES_DB:" docker-compose.yml; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (POSTGRES_DB non definito)" + inc_fail +fi + +echo -n "[TEST] Verifica POSTGRES_USER definito... " +if grep -q "POSTGRES_USER:" docker-compose.yml; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (POSTGRES_USER non definito)" + inc_fail +fi + +echo -n "[TEST] Verifica POSTGRES_PASSWORD definito... " +if grep -q "POSTGRES_PASSWORD:" docker-compose.yml; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (POSTGRES_PASSWORD non definito)" + inc_fail +fi + +# Se i container non sono in esecuzione, skip i test dinamici +echo "" +echo -n "[TEST] Verifica container database in esecuzione... " +if docker ps --format '{{{{Names}}}}' | grep -q "^lab05-db$"; then + echo -e "${GREEN}PASS${NC}" + inc_pass + + # Verifica healthcheck + echo -n "[TEST] Verifica healthcheck configurato... " + if docker inspect lab05-db --format '{{.State.Health.Status}}' &>/dev/null; then + echo -e "${GREEN}PASS${NC}" + inc_pass + + echo -n "[TEST] Verifica healthcheck status... " + health_status=$(docker inspect lab05-db --format '{{.State.Health.Status}}') + if [ "$health_status" = "healthy" ] || [ "$health_status" = "starting" ]; then + echo -e "${GREEN}PASS${NC} ($health_status)" + inc_pass + else + echo -e "${YELLOW}WARN${NC} ($health_status)" + inc_pass + fi + else + echo -e "${RED}FAIL${NC} (nessun healthcheck)" + inc_fail + fi + + # Verifica pg_isready disponibile + echo -n "[TEST] Verifica pg_isready disponibile... " + if docker exec lab05-db pg_isready &>/dev/null; then + echo -e "${GREEN}PASS${NC}" + inc_pass + else + echo -e "${YELLOW}SKIP${NC} (pg_isready non ancora pronto)" + inc_skip + fi +else + echo -e "${YELLOW}SKIP${NC} (container non in esecuzione)" + inc_skip + echo -e "${YELLOW}Avviare i container con: docker-compose up -d${NC}" +fi + +echo "" +echo "==========================================" +echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" +echo "==========================================" + +if [ $fail_count -gt 0 ]; then + exit 1 +fi + +exit 0 diff --git a/labs/lab-05-database/tests/02-private-network-test.sh b/labs/lab-05-database/tests/02-private-network-test.sh new file mode 100755 index 0000000..d868b62 --- /dev/null +++ b/labs/lab-05-database/tests/02-private-network-test.sh @@ -0,0 +1,151 @@ +#!/bin/bash +# Lab 05 - Database & RDS +# Test 02: Private Network Isolation +# Verifica che il database sia in una rete privata e non sia accessibile dall'host + +set -euo pipefail + +# Colori per output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Contatori +pass_count=0 +fail_count=0 +skip_count=0 + +# Funzioni helper +inc_pass() { ((pass_count++)) || true; } +inc_fail() { ((fail_count++)) || true; } +inc_skip() { ((skip_count++)) || true; } + +echo "==========================================" +echo "Lab 05 - Test 02: Private Network Isolation" +echo "==========================================" +echo "" + +# Verifica che docker-compose.yml esista +echo -n "[TEST] Verifica docker-compose.yml esista... " +if [ -f "docker-compose.yml" ]; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${YELLOW}SKIP${NC} (docker-compose.yml non trovato)" + inc_skip + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 0 +fi + +# Verifica che il database sia in una rete privata +echo -n "[TEST] Verifica database in rete 'vpc-private'... " +if grep -A 10 "database:" docker-compose.yml | grep -q "vpc-private"; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (database non in rete vpc-private)" + inc_fail + echo "Il database deve essere nella rete privata per simulare RDS in VPC" +fi + +# Verifica che la rete privata sia configurata come internal +echo -n "[TEST] Verifica rete 'vpc-private' con flag internal... " +if grep -A 5 "vpc-private:" docker-compose.yml | grep -q "internal: true"; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${YELLOW}WARN${NC} (rete privata senza flag internal)" + inc_skip +fi + +# Verifica che NON ci siano porte esposte per il database (INF-02) +echo -n "[TEST] Verifica NESSUNA porta esposta per database (INF-02)... " +if grep -A 20 "database:" docker-compose.yml | grep -q "ports:"; then + # Se ci sono porte, verifica che siano solo 127.0.0.1 + if grep -A 20 "database:" docker-compose.yml | grep "ports:" -A 1 | grep -q "127.0.0.1"; then + echo -e "${YELLOW}WARN${NC} (porta su 127.0.0.1 - database RDS reale non espone porte)" + inc_skip + else + echo -e "${RED}FAIL${NC} (porta esposta su host - INF-02 violation)" + inc_fail + echo "RDS in VPC privata NON espone porte sull'host" + fi +else + echo -e "${GREEN}PASS${NC} (nessuna porta esposta)" + inc_pass +fi + +# Se i container non sono in esecuzione, skip i test dinamici +echo "" +echo -n "[TEST] Verifica container database in esecuzione... " +if ! docker ps --format '{{{{Names}}}}' | grep -q "^lab05-db$"; then + echo -e "${YELLOW}SKIP${NC} (container non in esecuzione)" + inc_skip + echo -e "${YELLOW}Avviare i container con: docker-compose up -d${NC}" + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 0 +fi + +echo -e "${GREEN}PASS${NC}" +inc_pass + +# Verifica che il database NON sia accessibile dall'host +echo "" +echo "[TEST] Verifica database NON accessibile dall'host..." + +# Ottieni porta se esposta +db_port=$(docker port lab05-db 5432 2>/dev/null || echo "") + +if [ -z "$db_port" ]; then + echo -e " ${GREEN}PASS${NC} (nessuna porta mappata su host)" + inc_pass +else + echo -e " ${RED}FAIL${NC} (porta $db_port mappata su host)" + inc_fail + echo " RDS in VPC privata NON deve essere accessibile dall'host" +fi + +# Verifica che il container sia nella rete privata +echo -n "[TEST] Verifica container connesso a rete vpc-private... " +if docker inspect lab05-db --format '{{range $net, $conf := .NetworkSettings.Networks}}{{$net}}{{end}}' | grep -q "lab05-vpc-private"; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (container non in rete vpc-private)" + inc_fail +fi + +# Verifica isolamento - container in rete pubblica NON può connettersi +echo "" +echo "[TEST] Verifica isolamento tra reti..." + +# Cerca container in rete pubblica +public_container=$(docker ps --format '{{{{Names}}}}' | grep -E "lab05-(web|app|test)" | head -1) + +if [ -n "$public_container" ]; then + echo -n "[TEST] Container pubblico $public_container può connettersi al database... " + if docker exec $public_container pg_isready -h lab05-db -U lab05_user &>/dev/null; then + echo -e "${GREEN}PASS${NC} (connessione consentita - multi-homed app scenario)" + inc_pass + else + echo -e "${YELLOW}SKIP${NC} (connessione fallita - potrebbe essere corretta isolazione)" + inc_skip + fi +else + echo -e "${YELLOW}SKIP${NC} (nessun container pubblico trovato)" + inc_skip +fi + +echo "" +echo "==========================================" +echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" +echo "==========================================" + +if [ $fail_count -gt 0 ]; then + exit 1 +fi + +exit 0 diff --git a/labs/lab-05-database/tests/03-persistence-test.sh b/labs/lab-05-database/tests/03-persistence-test.sh new file mode 100755 index 0000000..0b99980 --- /dev/null +++ b/labs/lab-05-database/tests/03-persistence-test.sh @@ -0,0 +1,198 @@ +#!/bin/bash +# Lab 05 - Database & RDS +# Test 03: Data Persistence (INF-04) +# Verifica che i dati persistano oltre il ciclo di vita del container + +set -euo pipefail + +# Colori per output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Contatori +pass_count=0 +fail_count=0 +skip_count=0 + +# Funzioni helper +inc_pass() { ((pass_count++)) || true; } +inc_fail() { ((fail_count++)) || true; } +inc_skip() { ((skip_count++)) || true; } + +echo "==========================================" +echo "Lab 05 - Test 03: Data Persistence (INF-04)" +echo "==========================================" +echo "" + +# Verifica che docker-compose.yml esista +echo -n "[TEST] Verifica docker-compose.yml esista... " +if [ -f "docker-compose.yml" ]; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${YELLOW}SKIP${NC} (docker-compose.yml non trovato)" + inc_skip + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 0 +fi + +# Verifica che il volume sia definito +echo -n "[TEST] Verifica volume 'db-data' definito... " +if grep -q "db-data:" docker-compose.yml; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (volume db-data non definito)" + inc_fail + echo "INF-04 richiede volume nominativo per persistenza dati" +fi + +# Verifica che il volume sia montato correttamente +echo -n "[TEST] Verifica volume montato su /var/lib/postgresql/data... " +if grep -A 20 "database:" docker-compose.yml | grep -q "/var/lib/postgresql/data"; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (volume non montato correttamente)" + inc_fail +fi + +# Verifica che il volume sia nominativo (non anonymous) +echo -n "[TEST] Verifica volume nominativo (non bind mount)... " +if grep -B 5 -A 5 "db-data:" docker-compose.yml | grep -q "driver: local"; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${YELLOW}WARN${NC} (volume potrebbe non essere nominativo)" + inc_skip +fi + +# Se i container non sono in esecuzione, skip i test dinamici +echo "" +echo -n "[TEST] Verifica container database in esecuzione... " +if ! docker ps --format '{{{{Names}}}}' | grep -q "^lab05-db$"; then + echo -e "${YELLOW}SKIP${NC} (container non in esecuzione)" + inc_skip + echo -e "${YELLOW}Avviare i container con: docker-compose up -d${NC}" + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 0 +fi + +echo -e "${GREEN}PASS${NC}" +inc_pass + +# Verifica che il volume esista +echo -n "[TEST] Verifica volume 'lab05_db-data' esista... " +if docker volume ls --format '{{{{.Name}}}}' | grep -q "^lab05_db-data$"; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (volume non creato)" + inc_fail +fi + +# Test creazione dati +echo "" +echo "[TEST] Verifica creazione e persistenza dati..." + +# Crea tabella di test +echo -n "[TEST] Creazione tabella di test... " +if docker exec lab05-db psql -U lab05_user -d lab05_db -c "CREATE TABLE IF NOT EXISTS persistence_test (id SERIAL PRIMARY KEY, data TEXT);" &>/dev/null; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (impossibile creare tabella)" + inc_fail +fi + +# Inserisci dati di test +echo -n "[TEST] Inserimento dati di test... " +test_data="TEST_PERSISTENCE_$(date +%s)" +if docker exec lab05-db psql -U lab05_user -d lab05_db -c "INSERT INTO persistence_test (data) VALUES ('$test_data');" &>/dev/null; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (impossibile inserire dati)" + inc_fail + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 1 +fi + +# Verifica dati inseriti +echo -n "[TEST] Verifica dati inseriti... " +retrieved_data=$(docker exec lab05-db psql -U lab05_user -d lab05_db -t -c "SELECT data FROM persistence_test WHERE data = '$test_data';" 2>/dev/null | tr -d ' ') +if [ "$retrieved_data" = "$test_data" ]; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (dati non recuperati)" + inc_fail +fi + +# Test riavvio container +echo "" +echo "[TEST] Test persistenza dopo riavvio container..." + +echo -n "[TEST] Riavvio container database... " +if docker restart lab05-db &>/dev/null; then + echo -e "${GREEN}PASS${NC}" + inc_pass + # Attendi che il database sia pronto + sleep 5 +else + echo -e "${RED}FAIL${NC} (impossibile riavviare)" + inc_fail + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 1 +fi + +# Attendi che il database sia pronto +echo -n "[TEST] Attesa database pronto... " +max_attempts=12 +attempt=0 +while [ $attempt -lt $max_attempts ]; do + if docker exec lab05-db pg_isready -U lab05_user &>/dev/null; then + echo -e "${GREEN}PASS${NC}" + inc_pass + break + fi + ((attempt++)) || true + sleep 1 +done + +if [ $attempt -eq $max_attempts ]; then + echo -e "${RED}FAIL${NC} (database non pronto)" + inc_fail + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 1 +fi + +# Verifica dati dopo riavvio +echo -n "[TEST] Verifica dati dopo riavvio... " +retrieved_data=$(docker exec lab05-db psql -U lab05_user -d lab05_db -t -c "SELECT data FROM persistence_test WHERE data = '$test_data';" 2>/dev/null | tr -d ' ') +if [ "$retrieved_data" = "$test_data" ]; then + echo -e "${GREEN}PASS${NC} (dati persistiti correttamente)" + inc_pass +else + echo -e "${RED}FAIL${NC} (dati persi dopo riavvio)" + inc_fail + echo "INF-04 VIOLATION: i dati devono persistere oltre il riavvio" +fi + +echo "" +echo "==========================================" +echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" +echo "==========================================" + +if [ $fail_count -gt 0 ]; then + exit 1 +fi + +exit 0 diff --git a/labs/lab-05-database/tests/04-security-test.sh b/labs/lab-05-database/tests/04-security-test.sh new file mode 100755 index 0000000..ec7a2c7 --- /dev/null +++ b/labs/lab-05-database/tests/04-security-test.sh @@ -0,0 +1,177 @@ +#!/bin/bash +# Lab 05 - Database & RDS +# Test 04: Security Compliance (INF-01, INF-02, INF-03) +# Verifica conformità sicurezza: non-root, no host ports, resource limits + +set -euo pipefail + +# Colori per output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Contatori +pass_count=0 +fail_count=0 +skip_count=0 + +# Funzioni helper +inc_pass() { ((pass_count++)) || true; } +inc_fail() { ((fail_count++)) || true; } +inc_skip() { ((skip_count++)) || true; } + +echo "==========================================" +echo "Lab 05 - Test 04: Security Compliance" +echo "==========================================" +echo "" + +# Verifica che docker-compose.yml esista +echo -n "[TEST] Verifica docker-compose.yml esista... " +if [ -f "docker-compose.yml" ]; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${YELLOW}SKIP${NC} (docker-compose.yml non trovato)" + inc_skip + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 0 +fi + +echo "" +echo "=== INF-01: Nessun container gira come root ===" + +# PostgreSQL official image runs as postgres user, not root +echo -n "[TEST] Verifica immagine PostgreSQL (ufficiale gira come postgres)... " +if grep -q "image: postgres" docker-compose.yml; then + echo -e "${GREEN}PASS${NC} (PostgreSQL ufficiale non gira come root)" + inc_pass +else + echo -e "${YELLOW}WARN${NC} (immagine diversa da PostgreSQL ufficiale)" + inc_skip +fi + +echo "" +echo "=== INF-02: Reti private non espongono porte sull'host ===" + +# Verifica che il database NON esponga porte +echo -n "[TEST] Verifica database NON espone porte (INF-02)... " +if grep -A 30 "database:" docker-compose.yml | grep -q "ports:"; then + # Se ci sono porte, devono essere 127.0.0.1 solo + if grep -A 30 "database:" docker-compose.yml | grep -A 5 "ports:" | grep -q "127.0.0.1"; then + echo -e "${YELLOW}WARN${NC} (porta su 127.0.0.1 - RDS reale non espone porte)" + inc_skip + else + echo -e "${RED}FAIL${NC} (porta esposta su host)" + inc_fail + echo "INF-02 VIOLATION: database in rete privata non deve esporre porte" + fi +else + echo -e "${GREEN}PASS${NC} (nessuna porta esposta)" + inc_pass +fi + +# Verifica che il database sia in rete privata +echo -n "[TEST] Verifica database in rete privata... " +if grep -A 20 "database:" docker-compose.yml | grep -q "vpc-private"; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (database non in rete privata)" + inc_fail +fi + +echo "" +echo "=== INF-03: Tutti i container hanno limiti risorse ===" + +# Verifica limiti CPU +echo -n "[TEST] Verifica limiti CPU configurati... " +if grep -A 30 "database:" docker-compose.yml | grep -q "cpus:"; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (nessun limite CPU)" + inc_fail + echo "INF-03 VIOLATION: database deve avere limiti risorse" +fi + +# Verifica limiti memoria +echo -n "[TEST] Verifica limiti memoria configurati... " +if grep -A 30 "database:" docker-compose.yml | grep -q "memory:"; then + echo -e "${GREEN}PASS${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (nessun limite memoria)" + inc_fail + echo "INF-03 VIOLATION: database deve avere limiti memoria" +fi + +echo "" +echo "=== Validazione limiti risorse ===" + +# Se i container non sono in esecuzione, skip i test dinamici +echo -n "[TEST] Verifica container database in esecuzione... " +if ! docker ps --format '{{{{Names}}}}' | grep -q "^lab05-db$"; then + echo -e "${YELLOW}SKIP${NC} (container non in esecuzione)" + inc_skip + echo -e "${YELLOW}Avviare i container con: docker-compose up -d${NC}" + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 0 +fi + +echo -e "${GREEN}PASS${NC}" +inc_pass + +# Verifica limiti con docker stats +echo -n "[TEST] Verifica limiti con docker stats... " +if docker stats lab05-db --no-stream --format "{{.CPUPerc}},{{.MemUsage}}" &>/dev/null; then + echo -e "${GREEN}PASS${NC}" + inc_pass + + # Mostra utilizzo attuale + cpu_usage=$(docker stats lab05-db --no-stream --format "{{.CPUPerc}}") + mem_usage=$(docker stats lab05-db --no-stream --format "{{.MemUsage}}") + echo " CPU: $cpu_usage, Memoria: $mem_usage" +else + echo -e "${YELLOW}WARN${NC} (impossibile ottenere statistiche)" + inc_skip +fi + +echo "" +echo "=== Verifica utente container ===" + +# Verifica che il container NON giri come root +echo -n "[TEST] Verifica container NON gira come root... " +container_user=$(docker exec lab05-db whoami 2>/dev/null || echo "unknown") +if [ "$container_user" = "postgres" ] || [ "$container_user" != "root" ]; then + echo -e "${GREEN}PASS${NC} (utente: $container_user)" + inc_pass +else + echo -e "${RED}FAIL${NC} (container gira come root)" + inc_fail + echo "INF-01 VIOLATION: nessun container deve girare come root" +fi + +# Verifica UID del container +echo -n "[TEST] Verifica container UID != 0... " +container_uid=$(docker exec lab05-db id -u 2>/dev/null || echo "0") +if [ "$container_uid" != "0" ]; then + echo -e "${GREEN}PASS${NC} (UID: $container_uid)" + inc_pass +else + echo -e "${RED}FAIL${NC} (UID: 0 = root)" + inc_fail +fi + +echo "" +echo "==========================================" +echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" +echo "==========================================" + +if [ $fail_count -gt 0 ]; then + exit 1 +fi + +exit 0 diff --git a/labs/lab-05-database/tests/99-final-verification.sh b/labs/lab-05-database/tests/99-final-verification.sh new file mode 100755 index 0000000..4dfcfeb --- /dev/null +++ b/labs/lab-05-database/tests/99-final-verification.sh @@ -0,0 +1,272 @@ +#!/bin/bash +# Lab 05 - Database & RDS +# Test 99: Final Verification (Double Check) +# Verifica finale end-to-end per studenti + +set -euo pipefail + +# Colori per output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Contatori +pass_count=0 +fail_count=0 +skip_count=0 + +# Funzioni helper +inc_pass() { ((pass_count++)) || true; } +inc_fail() { ((fail_count++)) || true; } +inc_skip() { ((skip_count++)) || true; } + +echo "==========================================" +echo "Lab 05 - Final Verification (Double Check)" +echo "==========================================" +echo "" +echo "Verifica completa: Lab 05 - Database & RDS" +echo "Parallelo: PostgreSQL in Docker ↔ RDS in AWS VPC" +echo "" + +# Verifica file docker-compose.yml +echo -n "[CHECK] Verifica docker-compose.yml esista... " +if [ -f "docker-compose.yml" ]; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail + echo "ERRORE: docker-compose.yml non trovato" + exit 1 +fi + +echo "" +echo "=== VERIFICA CONFIGURAZIONE ===" + +# Verifica servizio database +echo -n "[CHECK] Servizio 'database' definito... " +if grep -q "database:" docker-compose.yml; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +# Verifica immagine PostgreSQL +echo -n "[CHECK] Immagine PostgreSQL... " +if grep -q "image: postgres" docker-compose.yml; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +# Verifica credenziali +echo -n "[CHECK] Credenziali PostgreSQL configurate... " +if grep -q "POSTGRES_DB:" docker-compose.yml && \ + grep -q "POSTGRES_USER:" docker-compose.yml && \ + grep -q "POSTGRES_PASSWORD:" docker-compose.yml; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +# Verifica volume +echo -n "[CHECK] Volume 'db-data' configurato... " +if grep -q "db-data:" docker-compose.yml; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +# Verifica rete privata +echo -n "[CHECK] Database in rete 'vpc-private'... " +if grep -A 20 "database:" docker-compose.yml | grep -q "vpc-private"; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +# Verifica nessuna porta esposta +echo -n "[CHECK] NESSUNA porta esposta (INF-02)... " +if grep -A 30 "database:" docker-compose.yml | grep -q "ports:"; then + echo -e "${YELLOW}WARN${NC} (porte configurate - RDS non espone porte)" + inc_skip +else + echo -e "${GREEN}OK${NC}" + inc_pass +fi + +# Verifica limiti risorse +echo -n "[CHECK] Limiti risorse configurati (INF-03)... " +if grep -A 30 "database:" docker-compose.yml | grep -q "cpus:" && \ + grep -A 30 "database:" docker-compose.yml | grep -q "memory:"; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +echo "" +echo "=== VERIFICA ESECUZIONE ===" + +# Verifica container in esecuzione +echo -n "[CHECK] Container 'lab05-db' in esecuzione... " +if docker ps --format '{{{{Names}}}}' | grep -q "^lab05-db$"; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail + echo "Avviare i container: docker-compose up -d" + echo "" + echo "Risultato: $pass_count PASS, $fail_count FAIL, $skip_count SKIP" + exit 1 +fi + +# Verifica healthcheck +echo -n "[CHECK] Healthcheck configurato... " +health_status=$(docker inspect lab05-db --format '{{.State.Health.Status}}' 2>/dev/null || echo "unknown") +if [ "$health_status" != "unknown" ]; then + echo -e "${GREEN}OK${NC} ($health_status)" + inc_pass +else + echo -e "${YELLOW}WARN${NC} (nessun healthcheck)" + inc_skip +fi + +# Verifica pg_isready +echo -n "[CHECK] PostgreSQL pronto (pg_isready)... " +if docker exec lab05-db pg_isready &>/dev/null; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${YELLOW}WARN${NC} (PostgreSQL non ancora pronto)" + inc_skip +fi + +echo "" +echo "=== VERIFICA SICUREZZA ===" + +# INF-01: Non-root +echo -n "[CHECK] Container NON gira come root (INF-01)... " +container_user=$(docker exec lab05-db whoami 2>/dev/null || echo "unknown") +if [ "$container_user" = "postgres" ]; then + echo -e "${GREEN}OK${NC} ($container_user)" + inc_pass +else + echo -e "${RED}FAIL${NC} ($container_user)" + inc_fail +fi + +# INF-02: No host ports +echo -n "[CHECK] NESSUNA porta su host (INF-02)... " +db_port=$(docker port lab05-db 5432 2>/dev/null || echo "") +if [ -z "$db_port" ]; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC} (porta $db_port)" + inc_fail +fi + +# INF-03: Resource limits +echo -n "[CHECK] Limiti risorsa applicati (INF-03)... " +if docker inspect lab05-db --format '{{.HostConfig.Memory}}' | grep -q "[1-9]"; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +# INF-04: Volume persistence +echo -n "[CHECK] Volume persistenza (INF-04)... " +if docker volume ls --format '{{{{.Name}}}}' | grep -q "^lab05_db-data$"; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +echo "" +echo "=== VERIFICA FUNZIONALITÀ ===" + +# Test connessione database +echo -n "[CHECK] Connessione database funziona... " +if docker exec lab05-db psql -U lab05_user -d lab05_db -c "SELECT 1;" &>/dev/null; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +# Test creazione tabella +echo -n "[CHECK] Creazione tabella... " +if docker exec lab05-db psql -U lab05_user -d lab05_db -c "CREATE TABLE IF NOT EXISTS verify_test (id SERIAL);" &>/dev/null; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +# Test inserimento dati +echo -n "[CHECK] Inserimento dati... " +if docker exec lab05-db psql -U lab05_user -d lab05_db -c "INSERT INTO verify_test DEFAULT VALUES;" &>/dev/null; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +# Test query dati +echo -n "[CHECK] Query dati... " +count=$(docker exec lab05-db psql -U lab05_user -d lab05_db -t -c "SELECT COUNT(*) FROM verify_test;" 2>/dev/null | tr -d ' ') +if [ -n "$count" ] && [ "$count" -gt 0 ]; then + echo -e "${GREEN}OK${NC} ($count righe)" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +echo "" +echo "==========================================" +echo "RISULTATO FINALE:" +echo " $pass_count PASS" +echo " $fail_count FAIL" +echo " $skip_count SKIP" +echo "==========================================" + +if [ $fail_count -eq 0 ]; then + echo "" + echo -e "${GREEN}✓ LAB 05 COMPLETATO CON SUCCESSO${NC}" + echo "" + echo "Paralleli confermati:" + echo " PostgreSQL container → RDS Instance" + echo " Private network → VPC Private Subnet" + echo " Named volume → EBS Volume" + echo " Resource limits → DB Instance Class" + echo "" + exit 0 +else + echo "" + echo -e "${RED}✗ LAB 05 HA ERRORI - RISOLVERE E RIPETERE${NC}" + echo "" + exit 1 +fi diff --git a/labs/lab-05-database/tests/quick-test.sh b/labs/lab-05-database/tests/quick-test.sh new file mode 100755 index 0000000..94bd2fb --- /dev/null +++ b/labs/lab-05-database/tests/quick-test.sh @@ -0,0 +1,111 @@ +#!/bin/bash +# Lab 05 - Database & RDS +# Quick Test Script (< 30 secondi) +# Validazione rapida per sviluppo + +set -euo pipefail + +# Colori per output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo "==========================================" +echo "Lab 05 - Quick Test (< 30s)" +echo "==========================================" +echo "" + +pass_count=0 +fail_count=0 + +inc_pass() { ((pass_count++)) || true; } +inc_fail() { ((fail_count++)) || true; } + +# Test rapidi +echo -n "[TEST] docker-compose.yml esiste... " +if [ -f "docker-compose.yml" ]; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail + exit 1 +fi + +echo -n "[TEST] Servizio database definito... " +if grep -q "database:" docker-compose.yml; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +echo -n "[TEST] PostgreSQL image configurata... " +if grep -q "image: postgres" docker-compose.yml; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +echo -n "[TEST] Volume db-data configurato... " +if grep -q "db-data:" docker-compose.yml; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +echo -n "[TEST] Database in rete privata... " +if grep -A 20 "database:" docker-compose.yml | grep -q "vpc-private"; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +echo -n "[TEST] Limiti risorse configurati... " +if grep -A 30 "database:" docker-compose.yml | grep -q "cpus:" && \ + grep -A 30 "database:" docker-compose.yml | grep -q "memory:"; then + echo -e "${GREEN}OK${NC}" + inc_pass +else + echo -e "${RED}FAIL${NC}" + inc_fail +fi + +echo "" +echo "Container check (skip se non in esecuzione)..." + +if docker ps --format '{{{{Names}}}}' | grep -q "^lab05-db$"; then + echo -n "[TEST] Container in esecuzione... " + echo -e "${GREEN}OK${NC}" + inc_pass + + echo -n "[TEST] PostgreSQL pronto... " + if docker exec lab05-db pg_isready &>/dev/null; then + echo -e "${GREEN}OK${NC}" + inc_pass + else + echo -e "${YELLOW}WAIT${NC}" + inc_pass + fi +else + echo -e "${YELLOW}SKIP${NC} (container non in esecuzione)" +fi + +echo "" +echo "==========================================" +echo "Risultato: $pass_count PASS, $fail_count FAIL" +echo "==========================================" + +if [ $fail_count -gt 0 ]; then + exit 1 +fi + +exit 0 diff --git a/labs/lab-05-database/tests/run-all-tests.sh b/labs/lab-05-database/tests/run-all-tests.sh new file mode 100755 index 0000000..14444d2 --- /dev/null +++ b/labs/lab-05-database/tests/run-all-tests.sh @@ -0,0 +1,93 @@ +#!/bin/bash +# Lab 05 - Database & RDS +# Test Orchestration Script +# Esegue tutti i test con fail-fast behavior + +set -euo pipefail + +# Colori per output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Directory corrente +TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$TEST_DIR" + +# Contatori globali +global_pass=0 +global_fail=0 +global_skip=0 + +# Funzioni helper +inc_global_pass() { ((global_pass++)) || true; } +inc_global_fail() { ((global_fail++)) || true; } +inc_global_skip() { ((global_skip++)) || true; } + +echo "==========================================" +echo "Lab 05 - Test Suite Orchestration" +echo "==========================================" +echo "" + +# Array dei test da eseguire +declare -a tests=( + "$TEST_DIR/01-database-creation-test.sh" + "$TEST_DIR/02-private-network-test.sh" + "$TEST_DIR/03-persistence-test.sh" + "$TEST_DIR/04-security-test.sh" + "$TEST_DIR/99-final-verification.sh" +) + +# Esegui tutti i test +for test_script in "${tests[@]}"; do + test_name=$(basename "$test_script") + + echo -e "${BLUE}Eseguendo: $test_name${NC}" + echo "----------------------------------------" + + if [ ! -f "$test_script" ]; then + echo -e "${RED}ERRORE: Test non trovato: $test_script${NC}" + inc_global_fail + continue + fi + + # Rendi eseguibile + chmod +x "$test_script" + + # Esegui il test e cattura l'exit code + if bash "$test_script"; then + test_result=$? + echo -e "${GREEN}✓ $test_name PASS${NC}" + echo "" + else + test_result=$? + echo -e "${RED}✗ $test_name FAIL${NC}" + echo "" + + # Fail-fast: esci al primo test fallito + echo -e "${RED}FAIL-FAST: Interrompo esecuzione per errore critico${NC}" + inc_global_fail + break + fi +done + +echo "==========================================" +echo "RIEPILOGO COMPLETO" +echo "==========================================" +echo "Test PASS: $global_pass" +echo "Test FAIL: $global_fail" +echo "Test SKIP: $global_skip" +echo "==========================================" + +if [ $global_fail -gt 0 ]; then + echo "" + echo -e "${RED}✗ TEST SUITE FALLITA${NC}" + echo "Risolvere gli errori e ripetere" + exit 1 +else + echo "" + echo -e "${GREEN}✓ TEST SUITE COMPLETATA CON SUCCESSO${NC}" + exit 0 +fi