feat: add complete Docker setup for testing
- Update docker-compose.yml with frontend service and healthchecks - Add frontend Dockerfile with dev and production stages - Add nginx.conf for production frontend serving - Add docker-compose.prod.yml for production deployment - Add .env.example with all configuration options - Add init scripts (init.sh, init.ps1) for easy setup
This commit is contained in:
24
.env.example
Normal file
24
.env.example
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Aegis Environment Variables
|
||||||
|
# =============================================================================
|
||||||
|
# Copy this file to .env and fill in the values
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# ── Database ─────────────────────────────────────────────────────────────────
|
||||||
|
DB_USER=postgres
|
||||||
|
DB_PASSWORD=change-me-in-production
|
||||||
|
DB_NAME=attackdb
|
||||||
|
|
||||||
|
# ── Security ─────────────────────────────────────────────────────────────────
|
||||||
|
# IMPORTANT: Generate a strong random key for production
|
||||||
|
# Example: openssl rand -hex 32
|
||||||
|
SECRET_KEY=change-me-in-production-use-a-long-random-string
|
||||||
|
TOKEN_EXPIRE_MINUTES=60
|
||||||
|
|
||||||
|
# ── MinIO Object Storage ─────────────────────────────────────────────────────
|
||||||
|
MINIO_ACCESS_KEY=minioadmin
|
||||||
|
MINIO_SECRET_KEY=change-me-in-production
|
||||||
|
MINIO_BUCKET=evidence
|
||||||
|
|
||||||
|
# ── Frontend ─────────────────────────────────────────────────────────────────
|
||||||
|
FRONTEND_PORT=80
|
||||||
106
docker-compose.prod.yml
Normal file
106
docker-compose.prod.yml
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Aegis - Production Docker Compose
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# docker-compose -f docker-compose.prod.yml up -d --build
|
||||||
|
#
|
||||||
|
# Note: Set environment variables in .env file or via environment
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
services:
|
||||||
|
# ── PostgreSQL Database ────────────────────────────────────────────────────
|
||||||
|
postgres:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
container_name: aegis-postgres
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${DB_USER:-postgres}
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
|
||||||
|
POSTGRES_DB: ${DB_NAME:-attackdb}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-attackdb}"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- aegis-network
|
||||||
|
|
||||||
|
# ── MinIO Object Storage ───────────────────────────────────────────────────
|
||||||
|
minio:
|
||||||
|
image: minio/minio:latest
|
||||||
|
container_name: aegis-minio
|
||||||
|
command: server /data --console-address ":9001"
|
||||||
|
environment:
|
||||||
|
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin}
|
||||||
|
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin}
|
||||||
|
volumes:
|
||||||
|
- minio_data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mc", "ready", "local"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- aegis-network
|
||||||
|
|
||||||
|
# ── FastAPI Backend ────────────────────────────────────────────────────────
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ./backend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: aegis-backend
|
||||||
|
environment:
|
||||||
|
DATABASE_URL: postgresql://${DB_USER:-postgres}:${DB_PASSWORD:-postgres}@postgres:5432/${DB_NAME:-attackdb}
|
||||||
|
SECRET_KEY: ${SECRET_KEY:?Set SECRET_KEY in environment}
|
||||||
|
ALGORITHM: HS256
|
||||||
|
ACCESS_TOKEN_EXPIRE_MINUTES: ${TOKEN_EXPIRE_MINUTES:-60}
|
||||||
|
MINIO_ENDPOINT: minio:9000
|
||||||
|
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
|
||||||
|
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
|
||||||
|
MINIO_BUCKET: ${MINIO_BUCKET:-evidence}
|
||||||
|
MINIO_SECURE: "false"
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
minio:
|
||||||
|
condition: service_started
|
||||||
|
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- aegis-network
|
||||||
|
|
||||||
|
# ── React Frontend (Production with Nginx) ─────────────────────────────────
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
target: production
|
||||||
|
container_name: aegis-frontend
|
||||||
|
ports:
|
||||||
|
- "${FRONTEND_PORT:-80}:80"
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- aegis-network
|
||||||
|
|
||||||
|
# ── Networks ─────────────────────────────────────────────────────────────────
|
||||||
|
networks:
|
||||||
|
aegis-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
# ── Volumes ──────────────────────────────────────────────────────────────────
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
name: aegis_postgres_data_prod
|
||||||
|
minio_data:
|
||||||
|
name: aegis_minio_data_prod
|
||||||
@@ -1,6 +1,26 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Aegis - MITRE ATT&CK Coverage Platform
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# Quick Start:
|
||||||
|
# docker-compose up -d
|
||||||
|
# docker-compose exec backend alembic upgrade head
|
||||||
|
# docker-compose exec backend python -m app.seed
|
||||||
|
#
|
||||||
|
# Access:
|
||||||
|
# - Frontend: http://localhost:5173
|
||||||
|
# - Backend API: http://localhost:8000
|
||||||
|
# - Swagger UI: http://localhost:8000/docs
|
||||||
|
# - MinIO Console: http://localhost:9001 (minioadmin/minioadmin)
|
||||||
|
#
|
||||||
|
# Default credentials: admin / admin123
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
# ── PostgreSQL Database ────────────────────────────────────────────────────
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:15
|
image: postgres:15-alpine
|
||||||
|
container_name: aegis-postgres
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
@@ -9,32 +29,91 @@ services:
|
|||||||
- "5433:5432"
|
- "5433:5432"
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U postgres -d attackdb"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ── MinIO Object Storage ───────────────────────────────────────────────────
|
||||||
minio:
|
minio:
|
||||||
image: minio/minio
|
image: minio/minio:latest
|
||||||
|
container_name: aegis-minio
|
||||||
command: server /data --console-address ":9001"
|
command: server /data --console-address ":9001"
|
||||||
environment:
|
environment:
|
||||||
MINIO_ROOT_USER: minioadmin
|
MINIO_ROOT_USER: minioadmin
|
||||||
MINIO_ROOT_PASSWORD: minioadmin
|
MINIO_ROOT_PASSWORD: minioadmin
|
||||||
ports:
|
ports:
|
||||||
- "9000:9000"
|
- "9000:9000" # API
|
||||||
- "9001:9001"
|
- "9001:9001" # Console
|
||||||
volumes:
|
volumes:
|
||||||
- minio_data:/data
|
- minio_data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mc", "ready", "local"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ── FastAPI Backend ────────────────────────────────────────────────────────
|
||||||
backend:
|
backend:
|
||||||
build: ./backend
|
build:
|
||||||
|
context: ./backend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: aegis-backend
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
environment:
|
environment:
|
||||||
|
# Database
|
||||||
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/attackdb
|
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/attackdb
|
||||||
|
# Security (change in production!)
|
||||||
|
SECRET_KEY: change-me-in-production-use-a-long-random-string
|
||||||
|
ALGORITHM: HS256
|
||||||
|
ACCESS_TOKEN_EXPIRE_MINUTES: 60
|
||||||
|
# MinIO
|
||||||
|
MINIO_ENDPOINT: minio:9000
|
||||||
|
MINIO_ACCESS_KEY: minioadmin
|
||||||
|
MINIO_SECRET_KEY: minioadmin
|
||||||
|
MINIO_BUCKET: evidence
|
||||||
|
MINIO_SECURE: "false"
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
postgres:
|
||||||
- minio
|
condition: service_healthy
|
||||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
minio:
|
||||||
|
condition: service_started
|
||||||
volumes:
|
volumes:
|
||||||
- ./backend:/app
|
- ./backend:/app
|
||||||
|
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ── React Frontend (Development) ───────────────────────────────────────────
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
target: development
|
||||||
|
container_name: aegis-frontend
|
||||||
|
ports:
|
||||||
|
- "5173:5173"
|
||||||
|
environment:
|
||||||
|
# Vite environment variables
|
||||||
|
VITE_API_URL: http://localhost:8000/api/v1
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
volumes:
|
||||||
|
- ./frontend:/app
|
||||||
|
- /app/node_modules # Prevent overwriting node_modules
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ── Volumes ──────────────────────────────────────────────────────────────────
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
name: aegis_postgres_data
|
||||||
minio_data:
|
minio_data:
|
||||||
|
name: aegis_minio_data
|
||||||
|
|||||||
45
frontend/Dockerfile
Normal file
45
frontend/Dockerfile
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# ── Development Stage ──────────────────────────────────────────────────────
|
||||||
|
FROM node:20-alpine AS development
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Expose Vite dev server port
|
||||||
|
EXPOSE 5173
|
||||||
|
|
||||||
|
# Start dev server with host binding for Docker
|
||||||
|
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
|
||||||
|
|
||||||
|
|
||||||
|
# ── Build Stage ────────────────────────────────────────────────────────────
|
||||||
|
FROM node:20-alpine AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
|
||||||
|
# ── Production Stage ───────────────────────────────────────────────────────
|
||||||
|
FROM nginx:alpine AS production
|
||||||
|
|
||||||
|
# Copy built files to nginx
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Copy nginx config for SPA routing
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
35
frontend/nginx.conf
Normal file
35
frontend/nginx.conf
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
|
||||||
|
|
||||||
|
# SPA routing - serve index.html for all routes
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Proxy API requests to backend (for production)
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://backend:8000/api/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Health endpoint proxy
|
||||||
|
location /health {
|
||||||
|
proxy_pass http://backend:8000/health;
|
||||||
|
}
|
||||||
|
}
|
||||||
132
scripts/init.ps1
Normal file
132
scripts/init.ps1
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Aegis Initialization Script (PowerShell)
|
||||||
|
# =============================================================================
|
||||||
|
# This script initializes the Aegis platform after starting Docker containers.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# .\scripts\init.ps1
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
Write-Host "╔═══════════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
|
||||||
|
Write-Host "║ Aegis - Platform Initialization ║" -ForegroundColor Cyan
|
||||||
|
Write-Host "╚═══════════════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
function Write-Status {
|
||||||
|
param([string]$Message)
|
||||||
|
Write-Host "[✓] $Message" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
|
||||||
|
function Write-Warning {
|
||||||
|
param([string]$Message)
|
||||||
|
Write-Host "[!] $Message" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
function Write-Error {
|
||||||
|
param([string]$Message)
|
||||||
|
Write-Host "[✗] $Message" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if Docker is running
|
||||||
|
try {
|
||||||
|
docker info | Out-Null
|
||||||
|
} catch {
|
||||||
|
Write-Error "Docker is not running. Please start Docker first."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if containers are running
|
||||||
|
$backendRunning = docker-compose ps | Select-String "aegis-backend"
|
||||||
|
if (-not $backendRunning) {
|
||||||
|
Write-Warning "Containers not running. Starting them now..."
|
||||||
|
docker-compose up -d
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Waiting for services to be healthy..."
|
||||||
|
Start-Sleep -Seconds 10
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait for backend to be ready
|
||||||
|
Write-Host "Waiting for backend to be ready..."
|
||||||
|
$maxRetries = 30
|
||||||
|
$retryCount = 0
|
||||||
|
$ready = $false
|
||||||
|
|
||||||
|
while (-not $ready -and $retryCount -lt $maxRetries) {
|
||||||
|
try {
|
||||||
|
$response = Invoke-WebRequest -Uri "http://localhost:8000/health" -UseBasicParsing -TimeoutSec 2
|
||||||
|
if ($response.StatusCode -eq 200) {
|
||||||
|
$ready = $true
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
$retryCount++
|
||||||
|
Write-Host " Waiting... ($retryCount/$maxRetries)"
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $ready) {
|
||||||
|
Write-Error "Backend failed to start after $maxRetries attempts"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Status "Backend is healthy"
|
||||||
|
|
||||||
|
# Run database migrations
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Running database migrations..."
|
||||||
|
docker-compose exec -T backend alembic upgrade head
|
||||||
|
Write-Status "Migrations completed"
|
||||||
|
|
||||||
|
# Seed admin user
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Seeding admin user..."
|
||||||
|
try {
|
||||||
|
docker-compose exec -T backend python -m app.seed 2>$null
|
||||||
|
Write-Status "Admin user ready"
|
||||||
|
} catch {
|
||||||
|
Write-Warning "Admin user may already exist"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ask about MITRE sync
|
||||||
|
Write-Host ""
|
||||||
|
$runSync = Read-Host "Do you want to run initial MITRE ATT&CK sync? (y/N)"
|
||||||
|
if ($runSync -eq "y" -or $runSync -eq "Y") {
|
||||||
|
Write-Host "Triggering MITRE sync (this may take a minute)..."
|
||||||
|
|
||||||
|
try {
|
||||||
|
# Get admin token
|
||||||
|
$loginBody = "username=admin&password=admin123"
|
||||||
|
$loginResponse = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/login" `
|
||||||
|
-Method Post -Body $loginBody -ContentType "application/x-www-form-urlencoded"
|
||||||
|
|
||||||
|
$token = $loginResponse.access_token
|
||||||
|
|
||||||
|
if ($token) {
|
||||||
|
$headers = @{ "Authorization" = "Bearer $token" }
|
||||||
|
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/system/sync-mitre" `
|
||||||
|
-Method Post -Headers $headers | Out-Null
|
||||||
|
Write-Status "MITRE sync triggered"
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Warning "Could not authenticate. Run sync manually from the System page."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print summary
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "╔═══════════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
|
||||||
|
Write-Host "║ Aegis is ready! ║" -ForegroundColor Cyan
|
||||||
|
Write-Host "╠═══════════════════════════════════════════════════════════════════════╣" -ForegroundColor Cyan
|
||||||
|
Write-Host "║ ║" -ForegroundColor Cyan
|
||||||
|
Write-Host "║ Frontend: http://localhost:5173 ║" -ForegroundColor White
|
||||||
|
Write-Host "║ Backend API: http://localhost:8000 ║" -ForegroundColor White
|
||||||
|
Write-Host "║ Swagger UI: http://localhost:8000/docs ║" -ForegroundColor White
|
||||||
|
Write-Host "║ MinIO Console: http://localhost:9001 ║" -ForegroundColor White
|
||||||
|
Write-Host "║ ║" -ForegroundColor Cyan
|
||||||
|
Write-Host "║ Default login: admin / admin123 ║" -ForegroundColor Yellow
|
||||||
|
Write-Host "║ ║" -ForegroundColor Cyan
|
||||||
|
Write-Host "║ ⚠️ Change the default password in production! ║" -ForegroundColor Yellow
|
||||||
|
Write-Host "║ ║" -ForegroundColor Cyan
|
||||||
|
Write-Host "╚═══════════════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
|
||||||
|
Write-Host ""
|
||||||
114
scripts/init.sh
Normal file
114
scripts/init.sh
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# =============================================================================
|
||||||
|
# Aegis Initialization Script
|
||||||
|
# =============================================================================
|
||||||
|
# This script initializes the Aegis platform after starting Docker containers.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/init.sh
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "╔═══════════════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ Aegis - Platform Initialization ║"
|
||||||
|
echo "╚═══════════════════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Function to print status
|
||||||
|
print_status() {
|
||||||
|
echo -e "${GREEN}[✓]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_warning() {
|
||||||
|
echo -e "${YELLOW}[!]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
echo -e "${RED}[✗]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if Docker is running
|
||||||
|
if ! docker info > /dev/null 2>&1; then
|
||||||
|
print_error "Docker is not running. Please start Docker first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if containers are running
|
||||||
|
if ! docker-compose ps | grep -q "aegis-backend"; then
|
||||||
|
print_warning "Containers not running. Starting them now..."
|
||||||
|
docker-compose up -d
|
||||||
|
echo ""
|
||||||
|
echo "Waiting for services to be healthy..."
|
||||||
|
sleep 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Wait for backend to be ready
|
||||||
|
echo "Waiting for backend to be ready..."
|
||||||
|
MAX_RETRIES=30
|
||||||
|
RETRY_COUNT=0
|
||||||
|
until curl -s http://localhost:8000/health > /dev/null 2>&1; do
|
||||||
|
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||||||
|
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
|
||||||
|
print_error "Backend failed to start after $MAX_RETRIES attempts"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " Waiting... ($RETRY_COUNT/$MAX_RETRIES)"
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
print_status "Backend is healthy"
|
||||||
|
|
||||||
|
# Run database migrations
|
||||||
|
echo ""
|
||||||
|
echo "Running database migrations..."
|
||||||
|
docker-compose exec -T backend alembic upgrade head
|
||||||
|
print_status "Migrations completed"
|
||||||
|
|
||||||
|
# Seed admin user
|
||||||
|
echo ""
|
||||||
|
echo "Seeding admin user..."
|
||||||
|
docker-compose exec -T backend python -m app.seed 2>/dev/null || print_warning "Admin user may already exist"
|
||||||
|
print_status "Admin user ready"
|
||||||
|
|
||||||
|
# Trigger initial MITRE sync (optional)
|
||||||
|
echo ""
|
||||||
|
read -p "Do you want to run initial MITRE ATT&CK sync? (y/N) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Triggering MITRE sync (this may take a minute)..."
|
||||||
|
# Get admin token
|
||||||
|
TOKEN=$(curl -s -X POST "http://localhost:8000/api/v1/auth/login" \
|
||||||
|
-d "username=admin&password=admin123" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4)
|
||||||
|
|
||||||
|
if [ -n "$TOKEN" ]; then
|
||||||
|
curl -s -X POST "http://localhost:8000/api/v1/system/sync-mitre" \
|
||||||
|
-H "Authorization: Bearer $TOKEN" > /dev/null
|
||||||
|
print_status "MITRE sync triggered"
|
||||||
|
else
|
||||||
|
print_warning "Could not authenticate. Run sync manually from the System page."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Print summary
|
||||||
|
echo ""
|
||||||
|
echo "╔═══════════════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ Aegis is ready! ║"
|
||||||
|
echo "╠═══════════════════════════════════════════════════════════════════════╣"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ Frontend: http://localhost:5173 ║"
|
||||||
|
echo "║ Backend API: http://localhost:8000 ║"
|
||||||
|
echo "║ Swagger UI: http://localhost:8000/docs ║"
|
||||||
|
echo "║ MinIO Console: http://localhost:9001 ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ Default login: admin / admin123 ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ ⚠️ Change the default password in production! ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "╚═══════════════════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
Reference in New Issue
Block a user