Skip to content

EvilCorp-Labs/webapp

Repository files navigation

Cloud Computing API

A scalable REST API built with FastAPI, deployed on AWS via Auto Scaling Group with full CI/CD.

Features

  • FastAPI with async support and automatic OpenAPI documentation
  • SQLModel ORM with MySQL database integration
  • Alembic database migrations
  • Structured JSON logging with request tracing (X-Request-ID)
  • StatsD metrics for API call counts and response time per endpoint
  • CloudWatch Agent integration with automatic dashboard deployment on first EC2 boot
  • Health check endpoint with database connectivity verification
  • User management with email verification via SNS → Lambda → Mailgun
  • BCrypt password hashing with strength validation
  • Environment-based configuration using Pydantic Settings
  • KMS-encrypted EBS, RDS, S3, and Secrets Manager via Terraform
  • HTTPS enforced at the ALB with ACM certificates; HTTP redirects to HTTPS

Project Structure

webapp/
├── alembic/                    # Database migrations
│   ├── versions/               # Migration scripts
│   └── env.py                  # Alembic configuration
├── app/
│   ├── api/routes/             # Route handlers (user, course, syllabus, healthz, metadata)
│   ├── core/                   # Config, auth, db, exceptions, logging, middleware, statsd
│   ├── model/                  # SQLModel database models
│   ├── schemas/                # Pydantic request/response schemas
│   └── services/               # Business logic (user, course, syllabus, SNS, S3, health)
├── scripts/                    # Packer provisioning scripts (see scripts/README.md)
├── tests/                      # Integration test suite
├── docs/
│   └── API.md                  # Full API reference
├── .github/
│   └── workflows/
│       ├── ci.yaml             # Integration tests + Packer validation (push + PR)
│       └── build.yaml          # AMI build + DEMO deploy (PR merged → main)
├── main.py                     # Application entrypoint
├── pyproject.toml              # Project dependencies & config
└── multi-cloud.pkr.hcl         # Packer template (AWS + GCP)

Prerequisites

  • Python 3.14+
  • MySQL 8.0+
  • uv

Quick Start

# Copy environment templates
cp .env.example .env
cp .env.db.example .env.db

# Edit with your settings
vi .env
vi .env.db

# Install dependencies
uv sync

# Run (development)
fastapi dev main.py

# Run (production)
fastapi run main.py

The API is available at http://localhost:8000.

Migrations run automatically on startup. No manual alembic upgrade head needed in production.

API Endpoints

Full request/response details: docs/API.md

Method Endpoint Auth Description
GET /healthz None Health check with DB verification
POST /v1/user None Create user account
GET /v1/user/self Basic Get authenticated user
PUT /v1/user/self Basic Update authenticated user
GET /v1/user/verify None Verify email address
GET /v1/courses Basic List all courses
GET /v1/courses/{id} Basic Get course by ID
POST /v1/courses Basic Create course
PUT /v1/courses/{id} Basic Update course
DELETE /v1/courses/{id} Basic Delete course
POST /v1/courses/{id}/syllabus Basic Upload syllabus to S3
DELETE /v1/courses/{id}/syllabus Basic Delete syllabus from S3

Authentication

HTTP Basic Authentication. Username must be a valid email address.

Authorization: Basic base64(email:password)

Configuration

.env — Application settings

Variable Default Description
AWS_REGION AWS region
AWS_S3_BUCKET_NAME S3 bucket for syllabus storage
AWS_SNS_TOPIC_ARN SNS topic for email verification
STATSD_HOST localhost StatsD host
STATSD_PORT 8125 StatsD port
LOG_FILE Optional file path for JSON logs
DEBUG false Enables /docs, /redoc, SQL logging

.env.db — Database credentials

Variable Description
DATABASE_HOST MySQL host
DATABASE_PORT MySQL port (default 3306)
DATABASE_USER MySQL username
DATABASE_PASSWORD MySQL password
DATABASE_NAME Database name

On AWS, .env.db is written by the EC2 user_data.sh script at launch time. The password is fetched from AWS Secrets Manager — it is never stored in the AMI or Terraform state.

Development

Running tests

# Install dev dependencies
uv sync --group dev

# Copy test env template
cp .env.test.example .env.test

# Run all tests
uv run pytest -v --cov=app --cov-report=term-missing

# Run specific file
uv run pytest tests/test_user_api.py -v

Linting

uv run ruff check .
uv run ruff format .

Database migrations

# Create a new migration
alembic revision --autogenerate -m "description"

# Apply manually (not needed in production — runs on startup)
alembic upgrade head

# Rollback one step
alembic downgrade -1

CI/CD

ci.yaml — Integration Tests (push + PR)

Runs on every push and pull request to main:

  1. Start MySQL service container
  2. Install Python 3.14 + uv
  3. Run linting (ruff)
  4. Run Alembic migrations
  5. Run pytest with coverage
  6. Upload test report artifact
  7. Validate Packer template (fmt + validate)

Required GitHub secrets (environment: CI):

Secret Description
MYSQL_ROOT_PASSWORD MySQL root password for the test container
MYSQL_DATABASE Test database name
MYSQL_USER Test database user
MYSQL_PASSWORD Test database password
AWS_REGION AWS region (used by app config during tests)
AWS_S3_BUCKET_NAME S3 bucket name (used by app config during tests)
AWS_SNS_TOPIC_ARN SNS topic ARN (used by app config during tests)
AWS_DEMO_ACCOUNT_ID DEMO account ID (for Packer validate)
GCP_PROJECT_ID GCP dev project ID (for Packer validate)
GCP_DEMO_PROJECT_ID GCP demo project ID (for Packer validate)
DB_NAME DB name passed to .env.setup for Packer validate
DB_USER DB user for .env.setup
DB_PASSWORD DB password for .env.setup
APP_GROUP App group for .env.setup
APP_USER App user for .env.setup
APP_DIR App dir for .env.setup
DATABASE_HOST DB host for .env.setup
DATABASE_PORT DB port for .env.setup
DATABASE_NAME DB name for .env.setup
DATABASE_USER DB user for .env.setup
DATABASE_PASSWORD DB password for .env.setup
AWS_SNS_TOPIC_ARN SNS ARN for .env.setup

build.yaml — PR Merged Deploy

Fires automatically when ci.yaml (Integration Tests) completes successfully on main. This happens on every PR merge.

Pipeline:

validate-packer → build-ami (DEV) → deploy-demo
  1. validate-packer: Packer fmt check + validate
  2. build-ami: Packer build in DEV (AMI shared with DEMO); extracts AMI ID
  3. deploy-demo:
    • Reconfigures AWS CLI to DEMO account credentials
    • Derives the Launch Template ID from the DEMO ASG
    • Creates a new Launch Template version with the latest AMI
    • Updates the ASG to use $Latest
    • Starts an instance refresh (MinHealthyPercentage: 50)
    • Polls until Successful; exits non-zero on Failed/Cancelled

Required GitHub secrets (environment: Packer):

Secret Description
AWS_ACCESS_KEY_ID DEV account IAM access key
AWS_SECRET_ACCESS_KEY DEV account IAM secret key
AWS_DEFAULT_REGION DEV account region
AWS_DEMO_ACCESS_KEY_ID DEMO account IAM access key
AWS_DEMO_SECRET_ACCESS_KEY DEMO account IAM secret key
AWS_DEMO_REGION DEMO account region (falls back to AWS_DEFAULT_REGION)
DEMO_ASG_NAME Name of the DEMO Auto Scaling Group (e.g. webapp-demo-asg)
GCP_CREDENTIALS GCP service account JSON
GCP_PROJECT_ID GCP dev project ID
GCP_DEMO_PROJECT_ID GCP demo project ID

Building the AMI with Packer

# Initialize plugins (first time only)
packer init multi-cloud.pkr.hcl

# Build for both AWS and GCP
packer build \
  -var="aws_demo_account_id=<DEMO_ACCOUNT_ID>" \
  -var="gcp_project_id=<GCP_DEV_PROJECT_ID>" \
  -var="gcp_demo_project_id=<GCP_DEMO_PROJECT_ID>" \
  multi-cloud.pkr.hcl

# AWS only
packer build -only="amazon-ebs.ubuntu_mysql" \
  -var="aws_demo_account_id=<DEMO_ACCOUNT_ID>" \
  multi-cloud.pkr.hcl

The built AMI is automatically shared with the DEMO AWS account and GCP demo project.

For provisioning script details, see scripts/README.md.

Security

  • HTTPS only: ALB enforces HTTPS (port 443); HTTP (port 80) redirects to HTTPS with 301
  • EC2 isolation: Application port ingress allowed only from ALB security group — not from the internet
  • KMS encryption: EBS, RDS, S3, and Secrets Manager all use dedicated Customer Managed Keys with 90-day rotation
  • Secrets Manager: DB password and Mailgun credentials stored in Secrets Manager, fetched at runtime — never baked into AMI or user data
  • BCrypt passwords: User passwords hashed with bcrypt + salt
  • Least-privilege IAM: EC2 and Lambda roles scoped to the minimum required resources

Architecture

Internet
   │ HTTPS (443)
   ▼
ALB (SSL termination, ACM certificate)
   │ HTTP (app_port)
   ▼
EC2 Instances (Auto Scaling Group)
   │             │              │
   ▼             ▼              ▼
RDS MySQL    S3 Bucket      SNS Topic
(private)   (private)          │
                                ▼
                           Lambda Function
                                │
                                ▼
                         Mailgun API (email)

All sensitive data: AWS Secrets Manager (KMS-encrypted)
All EBS/RDS/S3:    Customer Managed KMS Keys (90-day rotation)

About

The repository includes a rest-api, which will be used to understand various concepts regarding cloud computing and network topologies

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors