diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3a78c49..0000000 --- a/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: python -python: - - "2.7" -install: "pip install -r app/requirements.txt" -script: - - python app/test.py diff --git a/Dockerfile b/Dockerfile index de88ab3..ac1519d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,15 +22,17 @@ COPY supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf COPY app /var/www/app -RUN mkdir -p /var/log/nginx/app /var/log/supervisor \ +RUN mkdir -p /var/log/nginx/app /var/log/supervisor /tmp/nginx /var/lib/nginx /var/cache/nginx \ && rm /etc/nginx/sites-enabled/default \ && ln -s /etc/nginx/sites-available/flask.conf /etc/nginx/sites-enabled/flask.conf \ && echo "daemon off;" >> /etc/nginx/nginx.conf \ - && sed -i 's|pid /run/nginx.pid;|pid /var/run/nginx.pid;|' /etc/nginx/nginx.conf \ + && sed -i 's|pid /run/nginx.pid;|pid /tmp/nginx/nginx.pid;|' /etc/nginx/nginx.conf \ && uv pip install --system --no-cache --break-system-packages -r /var/www/app/requirements.txt \ && chown -R appuser:appuser /var/www/app \ && chown -R appuser:appuser /var/log \ - && chown -R appuser:appuser /var/run + && chown -R appuser:appuser /tmp/nginx \ + && chown -R appuser:appuser /var/lib/nginx \ + && chown -R appuser:appuser /var/cache/nginx EXPOSE 8080 diff --git a/Makefile b/Makefile index eaf3192..ead3ea7 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,15 @@ # Docker Flask Application Makefile -# Variables IMAGE_NAME = docker-flask CONTAINER_NAME = flask-app -COMPOSE_FILE = docker-compose.yml PORT = 8080 -# Security Configuration -# Set to 'true' to enable security scanning and /security endpoint -# Set to 'false' to disable security features for faster deployment -ENABLE_SECURITY ?= true - -# Default target .DEFAULT_GOAL := help +# Quickstart +.PHONY: run +run: clean build ## Build and run standalone container + docker run -d --name $(CONTAINER_NAME) -p $(PORT):8080 $(IMAGE_NAME) + # Build targets .PHONY: build build: ## Build Docker image @@ -23,80 +20,38 @@ build-no-cache: ## Build Docker image without cache docker build --no-cache -t $(IMAGE_NAME) . # Run targets -.PHONY: run -run: rm ## Build and run container (with optional security scanning) -ifeq ($(ENABLE_SECURITY),true) - @echo "Starting deployment with security scanning enabled..." - $(MAKE) trivy-pull build scan-json - @echo "Starting container with security reports..." - docker run -d --name $(CONTAINER_NAME) -p $(PORT):8080 $(IMAGE_NAME) - @echo "Updating security reports in running container..." - @sleep 3 - $(MAKE) update-security-reports - @echo "Generating markdown security report..." - $(MAKE) scan-markdown - @echo "Container started successfully with latest security reports!" - @echo "Access application: http://localhost:8080" - @echo "Security dashboard: http://localhost:8080/security" - @echo "Markdown report: reports/security-report.md" -else - @echo "Starting deployment without security scanning..." - $(MAKE) build - @echo "Starting container..." - docker run -d --name $(CONTAINER_NAME) -p $(PORT):8080 $(IMAGE_NAME) - @echo "Generating markdown security report..." - $(MAKE) scan-markdown - @echo "Container started successfully!" - @echo "Access application: http://localhost:8080" - @echo "Note: Security scanning disabled. Set ENABLE_SECURITY=true to enable." - @echo "Markdown report: reports/security-report.md" -endif - -.PHONY: run-secure -run-secure: rm ## Build and run container with security scanning (always enabled) - @echo "Starting secure deployment with security scanning..." - $(MAKE) trivy-pull build scan-json - @echo "Starting container with security reports..." - docker run -d --name $(CONTAINER_NAME) -p $(PORT):8080 $(IMAGE_NAME) - @echo "Updating security reports in running container..." - @sleep 3 - $(MAKE) update-security-reports - @echo "Container started successfully with latest security reports!" - @echo "Access application: http://localhost:8080" - @echo "Security dashboard: http://localhost:8080/security" - -.PHONY: run-basic -run-basic: rm ## Build and run container without security scanning (fast deployment) - @echo "Starting basic deployment without security scanning..." - $(MAKE) build - @echo "Starting container..." - docker run -d --name $(CONTAINER_NAME) -p $(PORT):8080 $(IMAGE_NAME) - @echo "Container started successfully!" - @echo "Access application: http://localhost:8080" - -.PHONY: run-fg -run-fg: ## Run container in foreground - docker run --rm --name $(CONTAINER_NAME) -p $(PORT):8080 $(IMAGE_NAME) - .PHONY: up up: ## Start services using docker-compose - docker-compose -f $(COMPOSE_FILE) up -d + docker-compose up -d .PHONY: up-build -up-build: ## Start services and rebuild if needed - docker-compose -f $(COMPOSE_FILE) up -d --build +up-build: ## Start services and rebuild + docker-compose up -d --build .PHONY: down down: ## Stop and remove containers - docker-compose -f $(COMPOSE_FILE) down + docker-compose down -# Development targets .PHONY: dev dev: ## Start development environment - docker-compose -f $(COMPOSE_FILE) up --build + docker-compose up --build +# Testing targets +.PHONY: test +test: ## Run tests inside container + docker run --rm $(IMAGE_NAME) python3 /var/www/app/test.py + +.PHONY: test-compose +test-compose: ## Run tests using docker-compose + docker-compose exec nginx python3 /var/www/app/test.py + +.PHONY: test-local +test-local: ## Run tests locally + cd app && python3 test.py + +# Development tools .PHONY: shell -shell: ## Access running container shell +shell: ## Access container shell docker exec -it $(CONTAINER_NAME) /bin/bash .PHONY: logs @@ -105,231 +60,44 @@ logs: ## Show container logs .PHONY: logs-compose logs-compose: ## Show docker-compose logs - docker-compose -f $(COMPOSE_FILE) logs -f - -# Testing targets -.PHONY: test -test: ## Run tests inside container - docker run --rm $(IMAGE_NAME) python3 -m pytest /var/www/app/test.py - -.PHONY: test-local -test-local: ## Run tests locally (requires Python 3) - cd app && python3 test.py + docker-compose logs -f -.PHONY: lint -lint: ## Run linting inside container - docker run --rm $(IMAGE_NAME) python3 -m flake8 /var/www/app/ - -# Health and status targets -.PHONY: health -health: ## Check container health status - docker inspect --format='{{.State.Health.Status}}' $(CONTAINER_NAME) - -.PHONY: status -status: ## Show container status - docker ps -f name=$(CONTAINER_NAME) +# Security scanning +.PHONY: scan +scan: build ## Scan image for vulnerabilities + @mkdir -p reports + docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + -v $(PWD):/workspace aquasec/trivy:latest image \ + --format table $(IMAGE_NAME) -.PHONY: inspect -inspect: ## Inspect container details - docker inspect $(CONTAINER_NAME) +.PHONY: scan-json +scan-json: build ## Generate JSON security reports + @mkdir -p reports + docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + -v $(PWD):/workspace aquasec/trivy:latest image \ + --format json --output /workspace/reports/image-scan.json $(IMAGE_NAME) # Cleanup targets .PHONY: stop -stop: ## Stop running container +stop: ## Stop container docker stop $(CONTAINER_NAME) || true -.PHONY: rm -rm: stop ## Remove container - docker rm $(CONTAINER_NAME) || true - .PHONY: clean -clean: rm ## Clean up containers and images +clean: stop ## Remove container and image + docker rm $(CONTAINER_NAME) || true docker rmi $(IMAGE_NAME) || true .PHONY: clean-all -clean-all: ## Remove all unused containers, networks, images +clean-all: ## Remove all unused containers and images docker system prune -af -.PHONY: clean-volumes -clean-volumes: ## Remove all unused volumes - docker volume prune -f - -# Maintenance targets -.PHONY: pull -pull: ## Pull latest base image - docker pull debian:bookworm-slim - -.PHONY: size -size: ## Show image size - docker images $(IMAGE_NAME) - -.PHONY: history -history: ## Show image build history - docker history $(IMAGE_NAME) - -# Security targets with Trivy -.PHONY: trivy-pull -trivy-pull: ## Pull latest Trivy Docker image - @echo "Pulling latest Trivy Docker image..." - docker pull aquasec/trivy:latest - -.PHONY: trivy-install -trivy-install: trivy-pull ## Pull Trivy Docker image (replaces host installation) - @echo "Trivy Docker image ready for use" - -.PHONY: scan-image -scan-image: ## Scan Docker image for vulnerabilities with Trivy - @echo "Scanning Docker image $(IMAGE_NAME) for vulnerabilities..." - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ - -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest image \ - --exit-code 0 --severity HIGH,CRITICAL --format table $(IMAGE_NAME) - -.PHONY: scan-dockerfile -scan-dockerfile: ## Scan Dockerfile for misconfigurations - @echo "Scanning Dockerfile for misconfigurations..." - docker run --rm -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest config \ - --exit-code 0 --severity HIGH,CRITICAL --format table /workspace - -.PHONY: scan-fs -scan-fs: ## Scan filesystem/source code for vulnerabilities - @echo "Scanning filesystem for vulnerabilities and secrets..." - docker run --rm -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest fs \ - --exit-code 0 --severity HIGH,CRITICAL --scanners vuln,secret,misconfig --format table /workspace - -.PHONY: scan-python -scan-python: ## Scan Python dependencies for vulnerabilities - @echo "Scanning Python dependencies..." - docker run --rm -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest fs \ - --exit-code 0 --severity HIGH,CRITICAL --scanners vuln --format table /workspace/app/ - -.PHONY: scan-all -scan-all: scan-dockerfile scan-fs scan-python build scan-image ## Run all security scans - @echo "All security scans completed!" - -.PHONY: scan-json -scan-json: ## Generate JSON security reports - @mkdir -p reports - @echo "Generating JSON security reports..." - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ - -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest image \ - --exit-code 0 --format json --output /workspace/reports/image-scan.json $(IMAGE_NAME) || true - docker run --rm -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest config \ - --exit-code 0 --format json --output /workspace/reports/dockerfile-scan.json /workspace || true - docker run --rm -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest fs \ - --exit-code 0 --scanners vuln,secret,misconfig --format json --output /workspace/reports/fs-scan.json /workspace || true - @echo "Reports generated in reports/ directory" - -.PHONY: scan-markdown -scan-markdown: ## Generate markdown security report (always runs regardless of ENABLE_SECURITY) - @mkdir -p reports - @echo "Generating formatted markdown security report..." - $(MAKE) trivy-pull - @echo "# Security Report" > reports/security-report.md - @echo "" >> reports/security-report.md - @echo "## Overview" >> reports/security-report.md - @echo "" >> reports/security-report.md - @echo "- **Image**: $(IMAGE_NAME)" >> reports/security-report.md - @echo "- **Generated**: $$(date)" >> reports/security-report.md - @echo "- **Scanner**: Trivy (dockerized)" >> reports/security-report.md - @echo "" >> reports/security-report.md - @echo "---" >> reports/security-report.md - @echo "" >> reports/security-report.md - @echo "## 🐳 Docker Image Vulnerabilities" >> reports/security-report.md - @echo "" >> reports/security-report.md - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ - -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest image \ - --exit-code 0 --format table $(IMAGE_NAME) >> reports/security-report.md || true - @echo "" >> reports/security-report.md - @echo "---" >> reports/security-report.md - @echo "" >> reports/security-report.md - @echo "## 📋 Dockerfile Security Analysis" >> reports/security-report.md - @echo "" >> reports/security-report.md - docker run --rm -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest config \ - --exit-code 0 --format table /workspace >> reports/security-report.md || true - @echo "" >> reports/security-report.md - @echo "---" >> reports/security-report.md - @echo "" >> reports/security-report.md - @echo "## 📁 Filesystem Security Analysis" >> reports/security-report.md - @echo "" >> reports/security-report.md - docker run --rm -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest fs \ - --exit-code 0 --scanners vuln,secret,misconfig --format table /workspace >> reports/security-report.md || true - @echo "" >> reports/security-report.md - @echo "---" >> reports/security-report.md - @echo "" >> reports/security-report.md - @echo "## Summary" >> reports/security-report.md - @echo "" >> reports/security-report.md - @echo "This report was automatically generated as part of the security-first deployment workflow." >> reports/security-report.md - @echo "The container now runs as non-root user (appuser) on port 8080 for enhanced security." >> reports/security-report.md - @echo "" >> reports/security-report.md - @echo "> Generated with [Trivy](https://trivy.dev/) security scanner" >> reports/security-report.md - @echo "Formatted markdown security report generated: reports/security-report.md" - -.PHONY: update-security-reports -update-security-reports: scan-json ## Update security reports in running container - @echo "Copying security reports to running container..." - docker exec $(CONTAINER_NAME) mkdir -p /var/www/app/reports || true - docker cp reports/. $(CONTAINER_NAME):/var/www/app/reports/ || true - @echo "Security reports updated in container" - -.PHONY: scan-ci -scan-ci: ## CI-friendly scan with exit codes for failures - @echo "Running CI security scans..." - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ - -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest image \ - --exit-code 1 --severity HIGH,CRITICAL --quiet $(IMAGE_NAME) - docker run --rm -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest config \ - --exit-code 1 --severity HIGH,CRITICAL --quiet /workspace - docker run --rm -v $(PWD):/workspace \ - -v trivy-cache:/root/.cache \ - aquasec/trivy:latest fs \ - --exit-code 1 --severity HIGH,CRITICAL --scanners vuln,secret,misconfig --quiet /workspace - -.PHONY: scan -scan: ## Scan image for vulnerabilities (legacy compatibility) - $(MAKE) scan-image - -.PHONY: security-check -security-check: ## Run comprehensive security checks - @echo "Running comprehensive security checks..." - $(MAKE) scan-all - @echo "Checking for running processes..." - docker run --rm $(IMAGE_NAME) ps aux || true - @echo "Checking file permissions..." - docker run --rm $(IMAGE_NAME) ls -la /var/www/app/ || true - -# Quick commands +# Utility targets .PHONY: restart restart: stop run ## Restart container -.PHONY: rebuild -rebuild: clean build run ## Rebuild and run container - -.PHONY: fresh -fresh: clean pull build run ## Fresh build with latest base image +.PHONY: status +status: ## Show container status + docker ps -f name=$(CONTAINER_NAME) # Help target .PHONY: help @@ -340,18 +108,6 @@ help: ## Show this help message awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' @echo "" @echo "Variables:" - @echo " IMAGE_NAME = $(IMAGE_NAME)" - @echo " CONTAINER_NAME = $(CONTAINER_NAME)" - @echo " PORT = $(PORT)" - @echo " ENABLE_SECURITY = $(ENABLE_SECURITY)" - @echo "" - @echo "Quick Start:" - @echo " make run # Run (security: $(ENABLE_SECURITY))" - @echo " make run-basic # Run without security" - @echo " make run-secure # Run with security" - @echo " make logs # View logs" - @echo " make stop # Stop container" - @echo "" - @echo "Security Control:" - @echo " Edit ENABLE_SECURITY in Makefile (currently: $(ENABLE_SECURITY))" - @echo " Or: make ENABLE_SECURITY=true run" \ No newline at end of file + @echo " IMAGE_NAME = $(IMAGE_NAME)" + @echo " CONTAINER_NAME = $(CONTAINER_NAME)" + @echo " PORT = $(PORT)" \ No newline at end of file diff --git a/README.md b/README.md index c02f11e..eb419d2 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ Agentic AI Top 10 Overview - - A modern Flask web application containerized with Docker, featuring automated security scanning and comprehensive monitoring capabilities. ## Overview diff --git a/app/test.py b/app/test.py index 4a88eba..6d67ea4 100644 --- a/app/test.py +++ b/app/test.py @@ -2,7 +2,6 @@ from app import app - class TestPost(unittest.TestCase): def test_post(self):