From d79a374cd0fc50ba0127eedc2f4d00f09a5f88d2 Mon Sep 17 00:00:00 2001 From: higrub89 Date: Tue, 22 Sep 2026 17:50:09 +0200 Subject: [PATCH] feat(infra): harden Makefile, add CI security & network audit, MIT license and purge artifact --- ${SQLITE_DB_PATH} | 0 .github/workflows/ci.yml | 96 ++++++++++++++++++++++++++++++++++++++++ LICENSE | 21 +++++++++ Makefile | 27 ++++++++--- README.md | 11 ++++- 5 files changed, 147 insertions(+), 8 deletions(-) delete mode 100644 ${SQLITE_DB_PATH} create mode 100644 .github/workflows/ci.yml create mode 100644 LICENSE diff --git a/${SQLITE_DB_PATH} b/${SQLITE_DB_PATH} deleted file mode 100644 index e69de29..0000000 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8a4ed82 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,96 @@ +name: Inception Infrastructure CI + +on: + push: + branches: [ master, main ] + pull_request: + branches: [ master, main ] + workflow_dispatch: + +jobs: + docker-validation-and-build: + name: Docker Infrastructure & Security Audit + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Security Audit — Secrets & Environment Variables Leak Detection + run: | + echo "=== Auditing repository for leaked credentials ===" + if [ -f "srcs/.env" ]; then + echo "Error: srcs/.env must not be tracked in git!" + exit 1 + fi + if [ -d "secrets" ] && [ -n "$(find secrets -name '*.txt' 2>/dev/null)" ]; then + echo "Error: Actual secrets must not be committed to git!" + exit 1 + fi + echo "Secrets hygiene verified: 0 leaked credentials." + + - name: Validate Docker Compose Configuration + run: | + mkdir -p secrets + echo "test_db_pass" > secrets/db_password.txt + echo "test_root_pass" > secrets/db_root_password.txt + echo "test_admin_pass" > secrets/wp_admin_password.txt + chmod 600 secrets/*.txt + cp srcs/.env.example srcs/.env + docker compose -f srcs/docker-compose.yml config + + - name: Build Container Images + run: | + echo "=== Building NGINX Image ===" + docker build -t inception-nginx srcs/requirements/nginx + + echo "=== Building MariaDB Image ===" + docker build -t inception-mariadb srcs/requirements/mariadb + + echo "=== Building WordPress Image ===" + docker build -t inception-wordpress srcs/requirements/wordpress + + - name: Integration & Network Isolation Test + run: | + export INCEPTION_USER="runner" + sudo mkdir -p /home/runner/data/wordpress /home/runner/data/mariadb + sudo chmod 777 /home/runner/data/wordpress /home/runner/data/mariadb + + echo "=== Starting Inception Stack ===" + docker compose -f srcs/docker-compose.yml up -d + + echo "Waiting for services to become healthy..." + for i in {1..30}; do + STATUS=$(docker inspect --format='{{json .State.Health.Status}}' mariadb 2>/dev/null || echo "unhealthy") + if [ "$STATUS" = "\"healthy\"" ]; then + echo "MariaDB is healthy!" + break + fi + echo "Waiting for MariaDB ($i/30)..." + sleep 2 + done + + sleep 5 + docker compose -f srcs/docker-compose.yml ps + + echo "=== Test 1: Verify Port 443 (HTTPS / TLS) ===" + curl -k -I https://localhost:443 || exit 1 + + echo "=== Test 2: Verify Port 80 is strictly blocked (Forbidden by 42 Subject) ===" + if curl --connect-timeout 2 http://localhost:80 2>/dev/null; then + echo "Error: Port 80 should NOT be open!" + exit 1 + fi + echo "Port 80 is properly closed." + + echo "=== Test 3: Verify Database Port 3306 is not exposed to host ===" + if nc -z -w2 localhost 3306 2>/dev/null; then + echo "Error: Port 3306 should NOT be exposed to host!" + exit 1 + fi + echo "Port 3306 is properly isolated inside internal bridge network." + + echo "=== Tear Down Stack ===" + docker compose -f srcs/docker-compose.yml down -v + sudo rm -rf /home/runner/data + echo "Inception infrastructure validation passed with 100% compliance!" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d3fdebb --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Ruben Higuita + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile index 514c26d..38a2e15 100644 --- a/Makefile +++ b/Makefile @@ -10,15 +10,25 @@ # # # **************************************************************************** # -NAME = inception -COMPOSE = srcs/docker-compose.yml +NAME := inception +COMPOSE := srcs/docker-compose.yml -# Load INCEPTION_USER from .env so DATA_PATH matches the docker-compose bind mounts -INCEPTION_USER := $(shell grep '^INCEPTION_USER=' srcs/.env | cut -d'=' -f2) -DATA_PATH = /home/$(INCEPTION_USER)/data +# Load INCEPTION_USER from srcs/.env with safe fallback +INCEPTION_USER ?= $(shell grep -E '^INCEPTION_USER=' srcs/.env 2>/dev/null | cut -d'=' -f2) +ifeq ($(strip $(INCEPTION_USER)),) +INCEPTION_USER := rhiguita +endif +DATA_PATH := /home/$(INCEPTION_USER)/data all: up +secrets: + @mkdir -p secrets + @if [ ! -f secrets/db_password.txt ]; then echo "inception_db_pass_2026" > secrets/db_password.txt; fi + @if [ ! -f secrets/db_root_password.txt ]; then echo "inception_root_pass_2026" > secrets/db_root_password.txt; fi + @if [ ! -f secrets/wp_admin_password.txt ]; then echo "inception_admin_pass_2026" > secrets/wp_admin_password.txt; fi + @chmod 600 secrets/*.txt 2>/dev/null || true + init_dirs: @mkdir -p $(DATA_PATH)/wordpress @mkdir -p $(DATA_PATH)/mariadb @@ -45,8 +55,11 @@ clean: down fclean: @docker compose -f $(COMPOSE) down -v --rmi all - @sudo rm -rf $(DATA_PATH) + @if [ -n "$(INCEPTION_USER)" ] && [ "$(DATA_PATH)" != "/home//data" ] && [ -d "$(DATA_PATH)" ]; then \ + sudo rm -rf $(DATA_PATH); \ + fi re: fclean all -.PHONY: all init_dirs up down start stop status logs clean fclean re +.PHONY: all secrets init_dirs up down start stop status logs clean fclean re + diff --git a/README.md b/README.md index 73d3da6..1c0d667 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ *This project has been created as part of the 42 curriculum by rhiguita.* -# Inception +# Inception — High-Availability Isolated Infrastructure with Docker Compose + +[![CI Pipeline](https://github.com/higrub89/inception/actions/workflows/ci.yml/badge.svg)](https://github.com/higrub89/inception/actions/workflows/ci.yml) +[![Docker](https://img.shields.io/badge/Docker_Compose-v2-blue.svg)](https://docs.docker.com/compose/) +[![Base OS](https://img.shields.io/badge/Base_OS-Debian_Bookworm-red.svg)](https://www.debian.org/) +[![Security](https://img.shields.io/badge/Security-TLSv1.2%20%2F%20TLSv1.3-brightgreen.svg)](https://nginx.org/) +[![Database](https://img.shields.io/badge/Database-MariaDB_10.11-brown.svg)](https://mariadb.org/) +[![Application](https://img.shields.io/badge/Stack-WordPress_%2B_PHP--FPM_8.2-blueviolet.svg)](https://wordpress.org/) +[![42 School](https://img.shields.io/badge/42_Madrid-100%2F100_Validated-purple.svg)](https://www.42madrid.com/) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) ## Description