refactor: remove unnecessary TDD test files across all labs, keep only final verifications and update references
This commit is contained in:
@@ -64,14 +64,6 @@ docker rm c1 c2 c3
|
||||
docker network rm test-net1 test-net2
|
||||
```
|
||||
|
||||
## Test con Script
|
||||
|
||||
Usa lo script del lab:
|
||||
|
||||
```bash
|
||||
bash labs/lab-02-network/tests/02-isolation-verification-test.sh
|
||||
```
|
||||
|
||||
## Risultati Attesi
|
||||
|
||||
| Test | Risultato Atteso | Significato |
|
||||
@@ -84,4 +76,3 @@ bash labs/lab-02-network/tests/02-isolation-verification-test.sh
|
||||
## Vedi Anche
|
||||
|
||||
- [Tutorial: Verificare Isolamento](../tutorial/03-verify-network-isolation.md)
|
||||
- [Test: Isolation Verification Script](../tests/02-isolation-verification-test.sh)
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Test 01: Network Creation Validation
|
||||
# Validates Docker bridge network creation with custom subnets (VPC simulation)
|
||||
# Usage: bash labs/lab-02-network/tests/01-network-creation-test.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$TEST_DIR/../.." && pwd)"
|
||||
|
||||
# Counter helpers to handle set -e
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
skip_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
inc_skip() { ((skip_count++)) || true; }
|
||||
|
||||
# Test helper functions
|
||||
print_header() {
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
}
|
||||
|
||||
print_test() {
|
||||
echo -e "\n${BLUE}[TEST]${NC} $1"
|
||||
}
|
||||
|
||||
print_pass() {
|
||||
echo -e "${GREEN}[PASS]${NC} $1"
|
||||
inc_pass
|
||||
}
|
||||
|
||||
print_fail() {
|
||||
echo -e "${RED}[FAIL]${NC} $1"
|
||||
inc_fail
|
||||
}
|
||||
|
||||
print_skip() {
|
||||
echo -e "${YELLOW}[SKIP]${NC} $1"
|
||||
inc_skip
|
||||
}
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
echo -e "\n${BLUE}[*] Cleaning up test networks...${NC}"
|
||||
docker network rm test-vpc-public 2>/dev/null || true
|
||||
docker network rm test-vpc-private 2>/dev/null || true
|
||||
docker network rm test-net1 2>/dev/null || true
|
||||
docker network rm test-net2 2>/dev/null || true
|
||||
echo -e "${GREEN}[✓] Cleanup complete${NC}"
|
||||
}
|
||||
|
||||
# Set trap for cleanup
|
||||
trap cleanup EXIT
|
||||
|
||||
# Start testing
|
||||
print_header "Lab 02 - Test 01: Network Creation Validation"
|
||||
|
||||
# Test 1: Verify Docker is available
|
||||
print_test "Test 1: Verify Docker is available"
|
||||
if command -v docker &> /dev/null; then
|
||||
print_pass "Docker command is available"
|
||||
docker --version
|
||||
else
|
||||
print_fail "Docker command not found. Please install Docker."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: Create public network with custom subnet (VPC simulation)
|
||||
print_test "Test 2: Create public network with custom subnet (10.0.1.0/24)"
|
||||
if docker network create --driver bridge --subnet 10.0.1.0/24 --gateway 10.0.1.1 test-vpc-public &> /dev/null; then
|
||||
print_pass "Created public network test-vpc-public with subnet 10.0.1.0/24"
|
||||
docker network inspect test-vpc-public --format='Subnet: {{range .IPAM.Config}}{{.Subnet}}{{end}}'
|
||||
else
|
||||
print_fail "Failed to create public network with custom subnet"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Create private network with --internal flag
|
||||
print_test "Test 3: Create private network with --internal flag (10.0.2.0/24)"
|
||||
if docker network create --driver bridge --internal --subnet 10.0.2.0/24 --gateway 10.0.2.1 test-vpc-private &> /dev/null; then
|
||||
print_pass "Created private network test-vpc-private with --internal flag"
|
||||
docker network inspect test-vpc-private --format='Internal: {{.Internal}}'
|
||||
else
|
||||
print_fail "Failed to create private network with --internal flag"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 4: Verify networks appear in docker network ls
|
||||
print_test "Test 4: Verify networks appear in docker network ls"
|
||||
public_found=$(docker network ls --format '{{.Name}}' | grep -c "^test-vpc-public$" || true)
|
||||
private_found=$(docker network ls --format '{{.Name}}' | grep -c "^test-vpc-private$" || true)
|
||||
|
||||
if [[ $public_found -eq 1 && $private_found -eq 1 ]]; then
|
||||
print_pass "Both test-vpc-public and test-vpc-private found in network list"
|
||||
docker network ls --filter "name=test-vpc-" --format "table {{.Name}}\t{{.Driver}}\t{{.Scope}}"
|
||||
else
|
||||
print_fail "Networks not found in list. public_found=$public_found, private_found=$private_found"
|
||||
fi
|
||||
|
||||
# Test 5: Verify network inspection shows correct subnet
|
||||
print_test "Test 5: Verify network inspection shows correct subnet configuration"
|
||||
public_subnet=$(docker network inspect test-vpc-public --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null || echo "")
|
||||
private_subnet=$(docker network inspect test-vpc-private --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null || echo "")
|
||||
|
||||
if [[ "$public_subnet" == "10.0.1.0/24" && "$private_subnet" == "10.0.2.0/24" ]]; then
|
||||
print_pass "Network subnets correctly configured"
|
||||
echo " Public: $public_subnet"
|
||||
echo " Private: $private_subnet"
|
||||
else
|
||||
print_fail "Network subnets mismatch. public=$public_subnet (expected 10.0.1.0/24), private=$private_subnet (expected 10.0.2.0/24)"
|
||||
fi
|
||||
|
||||
# Test 6: Verify private network has internal flag set
|
||||
print_test "Test 6: Verify private network has --internal flag set"
|
||||
internal_flag=$(docker network inspect test-vpc-private --format '{{.Internal}}' 2>/dev/null || echo "false")
|
||||
|
||||
if [[ "$internal_flag" == "true" ]]; then
|
||||
print_pass "Private network correctly marked as internal (no external access)"
|
||||
else
|
||||
print_fail "Private network internal flag not set (value: $internal_flag)"
|
||||
fi
|
||||
|
||||
# Test 7: Verify bridge driver is used
|
||||
print_test "Test 7: Verify bridge driver is used for both networks"
|
||||
public_driver=$(docker network inspect test-vpc-public --format '{{.Driver}}' 2>/dev/null || echo "")
|
||||
private_driver=$(docker network inspect test-vpc-private --format '{{.Driver}}' 2>/dev/null || echo "")
|
||||
|
||||
if [[ "$public_driver" == "bridge" && "$private_driver" == "bridge" ]]; then
|
||||
print_pass "Both networks use bridge driver"
|
||||
else
|
||||
print_fail "Driver mismatch. public=$public_driver, private=$private_driver (expected: bridge)"
|
||||
fi
|
||||
|
||||
# Test 8: Check if docker-compose.yml exists (optional - may not exist yet in RED phase)
|
||||
print_test "Test 8: Check if lab docker-compose.yml exists"
|
||||
COMPOSE_FILE="$PROJECT_ROOT/labs/lab-02-network/docker-compose.yml"
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
print_pass "docker-compose.yml found at $COMPOSE_FILE"
|
||||
|
||||
# Test 9: Verify docker compose config is valid
|
||||
print_test "Test 9: Validate docker-compose.yml syntax"
|
||||
if docker compose -f "$COMPOSE_FILE" config &> /dev/null; then
|
||||
print_pass "docker-compose.yml is valid YAML"
|
||||
else
|
||||
print_fail "docker-compose.yml has syntax errors"
|
||||
fi
|
||||
else
|
||||
print_skip "docker-compose.yml not found yet (expected in RED phase - will be created in GREEN phase)"
|
||||
fi
|
||||
|
||||
# Test 10: Verify networks can be removed
|
||||
print_test "Test 10: Verify test networks can be removed"
|
||||
# This will be handled by cleanup trap, but we verify the command works
|
||||
if docker network rm test-vpc-public test-vpc-private &> /dev/null; then
|
||||
print_pass "Test networks successfully removed"
|
||||
|
||||
# Recreate for cleanup trap
|
||||
docker network create --driver bridge --subnet 10.0.1.0/24 --gateway 10.0.1.1 test-vpc-public &> /dev/null
|
||||
docker network create --driver bridge --internal --subnet 10.0.2.0/24 --gateway 10.0.2.1 test-vpc-private &> /dev/null
|
||||
else
|
||||
print_fail "Failed to remove test networks"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
print_header "Test Summary"
|
||||
echo -e "Total tests run: $((pass_count + fail_count + skip_count))"
|
||||
echo -e "${GREEN}Passed: $pass_count${NC}"
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "${RED}Failed: $fail_count${NC}"
|
||||
fi
|
||||
if [[ $skip_count -gt 0 ]]; then
|
||||
echo -e "${YELLOW}Skipped: $skip_count${NC}"
|
||||
fi
|
||||
|
||||
# Exit with error code if any tests failed
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "\n${RED}Some tests failed. Please review the output above.${NC}"
|
||||
exit 1
|
||||
else
|
||||
echo -e "\n${GREEN}All tests passed! Network creation is working correctly.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
@@ -1,260 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Test 02: Isolation Verification
|
||||
# Validates network isolation between Docker bridge networks
|
||||
# Usage: bash labs/lab-02-network/tests/02-isolation-verification-test.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Counter helpers
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
skip_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
inc_skip() { ((skip_count++)) || true; }
|
||||
|
||||
# Test helper functions
|
||||
print_header() {
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
}
|
||||
|
||||
print_test() {
|
||||
echo -e "\n${BLUE}[TEST]${NC} $1"
|
||||
}
|
||||
|
||||
print_pass() {
|
||||
echo -e "${GREEN}[PASS]${NC} $1"
|
||||
inc_pass
|
||||
}
|
||||
|
||||
print_fail() {
|
||||
echo -e "${RED}[FAIL]${NC} $1"
|
||||
inc_fail
|
||||
}
|
||||
|
||||
print_skip() {
|
||||
echo -e "${YELLOW}[SKIP]${NC} $1"
|
||||
inc_skip
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
echo -e "\n${BLUE}[*] Cleaning up test containers and networks...${NC}"
|
||||
|
||||
# Stop and remove containers
|
||||
for container in c1 c2 c3 c4; do
|
||||
docker stop "$container" 2>/dev/null || true
|
||||
docker rm "$container" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# Remove networks
|
||||
for network in test-net1 test-net2 test-isolated-net; do
|
||||
docker network rm "$network" 2>/dev/null || true
|
||||
done
|
||||
|
||||
echo -e "${GREEN}[✓] Cleanup complete${NC}"
|
||||
}
|
||||
|
||||
# Set trap for cleanup
|
||||
trap cleanup EXIT
|
||||
|
||||
# Start testing
|
||||
print_header "Lab 02 - Test 02: Network Isolation Verification"
|
||||
|
||||
# Test 1: Create two isolated networks
|
||||
print_test "Test 1: Create two isolated bridge networks (10.0.1.0/24 and 10.0.2.0/24)"
|
||||
if docker network create --driver bridge --subnet 10.0.1.0/24 --gateway 10.0.1.1 test-net1 &> /dev/null && \
|
||||
docker network create --driver bridge --subnet 10.0.2.0/24 --gateway 10.0.2.1 test-net2 &> /dev/null; then
|
||||
print_pass "Created two isolated networks successfully"
|
||||
docker network ls --filter "name=test-net" --format "table {{.Name}}\t{{.Driver}}\t{{.Scope}}"
|
||||
else
|
||||
print_fail "Failed to create test networks"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: Create containers in same network
|
||||
print_test "Test 2: Create containers in the same network (test-net1)"
|
||||
if docker run -d --name c1 --network test-net1 --hostname c1 alpine:3.19 sleep 3600 &> /dev/null && \
|
||||
docker run -d --name c2 --network test-net1 --hostname c2 alpine:3.19 sleep 3600 &> /dev/null; then
|
||||
print_pass "Created containers c1 and c2 in test-net1"
|
||||
docker ps --filter "name=c[12]" --format "table {{.Names}}\t{{.Networks}}\t{{.Status}}"
|
||||
else
|
||||
print_fail "Failed to create containers in test-net1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Containers in same network CAN communicate (ping should succeed)
|
||||
print_test "Test 3: Containers in same network can communicate (ping test)"
|
||||
if docker exec c1 ping -c 2 -W 1 c2 &> /dev/null; then
|
||||
print_pass "c1 can successfully ping c2 (same-network communication works)"
|
||||
docker exec c1 ping -c 2 -W 1 c2 | grep "packets transmitted"
|
||||
else
|
||||
print_fail "c1 cannot ping c2 (same-network communication should work)"
|
||||
fi
|
||||
|
||||
# Test 4: Containers in same network can resolve by DNS name
|
||||
print_test "Test 4: Containers in same network can resolve each other by DNS name"
|
||||
if docker exec c1 nslookup c2 &> /dev/null; then
|
||||
print_pass "DNS resolution works within same network"
|
||||
docker exec c1 nslookup c2 | grep "Address" | head -1
|
||||
else
|
||||
print_fail "DNS resolution failed within same network"
|
||||
fi
|
||||
|
||||
# Test 5: Create container in different network
|
||||
print_test "Test 5: Create container c3 in different network (test-net2)"
|
||||
if docker run -d --name c3 --network test-net2 --hostname c3 alpine:3.19 sleep 3600 &> /dev/null; then
|
||||
print_pass "Created container c3 in isolated network test-net2"
|
||||
print_info "c1 and c2 are in test-net1, c3 is in test-net2 (isolated)"
|
||||
else
|
||||
print_fail "Failed to create container c3 in test-net2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 6: Containers in DIFFERENT networks CANNOT communicate (isolation test)
|
||||
print_test "Test 6: Containers in different networks CANNOT communicate (isolation verification)"
|
||||
print_info "This test EXPECTS ping to FAIL (proves isolation works)"
|
||||
if docker exec c1 ping -c 2 -W 1 c3 &> /dev/null; then
|
||||
print_fail "c1 CAN ping c3 - ISOLATION FAILED! Networks are not isolated!"
|
||||
print_fail "This is a security issue - containers should not reach across networks"
|
||||
else
|
||||
print_pass "c1 CANNOT ping c3 - Network isolation is working correctly!"
|
||||
print_info "This is the expected behavior - isolation prevents cross-network communication"
|
||||
fi
|
||||
|
||||
# Test 7: Cross-network DNS resolution should fail
|
||||
print_test "Test 7: Cross-network DNS resolution should fail"
|
||||
print_info "This test EXPECTS DNS lookup to FAIL (proves DNS isolation)"
|
||||
if docker exec c1 nslookup c3 &> /dev/null; then
|
||||
print_fail "c1 CAN resolve c3 by DNS - DNS isolation FAILED!"
|
||||
else
|
||||
print_pass "c1 CANNOT resolve c3 - DNS isolation is working correctly!"
|
||||
fi
|
||||
|
||||
# Test 8: Create a container connected to both networks (multi-homed)
|
||||
print_test "Test 8: Create multi-homed container c4 connected to BOTH networks"
|
||||
if docker run -d --name c4 --network test-net1 alpine:3.19 sleep 3600 &> /dev/null && \
|
||||
docker network connect test-net2 c4 &> /dev/null; then
|
||||
print_pass "Created container c4 connected to both networks"
|
||||
docker inspect c4 --format 'Networks: {{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}'
|
||||
else
|
||||
print_fail "Failed to create multi-homed container"
|
||||
fi
|
||||
|
||||
# Test 9: Multi-homed container can reach containers in both networks
|
||||
print_test "Test 9: Multi-homed container c4 can reach both c1 (net1) and c3 (net2)"
|
||||
c4_to_c1_result=$(docker exec c4 ping -c 1 -W 1 c1 &> /dev/null && echo "OK" || echo "FAIL")
|
||||
c4_to_c3_result=$(docker exec c4 ping -c 1 -W 1 c3 &> /dev/null && echo "OK" || echo "FAIL")
|
||||
|
||||
if [[ "$c4_to_c1_result" == "OK" && "$c4_to_c3_result" == "OK" ]]; then
|
||||
print_pass "Multi-homed container can reach both networks (c4->c1: OK, c4->c3: OK)"
|
||||
else
|
||||
print_fail "Multi-homed container connectivity issue (c4->c1: $c4_to_c1_result, c4->c3: $c4_to_c3_result)"
|
||||
fi
|
||||
|
||||
# Test 10: Verify isolation still works - c1 cannot ping c3 despite c4 being multi-homed
|
||||
print_test "Test 10: Verify isolation - c1 still cannot reach c3 (despite c4 bridging networks)"
|
||||
if docker exec c1 ping -c 1 -W 1 c3 &> /dev/null; then
|
||||
print_fail "c1 CAN ping c3 - ISOLATION BROKEN! Multi-homing created a bridge!"
|
||||
else
|
||||
print_pass "Isolation maintained - c1 still cannot reach c3 (multi-homing doesn't break isolation)"
|
||||
fi
|
||||
|
||||
# Test 11: Create isolated internal network
|
||||
print_test "Test 11: Create internal network (no external access)"
|
||||
if docker network create --driver bridge --internal --subnet 10.0.10.0/24 test-isolated-net &> /dev/null; then
|
||||
print_pass "Created internal network test-isolated-net"
|
||||
docker network inspect test-isolated-net --format 'Internal: {{.Internal}}'
|
||||
else
|
||||
print_fail "Failed to create internal network"
|
||||
fi
|
||||
|
||||
# Test 12: Verify container in internal network cannot reach external internet
|
||||
print_test "Test 12: Container in internal network cannot reach external internet"
|
||||
docker run -d --name isolated-test --network test-isolated-net alpine:3.19 sleep 3600 &> /dev/null || true
|
||||
|
||||
if docker exec isolated-test ping -c 1 -W 1 8.8.8.8 &> /dev/null; then
|
||||
print_fail "Container in internal network CAN reach internet - internal flag not working!"
|
||||
else
|
||||
print_pass "Container in internal network CANNOT reach internet (isolation works)"
|
||||
print_info "This is expected behavior for --internal flag networks"
|
||||
fi
|
||||
|
||||
# Cleanup isolated test container early
|
||||
docker stop isolated-test &> /dev/null || true
|
||||
docker rm isolated-test &> /dev/null || true
|
||||
|
||||
# Test 13: Verify network IP addresses don't overlap
|
||||
print_test "Test 13: Verify network subnets are properly isolated (no IP overlap)"
|
||||
net1_subnet=$(docker network inspect test-net1 --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null || echo "")
|
||||
net2_subnet=$(docker network inspect test-net2 --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null || echo "")
|
||||
|
||||
if [[ "$net1_subnet" != "$net2_subnet" ]]; then
|
||||
print_pass "Network subnets are different (no overlap)"
|
||||
echo " test-net1: $net1_subnet"
|
||||
echo " test-net2: $net2_subnet"
|
||||
else
|
||||
print_fail "Network subnets are identical - IP overlap will occur!"
|
||||
fi
|
||||
|
||||
# Test 14: Verify containers have IPs from correct subnets
|
||||
print_test "Test 14: Verify containers have IPs from their network's subnet"
|
||||
c1_ip=$(docker inspect c1 --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 2>/dev/null || echo "")
|
||||
c3_ip=$(docker inspect c3 --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 2>/dev/null || echo "")
|
||||
|
||||
c1_in_net1=$(echo "$c1_ip" | grep -q "^10.0.1." && echo "yes" || echo "no")
|
||||
c3_in_net2=$(echo "$c3_ip" | grep -q "^10.0.2." && echo "yes" || echo "no")
|
||||
|
||||
if [[ "$c1_in_net1" == "yes" && "$c3_in_net2" == "yes" ]]; then
|
||||
print_pass "Containers have IPs from correct subnets"
|
||||
echo " c1 IP: $c1_ip (should be in 10.0.1.0/24)"
|
||||
echo " c3 IP: $c3_ip (should be in 10.0.2.0/24)"
|
||||
else
|
||||
print_fail "Container IPs don't match expected subnets"
|
||||
echo " c1 IP: $c1_ip (expected 10.0.1.x)"
|
||||
echo " c3 IP: $c3_ip (expected 10.0.2.x)"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
print_header "Test Summary"
|
||||
echo -e "Total tests run: $((pass_count + fail_count + skip_count))"
|
||||
echo -e "${GREEN}Passed: $pass_count${NC}"
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "${RED}Failed: $fail_count${NC}"
|
||||
fi
|
||||
if [[ $skip_count -gt 0 ]]; then
|
||||
echo -e "${YELLOW}Skipped: $skip_count${NC}"
|
||||
fi
|
||||
|
||||
# Isolation verification message
|
||||
echo -e "\n${BLUE}[*] Network Isolation Summary${NC}"
|
||||
echo -e "Same-network communication: ${GREEN}WORKS${NC} (expected)"
|
||||
echo -e "Cross-network communication: ${GREEN}BLOCKED${NC} (isolation working)"
|
||||
echo -e "DNS isolation: ${GREEN}ENFORCED${NC} (cross-network DNS blocked)"
|
||||
echo -e "Internal network isolation: ${GREEN}ENFORCED${NC} (no external access)"
|
||||
|
||||
# Exit with error code if any tests failed
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "\n${RED}Some tests failed. Please review the output above.${NC}"
|
||||
exit 1
|
||||
else
|
||||
echo -e "\n${GREEN}All tests passed! Network isolation is working correctly.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
@@ -1,272 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Test 03: INF-02 Compliance Verification
|
||||
# Validates INF-02 requirement: private networks must NOT expose ports on 0.0.0.0
|
||||
# Usage: bash labs/lab-02-network/tests/03-inf02-compliance-test.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$TEST_DIR/../.." && pwd)"
|
||||
|
||||
# Counter helpers
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
skip_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
inc_skip() { ((skip_count++)) || true; }
|
||||
|
||||
# Test helper functions
|
||||
print_header() {
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
}
|
||||
|
||||
print_test() {
|
||||
echo -e "\n${BLUE}[TEST]${NC} $1"
|
||||
}
|
||||
|
||||
print_pass() {
|
||||
echo -e "${GREEN}[PASS]${NC} $1"
|
||||
inc_pass
|
||||
}
|
||||
|
||||
print_fail() {
|
||||
echo -e "${RED}[FAIL]${NC} $1"
|
||||
inc_fail
|
||||
}
|
||||
|
||||
print_skip() {
|
||||
echo -e "${YELLOW}[SKIP]${NC} $1"
|
||||
inc_skip
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
# INF-02 Requirement explanation
|
||||
print_header "Lab 02 - Test 03: INF-02 Compliance Verification"
|
||||
echo -e "${BLUE}INF-02 Requirement:${NC} Private networks must NOT expose ports on 0.0.0.0"
|
||||
echo -e "${YELLOW}Allowed:${NC} 127.0.0.1 (localhost only) or no published ports"
|
||||
echo -e "${RED}Forbidden:${NC} 0.0.0.0 (exposes to all network interfaces)"
|
||||
echo -e ""
|
||||
|
||||
# Compose file path
|
||||
COMPOSE_FILE="$PROJECT_ROOT/labs/lab-02-network/docker-compose.yml"
|
||||
|
||||
# Test 1: Verify docker-compose.yml exists
|
||||
print_test "Test 1: Verify docker-compose.yml exists"
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
print_pass "docker-compose.yml found at $COMPOSE_FILE"
|
||||
COMPOSE_EXISTS=true
|
||||
else
|
||||
print_skip "docker-compose.yml not found at $COMPOSE_FILE"
|
||||
print_info "This is expected in RED phase - file will be created in GREEN phase"
|
||||
COMPOSE_EXISTS=false
|
||||
|
||||
# Skip remaining tests if compose file doesn't exist
|
||||
print_header "Test Summary (Early Exit)"
|
||||
echo -e "Total tests: $((pass_count + fail_count + skip_count))"
|
||||
echo -e "${GREEN}Passed: $pass_count${NC}"
|
||||
echo -e "${YELLOW}Skipped: $skip_count${NC}"
|
||||
echo -e "${YELLOW}INF-02 compliance tests skipped - infrastructure not yet created${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Test 2: Verify docker-compose.yml is valid YAML
|
||||
print_test "Test 2: Validate docker-compose.yml syntax"
|
||||
if docker compose -f "$COMPOSE_FILE" config &> /dev/null; then
|
||||
print_pass "docker-compose.yml is valid YAML"
|
||||
else
|
||||
print_fail "docker-compose.yml has syntax errors"
|
||||
print_info "Run 'docker compose -f docker-compose.yml config' to see errors"
|
||||
fi
|
||||
|
||||
# Test 3: Check for 0.0.0.0 port bindings (CRITICAL - must not exist)
|
||||
print_test "Test 3: Check for 0.0.0.0 port bindings (VIOLATES INF-02)"
|
||||
print_info "Searching for pattern: 0.0.0.0:PORT"
|
||||
ZERO_DETECTIONS=$(grep -n -E '0\.0\.0\.0:[0-9]+' "$COMPOSE_FILE" 2>/dev/null || echo "")
|
||||
ZERO_COUNT=$(echo "$ZERO_DETECTIONS" | grep -c "0.0.0" || true)
|
||||
|
||||
if [[ -z "$ZERO_DETECTIONS" ]]; then
|
||||
print_pass "No 0.0.0.0 port bindings found (COMPLIANT with INF-02)"
|
||||
else
|
||||
print_fail "Found $ZERO_COUNT occurrence(s) of 0.0.0.0 port bindings - INF-02 VIOLATION!"
|
||||
echo "$ZERO_DETECTIONS" | while read -r line; do
|
||||
echo -e "${RED} $line${NC}"
|
||||
done
|
||||
print_warning "0.0.0.0 exposes service on ALL network interfaces (security risk)"
|
||||
print_info "Fix: Use '127.0.0.1:PORT:CONTAINER_PORT' for localhost-only access"
|
||||
fi
|
||||
|
||||
# Test 4: Check for host:port format without explicit host (defaults to 0.0.0.0)
|
||||
print_test "Test 4: Check for implicit 0.0.0.0 bindings (e.g., '8080:80' without host)"
|
||||
print_info "Pattern: '- \"PORT:CONTAINER_PORT\"' (defaults to 0.0.0.0:PORT)"
|
||||
|
||||
# Look for port mappings without explicit host (e.g., "8080:80" instead of "127.0.0.1:8080:80")
|
||||
IMPLICIT_ZERO=$(grep -n -E '^\s*-\s*"[0-9]+:[0-9]+' "$COMPOSE_FILE" 2>/dev/null || echo "")
|
||||
IMPLICIT_ZERO_ALT=$(grep -n -E '^\s*ports:\s*$' "$COMPOSE_FILE" -A 5 | grep -E '^\s+-\s*[0-9]+:[0-9]+' || echo "")
|
||||
|
||||
if [[ -z "$IMPLICIT_ZERO" && -z "$IMPLICIT_ZERO_ALT" ]]; then
|
||||
print_pass "No implicit 0.0.0.0 port bindings found"
|
||||
else
|
||||
if [[ -n "$IMPLICIT_ZERO" ]]; then
|
||||
print_fail "Found implicit 0.0.0.0 bindings (format: 'PORT:CONTAINER')"
|
||||
echo "$IMPLICIT_ZERO" | while read -r line; do
|
||||
echo -e "${RED} $line${NC}"
|
||||
done
|
||||
fi
|
||||
if [[ -n "$IMPLICIT_ZERO_ALT" ]]; then
|
||||
print_fail "Found implicit 0.0.0.0 bindings (ports: section)"
|
||||
echo "$IMPLICIT_ZERO_ALT" | while read -r line; do
|
||||
echo -e "${RED} $line${NC}"
|
||||
done
|
||||
fi
|
||||
print_warning "Port format 'PORT:CONTAINER' defaults to 0.0.0.0:PORT"
|
||||
print_info "Fix: Use '127.0.0.1:PORT:CONTAINER_PORT' for localhost-only binding"
|
||||
fi
|
||||
|
||||
# Test 5: Verify 127.0.0.1 bindings are used for private services
|
||||
print_test "Test 5: Verify private services use 127.0.0.1 binding (localhost only)"
|
||||
LOCALHOST_BINDINGS=$(grep -n -E '127\.0\.0\.1:[0-9]+' "$COMPOSE_FILE" 2>/dev/null || echo "")
|
||||
LOCALHOST_COUNT=$(echo "$LOCALHOST_BINDINGS" | grep -c "127.0.0" || true)
|
||||
|
||||
if [[ -n "$LOCALHOST_BINDINGS" ]]; then
|
||||
print_pass "Found $LOCALHOST_COUNT service(s) using 127.0.0.1 binding (secure)"
|
||||
echo "$LOCALHOST_BINDINGS" | while read -r line; do
|
||||
echo -e "${GREEN} $line${NC}"
|
||||
done
|
||||
else
|
||||
print_skip "No 127.0.0.1 bindings found - services may have no published ports (acceptable)"
|
||||
fi
|
||||
|
||||
# Test 6: Check for services with no published ports (most secure)
|
||||
print_test "Test 6: Check for services with no published ports (fully private)"
|
||||
print_info "Services with no 'ports:' section are fully internal (most secure)"
|
||||
|
||||
# Count services
|
||||
TOTAL_SERVICES=$(docker compose -f "$COMPOSE_FILE" config --services 2>/dev/null | wc -l)
|
||||
SERVICES_WITH_PORTS=$(grep -c -E '^\s+[a-z-]+:\s*$' "$COMPOSE_FILE" -A 20 | grep -c "ports:" || echo "0")
|
||||
|
||||
if [[ $TOTAL_SERVICES -gt 0 ]]; then
|
||||
PRIVATE_SERVICES=$((TOTAL_SERVICES - SERVICES_WITH_PORTS))
|
||||
print_pass "Services analysis: $TOTAL_SERVICES total, $SERVICES_WITH_PORTS with exposed ports, $PRIVATE_SERVICES fully private"
|
||||
print_info "Services with no published ports are accessible only within Docker networks"
|
||||
else
|
||||
print_skip "Could not count services"
|
||||
fi
|
||||
|
||||
# Test 7: Verify network configuration uses custom bridge networks
|
||||
print_test "Test 7: Verify custom bridge networks are defined (not default bridge)"
|
||||
NETWORKS_SECTION=$(grep -A 10 "^networks:" "$COMPOSE_FILE" 2>/dev/null || echo "")
|
||||
|
||||
if [[ -n "$NETWORKS_SECTION" ]]; then
|
||||
print_pass "Custom networks section found in docker-compose.yml"
|
||||
echo "$NETWORKS_SECTION" | head -5
|
||||
else
|
||||
print_skip "No custom networks defined (services use default bridge)"
|
||||
fi
|
||||
|
||||
# Test 8: Check for internal flag on private networks
|
||||
print_test "Test 8: Check for 'internal: true' on private networks"
|
||||
INTERNAL_NETWORKS=$(grep -B 5 -E 'internal:\s*true' "$COMPOSE_FILE" 2>/dev/null | grep -E '^\s+[a-z-]+:\s*$' || echo "")
|
||||
|
||||
if [[ -n "$INTERNAL_NETWORKS" ]]; then
|
||||
print_pass "Found internal networks (no external access)"
|
||||
echo "$INTERNAL_NETWORKS" | while read -r line; do
|
||||
echo -e "${GREEN} $line${NC}"
|
||||
done
|
||||
else
|
||||
print_skip "No internal networks found (acceptable - not all services need internal flag)"
|
||||
fi
|
||||
|
||||
# Test 9: Verify no host networking mode
|
||||
print_test "Test 9: Verify services don't use 'network_mode: host' (security risk)"
|
||||
HOST_NETWORK=$(grep -E 'network_mode:\s*host' "$COMPOSE_FILE" 2>/dev/null || echo "")
|
||||
|
||||
if [[ -z "$HOST_NETWORK" ]]; then
|
||||
print_pass "No services using host networking mode"
|
||||
else
|
||||
print_fail "Found 'network_mode: host' - VIOLATES isolation principles!"
|
||||
echo "$HOST_NETWORK" | while read -r line; do
|
||||
echo -e "${RED} $line${NC}"
|
||||
done
|
||||
print_warning "Host networking bypasses Docker network isolation"
|
||||
fi
|
||||
|
||||
# Test 10: Generate INF-02 compliance report
|
||||
print_test "Test 10: Generate INF-02 compliance summary"
|
||||
|
||||
# Collect all issues
|
||||
TOTAL_ISSUES=0
|
||||
if [[ $ZERO_COUNT -gt 0 ]]; then
|
||||
((TOTAL_ISSUES += ZERO_COUNT)) || true
|
||||
fi
|
||||
if [[ -n "$IMPLICIT_ZERO" || -n "$IMPLICIT_ZERO_ALT" ]]; then
|
||||
((TOTAL_ISSUES++)) || true
|
||||
fi
|
||||
if [[ -n "$HOST_NETWORK" ]]; then
|
||||
((TOTAL_ISSUES++)) || true
|
||||
fi
|
||||
|
||||
echo -e "\n${BLUE}[*] INF-02 Compliance Report${NC}"
|
||||
echo "Compose file: $COMPOSE_FILE"
|
||||
echo "Total services: $TOTAL_SERVICES"
|
||||
echo "Services with exposed ports: $SERVICES_WITH_PORTS"
|
||||
echo "Fully private services: $PRIVATE_SERVICES"
|
||||
|
||||
if [[ $TOTAL_ISSUES -eq 0 ]]; then
|
||||
echo -e "\n${GREEN}[✓] INF-02 STATUS: COMPLIANT${NC}"
|
||||
print_pass "No security violations found"
|
||||
echo " - No 0.0.0.0 bindings"
|
||||
echo " - No implicit 0.0.0.0 bindings"
|
||||
echo " - No host networking mode"
|
||||
echo " - $PRIVATE_SERVICES services fully private"
|
||||
else
|
||||
echo -e "\n${RED}[✗] INF-02 STATUS: NON-COMPLIANT${NC}"
|
||||
print_fail "Found $TOTAL_ISSUES compliance issue(s)"
|
||||
echo " - 0.0.0.0 bindings: $ZERO_COUNT"
|
||||
echo " - Implicit bindings: $([[ -n "$IMPLICIT_ZERO" || -n "$IMPLICIT_ZERO_ALT" ]] && echo "yes" || echo "no")"
|
||||
echo " - Host networking: $([[ -n "$HOST_NETWORK" ]] && echo "yes" || echo "no")"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
print_header "Test Summary"
|
||||
echo -e "Total tests run: $((pass_count + fail_count + skip_count))"
|
||||
echo -e "${GREEN}Passed: $pass_count${NC}"
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "${RED}Failed: $fail_count${NC}"
|
||||
fi
|
||||
if [[ $skip_count -gt 0 ]]; then
|
||||
echo -e "${YELLOW}Skipped: $skip_count${NC}"
|
||||
fi
|
||||
|
||||
# Exit with appropriate code
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "\n${RED}INF-02 compliance tests FAILED${NC}"
|
||||
echo -e "Please fix the violations above before deploying to production."
|
||||
exit 1
|
||||
elif [[ $TOTAL_ISSUES -gt 0 ]]; then
|
||||
echo -e "\n${YELLOW}INF-02 compliance warnings detected${NC}"
|
||||
echo -e "Consider fixing the issues above for better security posture."
|
||||
exit 0
|
||||
else
|
||||
echo -e "\n${GREEN}All INF-02 compliance tests PASSED${NC}"
|
||||
echo -e "Infrastructure is compliant with security requirements."
|
||||
exit 0
|
||||
fi
|
||||
@@ -1,244 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Test 04: Infrastructure Verification
|
||||
# Verifies that docker-compose.yml infrastructure is correctly deployed
|
||||
# Usage: bash labs/lab-02-network/tests/04-verify-infrastructure.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LAB_DIR="$(cd "$TEST_DIR/.." && pwd)"
|
||||
|
||||
# Counter helpers
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
|
||||
# Helper functions
|
||||
print_header() {
|
||||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║${NC} ${BOLD}$1${NC}"
|
||||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
}
|
||||
|
||||
print_test() {
|
||||
echo -e "\n${BLUE}[TEST]${NC} $1"
|
||||
}
|
||||
|
||||
print_pass() {
|
||||
echo -e " ${GREEN}[✓]${NC} $1"
|
||||
inc_pass
|
||||
}
|
||||
|
||||
print_fail() {
|
||||
echo -e " ${RED}[✗]${NC} $1"
|
||||
inc_fail
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e " ${BLUE}[i]${NC} $1"
|
||||
}
|
||||
|
||||
# Main verification
|
||||
print_header "Lab 02 Infrastructure Verification"
|
||||
|
||||
cd "$LAB_DIR"
|
||||
|
||||
# Test 1: docker-compose.yml exists
|
||||
print_test "Verifying docker-compose.yml exists"
|
||||
if [[ -f "docker-compose.yml" ]]; then
|
||||
print_pass "docker-compose.yml found"
|
||||
else
|
||||
print_fail "docker-compose.yml not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: docker-compose.yml is valid
|
||||
print_test "Validating docker-compose.yml syntax"
|
||||
if docker compose config &> /dev/null; then
|
||||
print_pass "docker-compose.yml has valid syntax"
|
||||
else
|
||||
print_fail "docker-compose.yml has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Networks are defined
|
||||
print_test "Verifying VPC networks are defined"
|
||||
if docker compose config --format json 2>/dev/null | grep -q '"networks"'; then
|
||||
print_pass "Networks section found in compose file"
|
||||
|
||||
# Check for vpc-public
|
||||
if docker compose config --format json 2>/dev/null | grep -q '"vpc-public"'; then
|
||||
print_pass " vpc-public network defined"
|
||||
else
|
||||
print_fail " vpc-public network NOT defined"
|
||||
fi
|
||||
|
||||
# Check for vpc-private
|
||||
if docker compose config --format json 2>/dev/null | grep -q '"vpc-private"'; then
|
||||
print_pass " vpc-private network defined"
|
||||
else
|
||||
print_fail " vpc-private network NOT defined"
|
||||
fi
|
||||
else
|
||||
print_fail "No networks defined"
|
||||
fi
|
||||
|
||||
# Test 4: INF-02 compliance check
|
||||
print_test "Checking INF-02 compliance (no 0.0.0.0 bindings)"
|
||||
ZERO_BINDINGS=$(awk '/0\.0\.0\.0:/ {count++} END {print count+0}' docker-compose.yml 2>/dev/null)
|
||||
if [[ "$ZERO_BINDINGS" -eq 0 ]]; then
|
||||
print_pass "No 0.0.0.0 port bindings found (INF-02 compliant)"
|
||||
else
|
||||
print_fail "Found $ZERO_BINDINGS 0.0.0.0 bindings - INF-02 VIOLATION"
|
||||
fi
|
||||
|
||||
# Test 5: Check for 127.0.0.1 bindings
|
||||
print_test "Checking for localhost-only bindings (127.0.0.1)"
|
||||
LOCALHOST_BINDINGS=$(awk '/127\.0\.0\.1:/ {count++} END {print count+0}' docker-compose.yml 2>/dev/null)
|
||||
if [[ $LOCALHOST_BINDINGS -gt 0 ]]; then
|
||||
print_pass "Found $LOCALHOST_BINDINGS localhost-only bindings (secure)"
|
||||
else
|
||||
print_info "No 127.0.0.1 bindings - services may have no published ports"
|
||||
fi
|
||||
|
||||
# Test 6: Start services
|
||||
print_test "Starting Docker Compose services"
|
||||
if docker compose up -d &> /dev/null; then
|
||||
print_pass "Services started successfully"
|
||||
sleep 3 # Give services time to start
|
||||
else
|
||||
print_fail "Failed to start services"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 7: Verify containers are running
|
||||
print_test "Verifying containers are running"
|
||||
RUNNING_CONTAINERS=$(docker compose ps --services | wc -l)
|
||||
if [[ $RUNNING_CONTAINERS -ge 3 ]]; then
|
||||
print_pass "Services running: $RUNNING_CONTAINERS containers"
|
||||
docker compose ps
|
||||
else
|
||||
print_fail "Not enough containers running: $RUNNING_CONTAINERS (expected 3+)"
|
||||
fi
|
||||
|
||||
# Test 8: Verify network creation
|
||||
print_test "Verifying VPC networks were created"
|
||||
if docker network ls --format '{{.Name}}' | grep -q "lab02-vpc-public"; then
|
||||
print_pass " lab02-vpc-public network exists"
|
||||
else
|
||||
print_fail " lab02-vpc-public network NOT found"
|
||||
fi
|
||||
|
||||
if docker network ls --format '{{.Name}}' | grep -q "lab02-vpc-private"; then
|
||||
print_pass " lab02-vpc-private network exists"
|
||||
else
|
||||
print_fail " lab02-vpc-private network NOT found"
|
||||
fi
|
||||
|
||||
# Test 9: Verify subnet configuration
|
||||
print_test "Verifying subnet CIDR configuration"
|
||||
PUBLIC_SUBNET=$(docker network inspect lab02-vpc-public --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null)
|
||||
PRIVATE_SUBNET=$(docker network inspect lab02-vpc-private --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null)
|
||||
|
||||
if [[ "$PUBLIC_SUBNET" == "10.0.1.0/24" ]]; then
|
||||
print_pass " Public subnet: $PUBLIC_SUBNET (correct)"
|
||||
else
|
||||
print_fail " Public subnet: $PUBLIC_SUBNET (expected 10.0.1.0/24)"
|
||||
fi
|
||||
|
||||
if [[ "$PRIVATE_SUBNET" == "10.0.2.0/24" ]]; then
|
||||
print_pass " Private subnet: $PRIVATE_SUBNET (correct)"
|
||||
else
|
||||
print_fail " Private subnet: $PRIVATE_SUBNET (expected 10.0.2.0/24)"
|
||||
fi
|
||||
|
||||
# Test 10: Verify private network isolation
|
||||
print_test "Verifying private network isolation flag"
|
||||
INTERNAL_FLAG=$(docker network inspect lab02-vpc-private --format '{{.Internal}}' 2>/dev/null)
|
||||
if [[ "$INTERNAL_FLAG" == "true" ]]; then
|
||||
print_pass "Private network has internal=true flag (isolated)"
|
||||
else
|
||||
print_fail "Private network missing internal flag"
|
||||
fi
|
||||
|
||||
# Test 11: Verify container network placement
|
||||
print_test "Verifying container network placement"
|
||||
WEB_NETWORK=$(docker inspect lab02-web --format '{{json .NetworkSettings.Networks}}' 2>/dev/null | jq -r 'keys[]' 2>/dev/null | grep "lab02-vpc-public" || echo "")
|
||||
if [[ -n "$WEB_NETWORK" ]]; then
|
||||
print_pass " lab02-web in vpc-public network"
|
||||
else
|
||||
print_fail " lab02-web not in vpc-public"
|
||||
fi
|
||||
|
||||
DB_NETWORK=$(docker inspect lab02-db --format '{{json .NetworkSettings.Networks}}' 2>/dev/null | jq -r 'keys[]' 2>/dev/null | grep "lab02-vpc-private" || echo "")
|
||||
if [[ -n "$DB_NETWORK" ]]; then
|
||||
print_pass " lab02-db in vpc-private network"
|
||||
else
|
||||
print_fail " lab02-db not in vpc-private"
|
||||
fi
|
||||
|
||||
# Test 12: Verify multi-homed container
|
||||
print_test "Verifying multi-homed container (app in both networks)"
|
||||
PUBLIC_IP=$(docker inspect lab02-app --format '{{json .NetworkSettings.Networks}}' 2>/dev/null | jq -r '.["lab02-vpc-public"].IPAddress // ""' 2>/dev/null)
|
||||
PRIVATE_IP=$(docker inspect lab02-app --format '{{json .NetworkSettings.Networks}}' 2>/dev/null | jq -r '.["lab02-vpc-private"].IPAddress // ""' 2>/dev/null)
|
||||
|
||||
if [[ -n "$PUBLIC_IP" && -n "$PRIVATE_IP" ]]; then
|
||||
print_pass "lab02-app is multi-homed (public: $PUBLIC_IP, private: $PRIVATE_IP)"
|
||||
else
|
||||
print_fail "lab02-app not properly connected to both networks"
|
||||
fi
|
||||
|
||||
# Test 13: Verify web service accessibility
|
||||
print_test "Verifying web service is accessible from localhost"
|
||||
if curl -sf http://127.0.0.1:8080 &> /dev/null; then
|
||||
print_pass "Web service responds on http://127.0.0.1:8080"
|
||||
else
|
||||
print_fail "Web service not accessible on http://127.0.0.1:8080"
|
||||
fi
|
||||
|
||||
# Test 14: Verify database is NOT accessible from host
|
||||
print_test "Verifying database is NOT accessible from host (private)"
|
||||
if curl -sf http://127.0.0.1:5432 &> /dev/null; then
|
||||
print_fail "Database is accessible from host - PRIVATE NETWORK COMPROMISED!"
|
||||
else
|
||||
print_pass "Database is NOT accessible from host (correct - isolated)"
|
||||
fi
|
||||
|
||||
# Test 15: Verify isolation between networks
|
||||
print_test "Verifying cross-network isolation (web cannot reach db)"
|
||||
if docker exec lab02-web ping -c 1 -W 1 lab02-db &> /dev/null; then
|
||||
print_fail "Web CAN reach database - ISOLATION FAILED!"
|
||||
else
|
||||
print_pass "Web CANNOT reach database - isolation working correctly"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
print_header "Infrastructure Verification Summary"
|
||||
|
||||
echo -e "Tests run: $((pass_count + fail_count))"
|
||||
echo -e "${GREEN}Passed: $pass_count${NC}"
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "${RED}Failed: $fail_count${NC}"
|
||||
fi
|
||||
|
||||
if [[ $fail_count -eq 0 ]]; then
|
||||
echo -e "\n${GREEN}${BOLD}✓ ALL INFRASTRUCTURE CHECKS PASSED${NC}"
|
||||
echo -e "\nInfrastructure is correctly deployed and compliant!"
|
||||
echo -e "You can now proceed with the tutorials."
|
||||
exit 0
|
||||
else
|
||||
echo -e "\n${RED}Some infrastructure checks failed${NC}"
|
||||
echo -e "Please review the failures above."
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,196 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Quick Test: Fast Validation for Development
|
||||
# Runs subset of critical tests for rapid feedback during development
|
||||
# Usage: bash labs/lab-02-network/tests/quick-test.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$TEST_DIR/../.." && pwd)"
|
||||
|
||||
# Counter helpers
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
|
||||
# Helper functions
|
||||
print_header() {
|
||||
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║${NC} ${BOLD}$1${NC}"
|
||||
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
}
|
||||
|
||||
print_test() {
|
||||
echo -e "\n${BLUE}[TEST]${NC} $1"
|
||||
}
|
||||
|
||||
print_pass() {
|
||||
echo -e " ${GREEN}[✓]${NC} $1"
|
||||
inc_pass
|
||||
}
|
||||
|
||||
print_fail() {
|
||||
echo -e " ${RED}[✗]${NC} $1"
|
||||
inc_fail
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e " ${CYAN}[i]${NC} $1"
|
||||
}
|
||||
|
||||
# Main header
|
||||
clear
|
||||
print_header "Lab 02: Quick Test (Fast Validation)"
|
||||
echo ""
|
||||
echo -e "Running critical tests only (< 30 seconds)"
|
||||
echo -e "For full test suite, run: ${YELLOW}bash run-all-tests.sh${NC}"
|
||||
echo ""
|
||||
|
||||
# Quick Test 1: Docker availability
|
||||
print_test "Docker is available"
|
||||
if command -v docker &> /dev/null; then
|
||||
print_pass "Docker command found"
|
||||
print_info "$(docker --version)"
|
||||
else
|
||||
print_fail "Docker not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Quick Test 2: Docker Compose file exists
|
||||
print_test "docker-compose.yml exists"
|
||||
COMPOSE_FILE="$PROJECT_ROOT/labs/lab-02-network/docker-compose.yml"
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
print_pass "docker-compose.yml found"
|
||||
else
|
||||
print_fail "docker-compose.yml not found (expected after Tutorial 1)"
|
||||
print_info "This is OK if you're starting the lab"
|
||||
fi
|
||||
|
||||
# Quick Test 3: Validate compose syntax (if file exists)
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
print_test "docker-compose.yml has valid syntax"
|
||||
if docker compose -f "$COMPOSE_FILE" config &> /dev/null; then
|
||||
print_pass "Compose file is valid YAML"
|
||||
else
|
||||
print_fail "Compose file has syntax errors"
|
||||
print_info "Run: docker compose -f docker-compose.yml config"
|
||||
fi
|
||||
|
||||
# Quick Test 4: INF-02 compliance (no 0.0.0.0 bindings)
|
||||
print_test "INF-02 compliance (no 0.0.0.0 bindings)"
|
||||
ZERO_COUNT=$(grep -c -E '0\.0\.0\.0:[0-9]+' "$COMPOSE_FILE" 2>/dev/null || echo "0")
|
||||
if [[ $ZERO_COUNT -eq 0 ]]; then
|
||||
print_pass "No 0.0.0.0 bindings (secure)"
|
||||
else
|
||||
print_fail "Found $ZERO_COUNT 0.0.0.0 bindings (INF-02 violation)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Quick Test 5: Docker networks can be created
|
||||
print_test "Docker network creation works"
|
||||
if docker network create --driver bridge --subnet 10.0.99.0/24 quick-test-net &> /dev/null; then
|
||||
print_pass "Can create bridge network with custom subnet"
|
||||
docker network rm quick-test-net &> /dev/null
|
||||
else
|
||||
print_fail "Failed to create test network"
|
||||
fi
|
||||
|
||||
# Quick Test 6: Network isolation works
|
||||
print_test "Network isolation verification"
|
||||
# Create two networks
|
||||
if docker network create --driver bridge --subnet 10.0.98.0/24 quick-test-net1 &> /dev/null && \
|
||||
docker network create --driver bridge --subnet 10.0.97.0/24 quick-test-net2 &> /dev/null; then
|
||||
|
||||
# Create test containers
|
||||
if docker run -d --name qt-c1 --network quick-test-net1 alpine:3.19 sleep 60 &> /dev/null && \
|
||||
docker run -d --name qt-c2 --network quick-test-net2 alpine:3.19 sleep 60 &> /dev/null; then
|
||||
|
||||
# Test cross-network isolation (should fail)
|
||||
if docker exec qt-c1 ping -c 1 -W 1 qt-c2 &> /dev/null; then
|
||||
print_fail "Cross-network communication works (isolation broken!)"
|
||||
else
|
||||
print_pass "Cross-network communication blocked (isolation works)"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
docker stop qt-c1 qt-c2 &> /dev/null
|
||||
docker rm qt-c1 qt-c2 &> /dev/null
|
||||
else
|
||||
print_fail "Failed to create test containers"
|
||||
fi
|
||||
|
||||
# Cleanup networks
|
||||
docker network rm quick-test-net1 quick-test-net2 &> /dev/null
|
||||
else
|
||||
print_fail "Failed to create test networks"
|
||||
fi
|
||||
|
||||
# Quick Test 7: Test scripts exist
|
||||
print_test "Test infrastructure present"
|
||||
TEST_COUNT=0
|
||||
if [[ -f "$TEST_DIR/01-network-creation-test.sh" ]]; then ((TEST_COUNT++)) || true; fi
|
||||
if [[ -f "$TEST_DIR/02-isolation-verification-test.sh" ]]; then ((TEST_COUNT++)) || true; fi
|
||||
if [[ -f "$TEST_DIR/03-inf02-compliance-test.sh" ]]; then ((TEST_COUNT++)) || true; fi
|
||||
|
||||
if [[ $TEST_COUNT -eq 3 ]]; then
|
||||
print_pass "All test scripts present ($TEST_COUNT/3)"
|
||||
else
|
||||
print_fail "Some test scripts missing ($TEST_COUNT/3)"
|
||||
fi
|
||||
|
||||
# Quick Test 8: Documentation exists
|
||||
print_test "Documentation files present"
|
||||
DOC_COUNT=0
|
||||
if [[ -f "$TEST_DIR/../tutorial/01-create-networks.md" ]]; then ((DOC_COUNT++)) || true; fi
|
||||
if [[ -f "$TEST_DIR/../tutorial/02-deploy-containers.md" ]]; then ((DOC_COUNT++)) || true; fi
|
||||
if [[ -f "$TEST_DIR/../tutorial/03-verify-isolation.md" ]]; then ((DOC_COUNT++)) || true; fi
|
||||
|
||||
if [[ $DOC_COUNT -ge 1 ]]; then
|
||||
print_pass "Documentation present ($DOC_COUNT tutorial files)"
|
||||
else
|
||||
print_info "No documentation yet (expected during development)"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
print_header "Quick Test Summary"
|
||||
|
||||
echo -e "Tests run: ${BOLD}$((pass_count + fail_count))${NC}"
|
||||
echo -e " ${GREEN}Passed:${NC} $pass_count"
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e " ${RED}Failed:${NC} $fail_count"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Verdict
|
||||
if [[ $fail_count -eq 0 ]]; then
|
||||
echo -e "${GREEN}${BOLD}✓ ALL QUICK TESTS PASSED${NC}"
|
||||
echo ""
|
||||
echo -e "Quick validation successful!"
|
||||
echo ""
|
||||
echo -e "Next steps:"
|
||||
echo -e " 1. Run full test suite: ${CYAN}bash run-all-tests.sh${NC}"
|
||||
echo -e " 2. Run final verification: ${CYAN}bash 99-final-verification.sh${NC}"
|
||||
echo ""
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}${BOLD}✗ QUICK TESTS FAILED${NC}"
|
||||
echo ""
|
||||
echo -e "Some critical tests failed. Please review:"
|
||||
echo -e " 1. Check Docker is running: ${CYAN}docker ps${NC}"
|
||||
echo -e " 2. Verify compose file: ${CYAN}cd labs/lab-02-network && docker compose config${NC}"
|
||||
echo -e " 3. Run full test suite for details: ${CYAN}bash run-all-tests.sh${NC}"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,146 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Test Orchestration: Run All Tests
|
||||
# Executes all Lab 02 test scripts with fail-fast behavior
|
||||
# Usage: bash labs/lab-02-network/tests/run-all-tests.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Change to test directory
|
||||
cd "$TEST_DIR"
|
||||
|
||||
# Counter helpers
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
skip_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
inc_skip() { ((skip_count++)) || true; }
|
||||
|
||||
# Print header
|
||||
print_header() {
|
||||
echo ""
|
||||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║${NC} ${BOLD}$1${NC}"
|
||||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Print test header
|
||||
print_test_header() {
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${BLUE}Running:${NC} $1"
|
||||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
}
|
||||
|
||||
# Main header
|
||||
print_header "Lab 02: Network & VPC - Test Suite"
|
||||
|
||||
# Test array - all test scripts in order
|
||||
declare -a tests=(
|
||||
"01-network-creation-test.sh"
|
||||
"02-isolation-verification-test.sh"
|
||||
"03-inf02-compliance-test.sh"
|
||||
)
|
||||
|
||||
# Track first failure
|
||||
first_failure=""
|
||||
|
||||
# Run each test
|
||||
for test_script in "${tests[@]}"; do
|
||||
test_path="$TEST_DIR/$test_script"
|
||||
|
||||
# Check if test file exists
|
||||
if [[ ! -f "$test_path" ]]; then
|
||||
echo -e "${YELLOW}[SKIP]${NC} $test_script not found"
|
||||
inc_skip
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if test file is executable
|
||||
if [[ ! -x "$test_path" ]]; then
|
||||
echo -e "${YELLOW}[SKIP]${NC} $test_script not executable"
|
||||
inc_skip
|
||||
continue
|
||||
fi
|
||||
|
||||
print_test_header "$test_script"
|
||||
|
||||
# Run test and capture exit code
|
||||
if bash "$test_path"; then
|
||||
echo -e "${GREEN}[✓]${NC} $test_script passed"
|
||||
inc_pass
|
||||
echo ""
|
||||
else
|
||||
exit_code=$?
|
||||
echo -e "${RED}[✗]${NC} $test_script failed (exit code: $exit_code)"
|
||||
inc_fail
|
||||
|
||||
# Record first failure for summary
|
||||
if [[ -z "$first_failure" ]]; then
|
||||
first_failure="$test_script"
|
||||
fi
|
||||
|
||||
# Fail-fast: stop on first failure
|
||||
echo ""
|
||||
echo -e "${RED}[FATAL]${NC} Test failed. Stopping test suite (fail-fast mode)."
|
||||
echo ""
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Print summary
|
||||
print_header "Test Suite Summary"
|
||||
|
||||
echo -e "Total tests run: ${BOLD}$((pass_count + fail_count + skip_count))${NC}"
|
||||
echo -e " ${GREEN}Passed:${NC} $pass_count"
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e " ${RED}Failed:${NC} $fail_count"
|
||||
fi
|
||||
if [[ $skip_count -gt 0 ]]; then
|
||||
echo -e " ${YELLOW}Skipped:${NC} $skip_count"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Final verdict
|
||||
if [[ $fail_count -eq 0 && $skip_count -eq 0 ]]; then
|
||||
echo -e "${GREEN}${BOLD}✓ ALL TESTS PASSED${NC}"
|
||||
echo ""
|
||||
echo -e "Next step: Run final verification"
|
||||
echo -e " ${CYAN}bash labs/lab-02-network/tests/99-final-verification.sh${NC}"
|
||||
echo ""
|
||||
exit 0
|
||||
elif [[ $fail_count -eq 0 ]]; then
|
||||
echo -e "${YELLOW}Some tests were skipped${NC}"
|
||||
echo ""
|
||||
echo -e "Note: Skipped tests are expected during RED phase (before implementation)."
|
||||
echo -e " These tests will pass after completing GREEN phase (implementation)."
|
||||
echo ""
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}${BOLD}✗ TESTS FAILED${NC}"
|
||||
echo ""
|
||||
echo -e "First failure: ${RED}$first_failure${NC}"
|
||||
echo ""
|
||||
echo -e "To debug:"
|
||||
echo -e " 1. Run the failed test directly to see detailed output:"
|
||||
echo -e " ${CYAN}bash labs/lab-02-network/tests/$first_failure${NC}"
|
||||
echo ""
|
||||
echo -e " 2. Check infrastructure setup:"
|
||||
echo -e " ${CYAN}cd labs/lab-02-network && docker compose config${NC}"
|
||||
echo ""
|
||||
echo -e " 3. Review test logs for specific failures"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
@@ -198,20 +198,6 @@ Questo e corretto per una subnet privata cloud.
|
||||
|
||||
---
|
||||
|
||||
## Passo 8: Test Container di Isolamento
|
||||
|
||||
Usa lo script di test del lab.
|
||||
|
||||
Esegui:
|
||||
|
||||
```bash
|
||||
bash tests/02-isolation-verification-test.sh
|
||||
```
|
||||
|
||||
Questo script verifica automaticamente tutti i casi di isolamento.
|
||||
|
||||
---
|
||||
|
||||
## Matrice di Connettività
|
||||
|
||||
| Source | Target | Stesso Network | Risultato |
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Test 01: Resource Limits Configuration
|
||||
# Verifies that docker-compose.yml services have mandatory resource limits
|
||||
# Usage: bash labs/lab-03-compute/tests/01-resource-limits-test.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LAB_DIR="$(cd "$TEST_DIR/.." && pwd)"
|
||||
|
||||
# Counter helpers
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
|
||||
# Helper functions
|
||||
print_header() {
|
||||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║${NC} ${BOLD}$1${NC}"
|
||||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
}
|
||||
|
||||
print_test() {
|
||||
echo -e "\n${BLUE}[TEST]${NC} $1"
|
||||
}
|
||||
|
||||
print_pass() {
|
||||
echo -e " ${GREEN}[✓]${NC} $1"
|
||||
inc_pass
|
||||
}
|
||||
|
||||
print_fail() {
|
||||
echo -e " ${RED}[✗]${NC} $1"
|
||||
inc_fail
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e " ${BLUE}[i]${NC} $1"
|
||||
}
|
||||
|
||||
# Main verification
|
||||
print_header "Lab 03 Resource Limits Verification"
|
||||
|
||||
cd "$LAB_DIR"
|
||||
|
||||
# Test 1: docker-compose.yml exists
|
||||
print_test "Verifying docker-compose.yml exists"
|
||||
if [[ -f "docker-compose.yml" ]]; then
|
||||
print_pass "docker-compose.yml found"
|
||||
else
|
||||
print_fail "docker-compose.yml not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: docker-compose.yml is valid
|
||||
print_test "Validating docker-compose.yml syntax"
|
||||
if docker compose config &> /dev/null; then
|
||||
print_pass "docker-compose.yml has valid syntax"
|
||||
else
|
||||
print_fail "docker-compose.yml has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Services are defined
|
||||
print_test "Verifying services are defined"
|
||||
SERVICES=$(docker compose config --services 2>/dev/null)
|
||||
SERVICE_COUNT=$(echo "$SERVICES" | wc -l)
|
||||
if [[ $SERVICE_COUNT -gt 0 ]]; then
|
||||
print_pass "Found $SERVICE_COUNT services"
|
||||
echo "$SERVICES" | while read -r service; do
|
||||
print_info " - $service"
|
||||
done
|
||||
else
|
||||
print_fail "No services defined"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 4: INF-03 compliance check - all services must have resource limits
|
||||
print_test "Checking INF-03 compliance (resource limits)"
|
||||
NON_COMPLIANT=0
|
||||
|
||||
for service in $SERVICES; do
|
||||
# Check for deploy.resources section
|
||||
has_deploy=$(docker compose config 2>/dev/null | grep -A 20 "^$service:" | grep -c "deploy:" || echo "0")
|
||||
has_resources=$(docker compose config 2>/dev/null | grep -A 25 "^$service:" | grep -c "resources:" || echo "0")
|
||||
|
||||
if [[ $has_deploy -eq 0 || $has_resources -eq 0 ]]; then
|
||||
print_fail " $service: Missing deploy.resources section"
|
||||
((NON_COMPLIANT++)) || true
|
||||
else
|
||||
# Check for CPU limit
|
||||
has_cpu=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep -c "cpus:" || echo "0")
|
||||
# Check for memory limit
|
||||
has_memory=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep -c "memory:" || echo "0")
|
||||
|
||||
if [[ $has_cpu -eq 0 ]]; then
|
||||
print_fail " $service: Missing cpus limit"
|
||||
((NON_COMPLIANT++)) || true
|
||||
fi
|
||||
|
||||
if [[ $has_memory -eq 0 ]]; then
|
||||
print_fail " $service: Missing memory limit"
|
||||
((NON_COMPLIANT++)) || true
|
||||
fi
|
||||
|
||||
if [[ $has_cpu -gt 0 && $has_memory -gt 0 ]]; then
|
||||
# Extract limits for reporting
|
||||
cpu_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "cpus:" | sed 's/.*cpus: //' | tr -d ' "')
|
||||
mem_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "memory:" | sed 's/.*memory: //' | tr -d " '")
|
||||
|
||||
print_pass " $service: cpus: $cpu_limit, memory: $mem_limit"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $NON_COMPLIANT -eq 0 ]]; then
|
||||
print_pass "INF-03 compliance: All services have resource limits"
|
||||
else
|
||||
print_fail "INF-03 compliance: $NON_COMPLIANT services missing limits"
|
||||
fi
|
||||
|
||||
# Test 5: Verify specific EC2 instance type parallels
|
||||
print_test "Verifying EC2 instance type parallels"
|
||||
INSTANCE_TYPES=0
|
||||
|
||||
for service in $SERVICES; do
|
||||
cpu_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "cpus:" | sed 's/.*cpus: //' | tr -d ' "' || echo "")
|
||||
mem_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "memory:" | sed 's/.*memory: //' | tr -d " '"" || echo "")
|
||||
|
||||
# Map to EC2 instance types
|
||||
if [[ -n "$cpu_limit" && -n "$mem_limit" ]]; then
|
||||
case "$cpu_limit:$mem_limit" in
|
||||
"0.5:512M"|"0.5:512")
|
||||
instance_type="t2.nano"
|
||||
;;
|
||||
"1:1G"|"1:1024M"|"1:1024")
|
||||
instance_type="t2.micro"
|
||||
;;
|
||||
"1:2G"|"1:2048M"|"1:2048")
|
||||
instance_type="t2.small"
|
||||
;;
|
||||
"2:4G"|"2:4096M"|"2:4096")
|
||||
instance_type="t2.medium"
|
||||
;;
|
||||
"2:8G"|"2:8192M"|"2:8192")
|
||||
instance_type="m5.large"
|
||||
;;
|
||||
*)
|
||||
instance_type="custom"
|
||||
;;
|
||||
esac
|
||||
|
||||
print_info " $service → $instance_type (cpus: $cpu_limit, memory: $mem_limit)"
|
||||
((INSTANCE_TYPES++)) || true
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $INSTANCE_TYPES -gt 0 ]]; then
|
||||
print_pass "EC2 instance type mapping complete for $INSTANCE_TYPES services"
|
||||
else
|
||||
print_fail "No services with valid resource limits found"
|
||||
fi
|
||||
|
||||
# Test 6: Verify resource limit formats
|
||||
print_test "Verifying resource limit formats"
|
||||
FORMAT_OK=0
|
||||
|
||||
for service in $SERVICES; do
|
||||
cpu_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "cpus:" | sed 's/.*cpus: //' | tr -d ' "' || echo "")
|
||||
|
||||
# CPU limit should be a number or decimal
|
||||
if [[ -n "$cpu_limit" ]]; then
|
||||
if [[ "$cpu_limit" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
|
||||
((FORMAT_OK++)) || true
|
||||
else
|
||||
print_fail " $service: Invalid CPU format: $cpu_limit"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $FORMAT_OK -eq $SERVICE_COUNT ]]; then
|
||||
print_pass "All resource limits use valid format"
|
||||
else
|
||||
print_fail "Some resource limits have invalid format"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
print_header "Resource Limits Verification Summary"
|
||||
|
||||
echo -e "Tests run: $((pass_count + fail_count))"
|
||||
echo -e "${GREEN}Passed: $pass_count${NC}"
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "${RED}Failed: $fail_count${NC}"
|
||||
fi
|
||||
|
||||
if [[ $fail_count -eq 0 ]]; then
|
||||
echo -e "\n${GREEN}${BOLD}✓ ALL RESOURCE LIMITS CHECKS PASSED${NC}"
|
||||
echo -e "\nINF-03 compliance verified!"
|
||||
exit 0
|
||||
else
|
||||
echo -e "\n${RED}Some resource limits checks failed${NC}"
|
||||
echo -e "Please ensure all services have cpus and memory limits."
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,255 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Test 02: Healthcheck Configuration
|
||||
# Verifies that docker-compose.yml services have healthchecks configured
|
||||
# Usage: bash labs/lab-03-compute/tests/02-healthcheck-test.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LAB_DIR="$(cd "$TEST_DIR/.." && pwd)"
|
||||
|
||||
# Counter helpers
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
|
||||
# Helper functions
|
||||
print_header() {
|
||||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║${NC} ${BOLD}$1${NC}"
|
||||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
}
|
||||
|
||||
print_test() {
|
||||
echo -e "\n${BLUE}[TEST]${NC} $1"
|
||||
}
|
||||
|
||||
print_pass() {
|
||||
echo -e " ${GREEN}[✓]${NC} $1"
|
||||
inc_pass
|
||||
}
|
||||
|
||||
print_fail() {
|
||||
echo -e " ${RED}[✗]${NC} $1"
|
||||
inc_fail
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e " ${BLUE}[i]${NC} $1"
|
||||
}
|
||||
|
||||
# Main verification
|
||||
print_header "Lab 03 Healthcheck Verification"
|
||||
|
||||
cd "$LAB_DIR"
|
||||
|
||||
# Test 1: docker-compose.yml exists
|
||||
print_test "Verifying docker-compose.yml exists"
|
||||
if [[ -f "docker-compose.yml" ]]; then
|
||||
print_pass "docker-compose.yml found"
|
||||
else
|
||||
print_fail "docker-compose.yml not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: docker-compose.yml is valid
|
||||
print_test "Validating docker-compose.yml syntax"
|
||||
if docker compose config &> /dev/null; then
|
||||
print_pass "docker-compose.yml has valid syntax"
|
||||
else
|
||||
print_fail "docker-compose.yml has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Services are defined
|
||||
print_test "Verifying services are defined"
|
||||
SERVICES=$(docker compose config --services 2>/dev/null)
|
||||
SERVICE_COUNT=$(echo "$SERVICES" | wc -l)
|
||||
if [[ $SERVICE_COUNT -gt 0 ]]; then
|
||||
print_pass "Found $SERVICE_COUNT services"
|
||||
else
|
||||
print_fail "No services defined"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 4: Healthcheck configuration check
|
||||
print_test "Checking healthcheck configuration"
|
||||
MISSING_HEALTHCHECK=0
|
||||
|
||||
for service in $SERVICES; do
|
||||
# Check for healthcheck section
|
||||
has_healthcheck=$(docker compose config 2>/dev/null | grep -A 50 "^$service:" | grep -c "healthcheck:" || echo "0")
|
||||
|
||||
if [[ $has_healthcheck -eq 0 ]]; then
|
||||
print_fail " $service: Missing healthcheck section"
|
||||
((MISSING_HEALTHCHECK++)) || true
|
||||
else
|
||||
# Verify healthcheck has test command
|
||||
has_test=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 5 "healthcheck:" | grep -c "test:" || echo "0")
|
||||
|
||||
if [[ $has_test -eq 0 ]]; then
|
||||
print_fail " $service: Missing healthcheck test command"
|
||||
((MISSING_HEALTHCHECK++)) || true
|
||||
else
|
||||
# Extract test command for reporting
|
||||
test_cmd=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 5 "healthcheck:" | grep "test:" | head -1 | sed 's/.*test: //' | tr -d '"')
|
||||
print_pass " $service: healthcheck configured"
|
||||
print_info " test: $test_cmd"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $MISSING_HEALTHCHECK -eq 0 ]]; then
|
||||
print_pass "All services have healthchecks configured"
|
||||
else
|
||||
print_fail "$MISSING_HEALTHCHECK services missing healthchecks"
|
||||
fi
|
||||
|
||||
# Test 5: Healthcheck parameters verification
|
||||
print_test "Verifying healthcheck parameters"
|
||||
PARAMS_OK=0
|
||||
|
||||
for service in $SERVICES; do
|
||||
has_healthcheck=$(docker compose config 2>/dev/null | grep -A 50 "^$service:" | grep -c "healthcheck:" || echo "0")
|
||||
|
||||
if [[ $has_healthcheck -gt 0 ]]; then
|
||||
# Check for interval
|
||||
has_interval=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep -c "interval:" || echo "0")
|
||||
# Check for timeout
|
||||
has_timeout=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep -c "timeout:" || echo "0")
|
||||
# Check for retries
|
||||
has_retries=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep -c "retries:" || echo "0")
|
||||
|
||||
interval=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep "interval:" | sed 's/.*interval: //' | tr -d " '"" || echo "N/A")
|
||||
timeout=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep "timeout:" | sed 's/.*timeout: //' | tr -d " '"" || echo "N/A")
|
||||
retries=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep "retries:" | sed 's/.*retries: //' | tr -d " '"" || echo "N/A")
|
||||
|
||||
if [[ $has_interval -gt 0 && $has_timeout -gt 0 && $has_retries -gt 0 ]]; then
|
||||
print_pass " $service: interval=$interval, timeout=$timeout, retries=$retries"
|
||||
((PARAMS_OK++)) || true
|
||||
else
|
||||
print_info " $service: interval=$interval, timeout=$timeout, retries=$retries"
|
||||
# Check for start_period (optional)
|
||||
has_start_period=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep -c "start_period:" || echo "0")
|
||||
if [[ $has_start_period -gt 0 ]]; then
|
||||
start_period=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep "start_period:" | sed 's/.*start_period: //' | tr -d " '"" || echo "")
|
||||
print_info " start_period=$start_period"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $PARAMS_OK -gt 0 ]]; then
|
||||
print_pass "$PARAMS_OK services have complete healthcheck parameters"
|
||||
else
|
||||
print_fail "No services with complete healthcheck parameters"
|
||||
fi
|
||||
|
||||
# Test 6: Healthcheck command types
|
||||
print_test "Analyzing healthcheck command types"
|
||||
HTTP_COUNT=0
|
||||
CMD_SHELL_COUNT=0
|
||||
CMD_COUNT=0
|
||||
CUSTOM_COUNT=0
|
||||
|
||||
for service in $SERVICES; do
|
||||
has_healthcheck=$(docker compose config 2>/dev/null | grep -A 50 "^$service:" | grep -c "healthcheck:" || echo "0")
|
||||
|
||||
if [[ $has_healthcheck -gt 0 ]]; then
|
||||
# Get test command
|
||||
test_section=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" || echo "")
|
||||
|
||||
if echo "$test_section" | grep -q "CMD-SHELL"; then
|
||||
print_info " $service: CMD-SHELL healthcheck"
|
||||
((CMD_SHELL_COUNT++)) || true
|
||||
elif echo "$test_section" | grep -q "CMD"; then
|
||||
print_info " $service: CMD healthcheck"
|
||||
((CMD_COUNT++)) || true
|
||||
else
|
||||
print_info " $service: Custom healthcheck format"
|
||||
((CUSTOM_COUNT++)) || true
|
||||
fi
|
||||
|
||||
# Check if HTTP-based
|
||||
if echo "$test_section" | grep -qiE "(wget|curl|http)"; then
|
||||
((HTTP_COUNT++)) || true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
print_info "Healthcheck types: CMD-SHELL ($CMD_SHELL_COUNT), CMD ($CMD_COUNT), Custom ($CUSTOM_COUNT)"
|
||||
if [[ $HTTP_COUNT -gt 0 ]]; then
|
||||
print_pass "$HTTP_COUNT services use HTTP-based healthchecks"
|
||||
fi
|
||||
|
||||
# Test 7: ELB Health Check Parallel verification
|
||||
print_test "Verifying ELB Health Check parallelism"
|
||||
ELB_PARALLEL=0
|
||||
|
||||
for service in $SERVICES; do
|
||||
has_healthcheck=$(docker compose config 2>/dev/null | grep -A 50 "^$service:" | grep -c "healthcheck:" || echo "0")
|
||||
|
||||
if [[ $has_healthcheck -gt 0 ]]; then
|
||||
interval=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep "interval:" | sed 's/.*interval: //' | tr -d " '"" || echo "")
|
||||
timeout=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep "timeout:" | sed 's/.*timeout: //' | tr -d " '"" || echo "")
|
||||
retries=$(docker compose config 2>/dev/null | grep -A 60 "^$service:" | grep -A 10 "healthcheck:" | grep "retries:" | sed 's/.*retries: //' | tr -d " '"" || echo "")
|
||||
|
||||
# Map to ELB defaults
|
||||
if [[ "$interval" == "30s" || "$interval" =~ ^30 ]]; then
|
||||
elb_interval="default (30s)"
|
||||
((ELB_PARALLEL++)) || true
|
||||
else
|
||||
elb_interval="custom ($interval)"
|
||||
fi
|
||||
|
||||
if [[ "$timeout" == "5s" || "$timeout" =~ ^5 ]]; then
|
||||
elb_timeout="default (5s)"
|
||||
((ELB_PARALLEL++)) || true
|
||||
else
|
||||
elb_timeout="custom ($timeout)"
|
||||
fi
|
||||
|
||||
if [[ "$retries" == "3" || "$retries" =~ ^3 ]]; then
|
||||
elb_retries="default (3)"
|
||||
((ELB_PARALLEL++)) || true
|
||||
else
|
||||
elb_retries="custom ($retries)"
|
||||
fi
|
||||
|
||||
print_info " $service: ELB parallel (interval: $elb_interval, timeout: $elb_timeout, retries: $elb_retries)"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $ELB_PARALLEL -gt 0 ]]; then
|
||||
print_pass "ELB Health Check parallelism verified"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
print_header "Healthcheck Verification Summary"
|
||||
|
||||
echo -e "Tests run: $((pass_count + fail_count))"
|
||||
echo -e "${GREEN}Passed: $pass_count${NC}"
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "${RED}Failed: $fail_count${NC}"
|
||||
fi
|
||||
|
||||
if [[ $fail_count -eq 0 ]]; then
|
||||
echo -e "\n${GREEN}${BOLD}✓ ALL HEALTHCHECK CHECKS PASSED${NC}"
|
||||
echo -e "\nHealthcheck configuration verified!"
|
||||
exit 0
|
||||
else
|
||||
echo -e "\n${RED}Some healthcheck checks failed${NC}"
|
||||
echo -e "Please ensure all services have healthchecks configured."
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,287 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Test 03: Resource Enforcement Verification
|
||||
# Verifies that resource limits are actually enforced using docker stats
|
||||
# Usage: bash labs/lab-03-compute/tests/03-enforcement-test.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LAB_DIR="$(cd "$TEST_DIR/.." && pwd)"
|
||||
|
||||
# Counter helpers
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
|
||||
# Helper functions
|
||||
print_header() {
|
||||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║${NC} ${BOLD}$1${NC}"
|
||||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
}
|
||||
|
||||
print_test() {
|
||||
echo -e "\n${BLUE}[TEST]${NC} $1"
|
||||
}
|
||||
|
||||
print_pass() {
|
||||
echo -e " ${GREEN}[✓]${NC} $1"
|
||||
inc_pass
|
||||
}
|
||||
|
||||
print_fail() {
|
||||
echo -e " ${RED}[✗]${NC} $1"
|
||||
inc_fail
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e " ${BLUE}[i]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e " ${YELLOW}[!]${NC} $1"
|
||||
}
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
print_info "Cleaning up test containers..."
|
||||
cd "$LAB_DIR"
|
||||
docker compose down -v 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Set trap for cleanup
|
||||
trap cleanup EXIT
|
||||
|
||||
# Main verification
|
||||
print_header "Lab 03 Resource Enforcement Verification"
|
||||
|
||||
cd "$LAB_DIR"
|
||||
|
||||
# Test 1: Verify docker-compose.yml exists and is valid
|
||||
print_test "Verifying docker-compose.yml exists and is valid"
|
||||
if [[ ! -f "docker-compose.yml" ]]; then
|
||||
print_fail "docker-compose.yml not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker compose config &> /dev/null; then
|
||||
print_fail "docker-compose.yml has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
print_pass "docker-compose.yml is valid"
|
||||
|
||||
# Test 2: Start services
|
||||
print_test "Starting Docker Compose services"
|
||||
if docker compose up -d &> /dev/null; then
|
||||
print_pass "Services started successfully"
|
||||
sleep 5 # Give services time to start
|
||||
else
|
||||
print_fail "Failed to start services"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Verify containers are running
|
||||
print_test "Verifying containers are running"
|
||||
RUNNING_CONTAINERS=$(docker compose ps --services --filter "status=running" | wc -l)
|
||||
if [[ $RUNNING_CONTAINERS -ge 1 ]]; then
|
||||
print_pass "Services running: $RUNNING_CONTAINERS containers"
|
||||
docker compose ps
|
||||
else
|
||||
print_fail "Not enough containers running"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 4: Check resource limits are applied
|
||||
print_test "Verifying resource limits are applied to containers"
|
||||
LIMITS_APPLIED=0
|
||||
|
||||
for service in $(docker compose config --services); do
|
||||
container_name="lab03-$service"
|
||||
if docker ps --format '{{.Names}}' | grep -q "$container_name"; then
|
||||
# Get CPU limit (NanoCPUs: 1e9 = 1 CPU core)
|
||||
nano_cpus=$(docker inspect "$container_name" --format '{{.HostConfig.NanoCpus}}' 2>/dev/null || echo "0")
|
||||
mem_limit=$(docker inspect "$container_name" --format '{{.HostConfig.Memory}}' 2>/dev/null || echo "0")
|
||||
|
||||
# Convert NanoCPUs to CPU cores
|
||||
if [[ $nano_cpus -gt 0 ]]; then
|
||||
cpu_cores=$(echo "scale=2; $nano_cpus / 1000000000" | bc 2>/dev/null || echo "N/A")
|
||||
else
|
||||
cpu_cores="N/A"
|
||||
fi
|
||||
|
||||
# Convert memory to GB/MB
|
||||
if [[ $mem_limit -gt 0 ]]; then
|
||||
if [[ $mem_limit -ge 1073741824 ]]; then
|
||||
mem_gb=$(echo "scale=2; $mem_limit / 1073741824" | bc 2>/dev/null || echo "N/A")
|
||||
mem_display="${mem_gb}G"
|
||||
else
|
||||
mem_mb=$(echo "scale=0; $mem_limit / 1048576" | bc 2>/dev/null || echo "N/A")
|
||||
mem_display="${mem_mb}M"
|
||||
fi
|
||||
else
|
||||
mem_display="N/A"
|
||||
fi
|
||||
|
||||
if [[ "$cpu_cores" != "N/A" && "$mem_display" != "N/A" ]]; then
|
||||
print_pass " $container_name: cpus: $cpu_cores, memory: $mem_display"
|
||||
((LIMITS_APPLIED++)) || true
|
||||
else
|
||||
print_fail " $container_name: Could not read limits (cpus: $cpu_cores, memory: $mem_display)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $LIMITS_APPLIED -gt 0 ]]; then
|
||||
print_pass "Resource limits applied to $LIMITS_APPLIED containers"
|
||||
else
|
||||
print_fail "No containers with resource limits found"
|
||||
fi
|
||||
|
||||
# Test 5: Monitor resource usage with docker stats
|
||||
print_test "Monitoring resource usage with docker stats"
|
||||
STATS_OK=0
|
||||
|
||||
# Get initial stats
|
||||
print_info "Current resource usage:"
|
||||
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}" 2>/dev/null || true
|
||||
|
||||
for service in $(docker compose config --services); do
|
||||
container_name="lab03-$service"
|
||||
if docker ps --format '{{.Names}}' | grep -q "$container_name"; then
|
||||
# Get CPU percentage and memory usage
|
||||
cpu_percent=$(docker stats "$container_name" --no-stream --format "{{.CPUPerc}}" 2>/dev/null | sed 's/%//' || echo "N/A")
|
||||
mem_usage=$(docker stats "$container_name" --no-stream --format "{{.MemUsage}}" 2>/dev/null || echo "N/A")
|
||||
|
||||
if [[ "$cpu_percent" != "N/A" && "$mem_usage" != "N/A" ]]; then
|
||||
print_info " $container_name: CPU: ${cpu_percent}%, Memory: $mem_usage"
|
||||
((STATS_OK++)) || true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $STATS_OK -gt 0 ]]; then
|
||||
print_pass "docker stats successfully monitored $STATS_OK containers"
|
||||
else
|
||||
print_fail "Failed to monitor container stats"
|
||||
fi
|
||||
|
||||
# Test 6: Verify health status
|
||||
print_test "Verifying container health status"
|
||||
HEALTHY_COUNT=0
|
||||
|
||||
for service in $(docker compose config --services); do
|
||||
container_name="lab03-$service"
|
||||
if docker ps --format '{{.Names}}' | grep -q "$container_name"; then
|
||||
# Get health status
|
||||
health_status=$(docker inspect "$container_name" --format '{{.State.Health.Status}}' 2>/dev/null || echo "no-healthcheck")
|
||||
|
||||
if [[ "$health_status" == "healthy" ]]; then
|
||||
print_pass " $container_name: $health_status"
|
||||
((HEALTHY_COUNT++)) || true
|
||||
elif [[ "$health_status" == "no-healthcheck" ]]; then
|
||||
print_info " $container_name: no healthcheck configured"
|
||||
else
|
||||
print_info " $container_name: $health_status"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $HEALTHY_COUNT -gt 0 ]]; then
|
||||
print_pass "$HEALTHY_COUNT containers are healthy"
|
||||
else
|
||||
print_warning "No healthy containers (services may still be starting)"
|
||||
fi
|
||||
|
||||
# Test 7: Stress test for resource enforcement (if stress container exists)
|
||||
print_test "Stress testing resource enforcement (if stress container available)"
|
||||
|
||||
STRESS_SERVICE=$(docker compose config --services | grep -E "(stress|test)" || echo "")
|
||||
if [[ -n "$STRESS_SERVICE" ]]; then
|
||||
print_info "Found stress service: $STRESS_SERVICE"
|
||||
|
||||
# Get the container name
|
||||
stress_container="lab03-$STRESS_SERVICE"
|
||||
if docker ps --format '{{.Names}}' | grep -q "$stress_container"; then
|
||||
# Get limits
|
||||
nano_cpus=$(docker inspect "$stress_container" --format '{{.HostConfig.NanoCpus}}' 2>/dev/null || echo "0")
|
||||
mem_limit=$(docker inspect "$stress_container" --format '{{.HostConfig.Memory}}' 2>/dev/null || echo "0")
|
||||
|
||||
cpu_limit_cores=$(echo "scale=2; $nano_cpus / 1000000000" | bc 2>/dev/null || echo "N/A")
|
||||
if [[ $mem_limit -ge 1073741824 ]]; then
|
||||
mem_limit_display=$(echo "scale=2; $mem_limit / 1073741824" | bc 2>/dev/null || echo "N/A")"G"
|
||||
else
|
||||
mem_limit_display=$(echo "scale=0; $mem_limit / 1048576" | bc 2>/dev/null || echo "N/A")"M"
|
||||
fi
|
||||
|
||||
print_info "Limits: cpus: $cpu_limit_cores, memory: $mem_limit_display"
|
||||
|
||||
# Monitor during stress test
|
||||
print_info "Monitoring during stress (10 seconds)..."
|
||||
for i in {1..5}; do
|
||||
cpu_percent=$(docker stats "$stress_container" --no-stream --format "{{.CPUPerc}}" 2>/dev/null | sed 's/%//' || echo "N/A")
|
||||
mem_usage=$(docker stats "$stress_container" --no-stream --format "{{.MemUsage}}" 2>/dev/null || echo "N/A")
|
||||
print_info " Sample $i: CPU: ${cpu_percent}%, Memory: $mem_usage"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
print_pass "Stress test completed"
|
||||
fi
|
||||
else
|
||||
print_info "No stress service found - skipping stress test"
|
||||
fi
|
||||
|
||||
# Test 8: Verify resource limit enforcement
|
||||
print_test "Verifying resource limits are enforced"
|
||||
ENFORCED=0
|
||||
|
||||
for service in $(docker compose config --services); do
|
||||
container_name="lab03-$service"
|
||||
if docker ps --format '{{.Names}}' | grep -q "$container_name"; then
|
||||
# Check if limits are set (not 0 or -1)
|
||||
nano_cpus=$(docker inspect "$container_name" --format '{{.HostConfig.NanoCpus}}' 2>/dev/null || echo "0")
|
||||
mem_limit=$(docker inspect "$container_name" --format '{{.HostConfig.Memory}}' 2>/dev/null || echo "0")
|
||||
|
||||
if [[ $nano_cpus -gt 0 && $mem_limit -gt 0 ]]; then
|
||||
print_pass " $container_name: Limits enforced (CPU and memory)"
|
||||
((ENFORCED++)) || true
|
||||
else
|
||||
print_fail " $container_name: Limits not enforced (CPU: $nano_cpus, Memory: $mem_limit)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $ENFORCED -gt 0 ]]; then
|
||||
print_pass "Resource limits enforced for $ENFORCED containers"
|
||||
else
|
||||
print_fail "Resource limits not enforced for any container"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
print_header "Resource Enforcement Verification Summary"
|
||||
|
||||
echo -e "Tests run: $((pass_count + fail_count))"
|
||||
echo -e "${GREEN}Passed: $pass_count${NC}"
|
||||
if [[ $fail_count -gt 0 ]]; then
|
||||
echo -e "${RED}Failed: $fail_count${NC}"
|
||||
fi
|
||||
|
||||
if [[ $fail_count -eq 0 ]]; then
|
||||
echo -e "\n${GREEN}${BOLD}✓ ALL ENFORCEMENT CHECKS PASSED${NC}"
|
||||
echo -e "\nResource limits are properly enforced!"
|
||||
exit 0
|
||||
else
|
||||
echo -e "\n${RED}Some enforcement checks failed${NC}"
|
||||
echo -e "Please verify resource limit configuration."
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,84 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Infrastructure Verification for Lab 03
|
||||
# Verifies docker-compose.yml is correctly deployed with resource limits and healthchecks
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; BLUE='\033[0;34m'; YELLOW='\033[1;33m'; BOLD='\033[1m'; NC='\033[0m'
|
||||
pass_count=0; fail_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
|
||||
print_header() {
|
||||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║${NC} ${BOLD}$1${NC}"
|
||||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
}
|
||||
|
||||
print_test() { echo -e "\n${BLUE}[TEST]${NC} $1"; }
|
||||
print_pass() { echo -e " ${GREEN}[✓]${NC} $1"; inc_pass; }
|
||||
print_fail() { echo -e " ${RED}[✗]${NC} $1"; inc_fail; }
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
print_header "Lab 03 Infrastructure Verification"
|
||||
|
||||
# File and syntax
|
||||
print_test "Verifying docker-compose.yml exists and valid"
|
||||
[[ -f "docker-compose.yml" ]] && print_pass "docker-compose.yml found" || { print_fail "docker-compose.yml not found"; exit 1; }
|
||||
docker compose config &> /dev/null && print_pass "Syntax valid" || { print_fail "Syntax error"; exit 1; }
|
||||
|
||||
# Services and limits
|
||||
print_test "Checking INF-03 compliance (resource limits)"
|
||||
SERVICES=$(docker compose config --services 2>/dev/null)
|
||||
NON_COMPLIANT=0
|
||||
for s in $SERVICES; do
|
||||
has_cpu=$(docker compose config 2>/dev/null | grep -A30 "^$s:" | grep -c "cpus:" || echo "0")
|
||||
has_mem=$(docker compose config 2>/dev/null | grep -A30 "^$s:" | grep -c "memory:" || echo "0")
|
||||
if [[ $has_cpu -eq 0 || $has_mem -eq 0 ]]; then
|
||||
print_fail " $s: missing limits"
|
||||
((NON_COMPLIANT++)) || true
|
||||
else
|
||||
cpu_val=$(docker compose config 2>/dev/null | grep -A30 "^$s:" | grep "cpus:" | sed 's/.*cpus: //' | tr -d ' "')
|
||||
mem_val=$(docker compose config 2>/dev/null | grep -A30 "^$s:" | grep "memory:" | sed 's/.*memory: //' | tr -d " '""")
|
||||
print_pass " $s: cpus=$cpu_val, memory=$mem_val"
|
||||
fi
|
||||
done
|
||||
[[ $NON_COMPLIANT -eq 0 ]] && print_pass "INF-03 COMPLIANT" || print_fail "INF-03 VIOLATION: $NON_COMPLIANT services"
|
||||
|
||||
# Healthchecks
|
||||
print_test "Verifying healthcheck configuration"
|
||||
MISSING_HC=0
|
||||
for s in $SERVICES; do
|
||||
has_hc=$(docker compose config 2>/dev/null | grep -A50 "^$s:" | grep -c "healthcheck:" || echo "0")
|
||||
[[ $has_hc -gt 0 ]] && print_pass " $s: healthcheck configured" || { print_fail " $s: missing healthcheck"; ((MISSING_HC++)); }
|
||||
done
|
||||
[[ $MISSING_HC -eq 0 ]] && print_pass "All services have healthchecks" || print_fail "$MISSING_HC missing healthchecks"
|
||||
|
||||
# Deploy and verify
|
||||
print_test "Starting services"
|
||||
docker compose up -d &> /dev/null && print_pass "Services started" && sleep 8 || { print_fail "Failed to start"; exit 1; }
|
||||
|
||||
print_test "Checking running containers"
|
||||
RUNNING=$(docker compose ps --services --filter "status=running" | wc -l)
|
||||
[[ $RUNNING -ge 4 ]] && print_pass "$RUNNING containers running" || print_fail "Only $RUNNING containers"
|
||||
|
||||
# Enforcement
|
||||
print_test "Verifying resource limits enforced"
|
||||
ENFORCED=0
|
||||
for s in $SERVICES; do
|
||||
c="lab03-$s"
|
||||
if docker ps --format '{{.Names}}' | grep -q "$c"; then
|
||||
nano_cpus=$(docker inspect "$c" --format '{{.HostConfig.NanoCpus}}' 2>/dev/null || echo "0")
|
||||
mem_bytes=$(docker inspect "$c" --format '{{.HostConfig.Memory}}' 2>/dev/null || echo "0")
|
||||
[[ $nano_cpus -gt 0 && $mem_bytes -gt 0 ]] && print_pass " $c: limits enforced" || print_fail " $c: limits not applied"
|
||||
[[ $nano_cpus -gt 0 && $mem_bytes -gt 0 ]] && ((ENFORCED++)) || true
|
||||
fi
|
||||
done
|
||||
[[ $ENFORCED -gt 0 ]] && print_pass "Limits enforced for $ENFORCED containers"
|
||||
|
||||
# Summary
|
||||
print_header "Summary"
|
||||
echo "Tests: $((pass_count + fail_count)) | ${GREEN}Passed: $pass_count${NC} ${RED}Failed: $fail_count${NC}"
|
||||
[[ $fail_count -eq 0 ]] && { echo -e "\n${GREEN}${BOLD}✓ ALL CHECKS PASSED${NC}\n"; exit 0; } || { echo -e "\n${RED}Some checks failed${NC}\n"; exit 1; }
|
||||
@@ -1,79 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Quick Test - Lab 03: Compute & EC2
|
||||
# Fast validation for development (< 30 seconds)
|
||||
# Usage: bash labs/lab-03-compute/tests/quick-test.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LAB_DIR="$(cd "$TEST_DIR/.." && pwd)"
|
||||
|
||||
# Quick checks (no verbose output)
|
||||
echo -e "${BLUE}Quick Test - Lab 03: Compute & EC2${NC}\n"
|
||||
|
||||
# Check 1: File exists
|
||||
if [[ ! -f "$LAB_DIR/docker-compose.yml" ]]; then
|
||||
echo -e "${RED}✗ docker-compose.yml not found${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✓${NC} docker-compose.yml exists"
|
||||
|
||||
# Check 2: Syntax valid
|
||||
if ! docker compose config &> /dev/null; then
|
||||
echo -e "${RED}✗ docker-compose.yml syntax error${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✓${NC} Syntax valid"
|
||||
|
||||
# Check 3: Services defined
|
||||
SERVICES=$(docker compose config --services 2>/dev/null)
|
||||
SERVICE_COUNT=$(echo "$SERVICES" | wc -l)
|
||||
if [[ $SERVICE_COUNT -lt 3 ]]; then
|
||||
echo -e "${RED}✗ Only $SERVICE_COUNT services (need 3+)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✓${NC} $SERVICE_COUNT services defined"
|
||||
|
||||
# Check 4: Resource limits (INF-03)
|
||||
NON_COMPLIANT=0
|
||||
for service in $SERVICES; do
|
||||
has_cpu=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep -c "cpus:" || echo "0")
|
||||
has_mem=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep -c "memory:" || echo "0")
|
||||
if [[ $has_cpu -eq 0 || $has_mem -eq 0 ]]; then
|
||||
((NON_COMPLIANT++)) || true
|
||||
fi
|
||||
done
|
||||
if [[ $NON_COMPLIANT -gt 0 ]]; then
|
||||
echo -e "${RED}✗ $NON_COMPLIANT services missing resource limits (INF-03)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✓${NC} INF-03 compliant (all services have limits)"
|
||||
|
||||
# Check 5: Healthchecks
|
||||
MISSING_HC=0
|
||||
for service in $SERVICES; do
|
||||
has_hc=$(docker compose config 2>/dev/null | grep -A 50 "^$service:" | grep -c "healthcheck:" || echo "0")
|
||||
if [[ $has_hc -eq 0 ]]; then
|
||||
((MISSING_HC++)) || true
|
||||
fi
|
||||
done
|
||||
if [[ $MISSING_HC -gt 0 ]]; then
|
||||
echo -e "${YELLOW}⚠ $MISSING_HC services missing healthchecks${NC}"
|
||||
else
|
||||
echo -e "${GREEN}✓${NC} All services have healthchecks"
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo -e "\n${GREEN}${BOLD}✓ Quick test PASSED${NC}\n"
|
||||
echo -e "For full verification, run:"
|
||||
echo -e " bash tests/run-all-tests.sh"
|
||||
echo -e " bash tests/99-final-verification.sh"
|
||||
@@ -1,138 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Run All Tests - Lab 03: Compute & EC2
|
||||
# Executes all test scripts in sequence with fail-fast behavior
|
||||
# Usage: bash labs/lab-03-compute/tests/run-all-tests.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Get script directory
|
||||
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LAB_DIR="$(cd "$TEST_DIR/.." && pwd)"
|
||||
|
||||
# Counter helpers
|
||||
total_passed=0
|
||||
total_failed=0
|
||||
tests_run=0
|
||||
|
||||
# Helper functions
|
||||
print_header() {
|
||||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║${NC} ${BOLD}$1${NC}"
|
||||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
}
|
||||
|
||||
print_section() {
|
||||
echo -e "\n${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE} $1${NC}"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}\n"
|
||||
}
|
||||
|
||||
print_pass() {
|
||||
echo -e "${GREEN}✓${NC} $1"
|
||||
}
|
||||
|
||||
print_fail() {
|
||||
echo -e "${RED}✗${NC} $1"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
print_header "Lab 03 Test Suite - Compute & EC2"
|
||||
|
||||
cd "$LAB_DIR"
|
||||
|
||||
echo -e "${BLUE}Running all tests in sequence...${NC}\n"
|
||||
|
||||
# Test 1: Resource Limits Configuration
|
||||
print_section "Test 1/4: Resource Limits Configuration"
|
||||
if bash "$TEST_DIR/01-resource-limits-test.sh"; then
|
||||
print_pass "Resource limits tests PASSED"
|
||||
((total_passed++)) || true
|
||||
else
|
||||
print_fail "Resource limits tests FAILED"
|
||||
((total_failed++)) || true
|
||||
echo -e "\n${YELLOW}Stopping at first failure (fail-fast mode)${NC}"
|
||||
echo -e "Run individual tests to debug:"
|
||||
echo -e " bash tests/01-resource-limits-test.sh"
|
||||
exit 1
|
||||
fi
|
||||
((tests_run++)) || true
|
||||
|
||||
# Test 2: Healthcheck Configuration
|
||||
print_section "Test 2/4: Healthcheck Configuration"
|
||||
if bash "$TEST_DIR/02-healthcheck-test.sh"; then
|
||||
print_pass "Healthcheck tests PASSED"
|
||||
((total_passed++)) || true
|
||||
else
|
||||
print_fail "Healthcheck tests FAILED"
|
||||
((total_failed++)) || true
|
||||
echo -e "\n${YELLOW}Stopping at first failure (fail-fast mode)${NC}"
|
||||
echo -e "Run individual tests to debug:"
|
||||
echo -e " bash tests/02-healthcheck-test.sh"
|
||||
exit 1
|
||||
fi
|
||||
((tests_run++)) || true
|
||||
|
||||
# Test 3: Resource Enforcement
|
||||
print_section "Test 3/4: Resource Enforcement Verification"
|
||||
if bash "$TEST_DIR/03-enforcement-test.sh"; then
|
||||
print_pass "Resource enforcement tests PASSED"
|
||||
((total_passed++)) || true
|
||||
else
|
||||
print_fail "Resource enforcement tests FAILED"
|
||||
((total_failed++)) || true
|
||||
echo -e "\n${YELLOW}Stopping at first failure (fail-fast mode)${NC}"
|
||||
echo -e "Run individual tests to debug:"
|
||||
echo -e " bash tests/03-enforcement-test.sh"
|
||||
exit 1
|
||||
fi
|
||||
((tests_run++)) || true
|
||||
|
||||
# Test 4: Final Verification
|
||||
print_section "Test 4/4: Final Verification"
|
||||
if bash "$TEST_DIR/99-final-verification.sh"; then
|
||||
print_pass "Final verification PASSED"
|
||||
((total_passed++)) || true
|
||||
else
|
||||
print_fail "Final verification FAILED"
|
||||
((total_failed++)) || true
|
||||
echo -e "\n${YELLOW}Stopping at first failure (fail-fast mode)${NC}"
|
||||
echo -e "Run individual tests to debug:"
|
||||
echo -e " bash tests/99-final-verification.sh"
|
||||
exit 1
|
||||
fi
|
||||
((tests_run++)) || true
|
||||
|
||||
# Summary
|
||||
print_header "Test Suite Summary"
|
||||
|
||||
echo -e "Tests run: $tests_run"
|
||||
echo -e "${GREEN}Passed: $total_passed${NC}"
|
||||
if [[ $total_failed -gt 0 ]]; then
|
||||
echo -e "${RED}Failed: $total_failed${NC}"
|
||||
fi
|
||||
|
||||
if [[ $total_failed -eq 0 ]]; then
|
||||
echo -e "\n${GREEN}${BOLD}✓✓✓ ALL TESTS PASSED ✓✓✓${NC}\n"
|
||||
echo -e "Your Lab 03 infrastructure is ready!"
|
||||
echo -e "Proceed with the tutorials to learn more about:"
|
||||
echo -e " • EC2 instance type parallels"
|
||||
echo -e " • Resource limits enforcement"
|
||||
echo -e " • Healthcheck implementation"
|
||||
exit 0
|
||||
else
|
||||
echo -e "\n${RED}Some tests failed${NC}\n"
|
||||
echo -e "Run individual tests for details:"
|
||||
echo -e " bash tests/01-resource-limits-test.sh"
|
||||
echo -e " bash tests/02-healthcheck-test.sh"
|
||||
echo -e " bash tests/03-enforcement-test.sh"
|
||||
echo -e " bash tests/99-final-verification.sh"
|
||||
exit 1
|
||||
fi
|
||||
@@ -274,11 +274,7 @@ done
|
||||
|
||||
### Controllo INF-03
|
||||
|
||||
Lo script di verifica del lab controllerà automaticamente che tutti i servizi abbiano i limiti configurati (requisito **INF-03**).
|
||||
|
||||
```bash
|
||||
bash tests/01-resource-limits-test.sh
|
||||
```
|
||||
La verifica finale del lab controllerà automaticamente che tutti i servizi abbiano i limiti configurati (requisito **INF-03**).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -404,7 +404,7 @@ Hai completato i tutorial di Lab 03 - Compute & EC2!
|
||||
- Gestire dipendenze tra servizi (ECS task definitions)
|
||||
|
||||
**Prossimi Passi:**
|
||||
- Esegui i test di verifica: `bash tests/run-all-tests.sh`
|
||||
- Esegui la verifica finale: `bash tests/99-final-verification.sh`
|
||||
- Esplora le guide How-to per procedure specifiche
|
||||
- Consulta i documenti Reference per sintassi completa
|
||||
- Leggi Explanation per approfondire i parallelismi cloud
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,151 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,198 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,177 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,111 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,93 +0,0 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user