The main implementation of YAML-driven infrastructure deployment with a web-based specification editor. This backend provides declarative infrastructure specifications driving automated AWS deployment through GitHub Actions workflows.
Key Technologies: Flask (Python), Terraform, AWS (ALB, WAF, EC2), Docker, GitHub Actions
- YAML specifications drive infrastructure deployment - Edit specs via web UI, trigger deployments automatically
- Web UI for managing pod configurations - Form-based editor for infrastructure specifications
- GitHub Actions automation - Workflow dispatch integration for deployment triggers
- AWS WAF security integration - Path-based filtering and rate limiting rules
- Path-based ALB routing - Multiple services behind a single load balancer (
/spec→ editor,/→ demo app) - Complete GitOps workflow - Changes committed to repo, deployed via IaC (Terraform)
graph TB
subgraph "User Access"
User[User Browser]
end
subgraph "AWS Infrastructure"
ALB[Application Load Balancer<br/>Path-Based Routing]
WAF[AWS WAF<br/>Security Protection]
subgraph "EC2 Instance - Docker Compose"
SpecEditor[Spec-Editor<br/>Flask App<br/>Port 5000]
DemoApp[Demo App<br/>Echo Server<br/>Port 80]
end
end
subgraph "GitHub"
Repo[action-spec Repository]
Actions[GitHub Actions<br/>deploy-pod.yml]
Specs[Pod Specs<br/>infra/customer/env/]
end
subgraph "Infrastructure as Code"
TF[Terraform Modules<br/>infra/modules/pod/]
end
User -->|HTTP Request| WAF
WAF -->|Allowed Paths| ALB
ALB -->|/spec*| SpecEditor
ALB -->|/*| DemoApp
SpecEditor -->|Read Specs| Specs
SpecEditor -->|Trigger Workflow| Actions
Actions -->|workflow_dispatch| Actions
Actions -->|terraform apply| TF
TF -->|Deploy/Update| EC2[EC2 Instance]
style User fill:#e1f5ff
style WAF fill:#ff9999
style ALB fill:#99ccff
style SpecEditor fill:#99ff99
style DemoApp fill:#ffcc99
style Actions fill:#cc99ff
style TF fill:#ffff99
Spec-Editor (Flask app, port 5000)
- Web UI for viewing and editing pod specifications
- GitHub API integration for spec storage and retrieval
- Workflow dispatch capability for triggering deployments
- Form-based interface with validation
Demo App (Echo server, port 80)
- Simple application demonstrating deployed workload
- Shows request/response details for testing
- Validates ALB routing is working
ALB Routing
/specand/spec/*→ Spec-editor UI/and all other paths → Demo application- Health checks on both target groups
WAF Protection
- Path filtering rules (only
/spec,/health,/api/v1/*allowed initially) - Rate limiting (10 requests per 5 minutes per IP)
- OWASP Top 10 managed rule groups
- Custom rules for common attack patterns
- Docker and Docker Compose installed
- GitHub personal access token with
repoandactions:writescopes - Git configured with user.name and user.email
- Clone the repository:
git clone https://github.com/yourusername/action-spec.git
cd action-spec- Create
.envfile with required variables:
# GitHub Configuration
GITHUB_TOKEN=ghp_your_token_here
GITHUB_OWNER=yourusername
GITHUB_REPO=action-spec
WORKFLOW_BRANCH=feature/demo-phase-d8 # or your branch name
# Flask Configuration
FLASK_ENV=development
FLASK_DEBUG=1- Start the services:
docker compose up- Access the services:
- Spec-Editor UI: http://localhost:5000
- Demo App: http://localhost:80
- Spec-editor mounts
infra/for live spec editing - Changes to Flask code require container restart
- Logs visible via
docker compose logs -f spec-editor
The implementation uses a "pod" infrastructure pattern where each pod is a self-contained deployment unit:
infra/
└── {customer}/ # Customer/organization name (e.g., advworks)
└── {environment}/ # Environment (dev, staging, prod)
├── spec.yml # Pod specification (what to deploy)
└── terraform/ # Generated Terraform configs (managed by workflow)
Each pod has a spec.yml file defining:
- Instance configuration: type, AMI, key pair
- Networking: VPC, subnets, security groups
- Features: WAF enabled/disabled, ALB settings
- Application: Docker image, environment variables
Example spec.yml:
pod:
customer: advworks
environment: dev
instance:
type: t4g.nano
ami: ami-0c55b159cbfafe1f0
networking:
vpc_id: vpc-12345
subnet_ids:
- subnet-abc123
features:
waf_enabled: true
alb_enabled: trueThe deploy-pod.yml workflow:
- Triggered via workflow_dispatch (from spec-editor UI or manually)
- Validates pod specification
- Runs
terraform planto preview changes - Applies infrastructure changes via
terraform apply - Commits updated state back to repository
- Returns deployment status and Action URL
Trigger from UI: Click "Deploy Changes" button in spec-editor Trigger manually: GitHub UI → Actions tab → deploy-pod → Run workflow
sequenceDiagram
actor User
participant UI as Spec-Editor UI<br/>(http://alb-url/spec)
participant GH as GitHub
participant Actions as GitHub Actions
participant TF as Terraform
participant AWS as AWS Infrastructure
User->>UI: 1. Access spec-editor
UI->>GH: 2. Fetch pod specs
GH-->>UI: 3. Return YAML specs
UI-->>User: 4. Display form with current config
User->>UI: 5. Edit pod config (e.g., enable WAF)
User->>UI: 6. Click "Deploy Changes"
UI->>GH: 7. Trigger workflow_dispatch
GH->>Actions: 8. Start deploy-pod.yml
Actions->>GH: 9. Checkout repo
Actions->>TF: 10. terraform plan
Actions->>TF: 11. terraform apply
TF->>AWS: 12. Create/update infrastructure
AWS-->>TF: 13. Resources deployed
Actions-->>UI: 14. Return Action URL
UI-->>User: 15. Show success + GitHub Action link
User->>User: 16. Click Action link
User->>Actions: 17. View deployment logs
- Access spec-editor: Navigate to
http://<alb-url>/spec - Select pod: Choose customer and environment (e.g., advworks/dev)
- View current configuration: Form displays current spec.yml values
- Make changes:
- Change instance name
- Enable/disable WAF
- Modify instance type
- Deploy changes: Click "Deploy Changes" button
- Deployment triggers: GitHub Action starts automatically
- View progress: Click the returned Action URL to watch logs
- Verify deployment: Check AWS Console for infrastructure changes
- Test demo app: Visit
http://<alb-url>/to see deployed application - Test WAF: Try blocked paths (e.g.,
/admin) to verify security rules
Backend Application
backend/- Flask spec-editor applicationapp.py- Main application entry pointtemplates/- Jinja2 HTML templatesstatic/- CSS and client-side assets
Infrastructure Specifications
infra/- Pod specifications organized by customer/environment- Currently contains: advworks/dev, contoso/staging, fabrikam/prod
Terraform Modules
infra/modules/pod/- Reusable Terraform module for pod deployment- Manages EC2, ALB, WAF, security groups, IAM roles
Development Environment
docker-compose.yml- Local development setup (at root)backend/Dockerfile- Container image for spec-editorjustfile- Task runner with useful commands (at root)
GitHub Workflows
.github/workflows/deploy-pod.yml- Pod deployment automation.github/workflows/terraform-plan.yml- Preview infrastructure changes.github/workflows/terraform-apply.yml- Apply infrastructure changes
The Flask application exposes REST API endpoints for programmatic access to pod specification management. These endpoints enable frontend decoupling and headless automation.
List all pods discovered from GitHub repository structure.
Response:
[
{"customer": "acme", "env": "dev"},
{"customer": "acme", "env": "prod"}
]Example:
curl http://localhost:5000/api/podsFetch spec.yml for a specific pod.
Parameters:
customer- Customer name (alphanumeric, hyphens, underscores)env- Environment name (dev, stg, prd)
Response:
{
"metadata": {
"customer": "acme",
"environment": "dev",
"version": "1.0"
},
"spec": {
"compute": {
"instance_name": "acme-dev-web",
"instance_type": "t4g.nano"
},
"security": {
"waf": {
"enabled": true
}
}
}
}Error Responses:
400- Invalid customer/env format404- Pod not found500- GitHub API error
Example:
curl http://localhost:5000/api/pod/acme/devCreate or update a pod specification.
Request Body:
{
"customer": "acme",
"env": "dev",
"spec": {
"instance_name": "acme-dev-web",
"waf_enabled": true
},
"commit_message": "Deploy acme dev environment (optional)"
}Response:
{
"branch": "deploy-acme-dev-1234567890",
"pr_url": "https://github.com/owner/repo/pull/123",
"pr_number": 123
}Error Responses:
400- Validation error (invalid input)500- GitHub API error (branch/PR creation failed)
Example:
curl -X POST http://localhost:5000/api/pod \
-H "Content-Type: application/json" \
-d '{
"customer": "acme",
"env": "dev",
"spec": {
"instance_name": "acme-dev-web",
"waf_enabled": true
}
}'Health check endpoint with GitHub connectivity status.
Response:
{
"status": "healthy",
"github": "connected",
"repo": "owner/repo",
"scopes": {
"repo": true,
"workflow": true
},
"rate_limit": {
"remaining": 4999,
"limit": 5000,
"reset_at": 1234567890
}
}Example:
curl http://localhost:5000/healthAll API endpoints return errors in consistent JSON format:
{
"error": "Human-readable error message",
"details": {
"additional": "context"
}
}CORS is not enabled by default since the Flask app serves both API and frontend from the same origin (no cross-origin requests). If needed for development, CORS can be configured via environment variables.
The justfile provides convenient commands for testing WAF rules:
# Test path-based filtering (tests allowed and blocked paths)
just waf-test-paths http://your-alb-url.amazonaws.com
# Test rate limiting (fires 200 requests to trigger rate limits)
just waf-test-rate http://your-alb-url.amazonaws.com
# Run all WAF tests
just waf-test-all http://your-alb-url.amazonaws.comAllowed Paths (should return 200 OK):
/spec- Spec-editor UI/spec/pod/advworks/dev- Pod form/health- Health check endpoint/api/v1/pods- API endpoints/- Demo application
Blocked Paths (should return 403 Forbidden):
/admin- Admin panel (common attack target)/malicious- Explicitly blocked pattern/../../etc/passwd- Path traversal attempt.php,.aspfiles - Disallowed file extensions
Rate Limiting:
- First ~10 requests from same IP succeed (200 OK)
- Subsequent requests blocked (403 Forbidden)
- Rate limit resets after 5 minutes
Test ALB routing:
# Should show spec-editor UI
curl -i http://<alb-url>/spec
# Should show demo app
curl -i http://<alb-url>/
# Should be blocked by WAF
curl -i http://<alb-url>/adminTest workflow dispatch:
# Trigger deployment via API (requires GitHub token)
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/OWNER/REPO/actions/workflows/deploy-pod.yml/dispatches \
-d '{"ref":"main","inputs":{"customer":"advworks","environment":"dev"}}'This implementation has intentional scope limitations:
Security Constraints:
- ❌ No user authentication (single-tenant implementation)
- ❌ GitHub token stored in environment (not secrets manager)
- ❌ No HTTPS in local development
⚠️ Wide-open security groups (not production ready)
Functionality Constraints:
- ❌ No delete functionality (safety measure - creates and updates only)
- ❌ Limited to 3 customers (hardcoded in spec.yml structure)
- ❌ No rollback capability (manual revert via Git required)
- ❌ No deployment history or audit log
- ❌ No concurrent deployment protection
Cost Optimization:
- Uses t4g.nano instances (cost-optimized, not performance-optimized)
- No auto-scaling (single instance per pod)
- No multi-region deployment
Data Persistence:
- Specs stored in Git (no database)
- No backup/restore functionality
- No config drift detection
Production Readiness:
- This is a portfolio project, not production-grade infrastructure
- See parent
README.mdfor enterprise solution roadmap - Missing: monitoring, alerting, disaster recovery, compliance controls
For Local Development:
- Explore the spec-editor UI at http://localhost:5000
- Review pod specifications in
infra/ - Make changes and observe workflow triggers
- Review Terraform modules in
infra/modules/
For AWS Deployment:
- Configure AWS credentials in GitHub Secrets
- Update pod specifications with your AWS resource IDs
- Trigger deployment via spec-editor or GitHub Actions
- Monitor deployment via Action logs
- Test WAF rules using justfile commands
For Contributing:
- See parent repository
CONTRIBUTING.md(if exists) - Follow commit message conventions (conventional commits)
- Test locally before deploying to AWS
- Document any new features or changes
Issue: Spec-editor shows "Failed to fetch pods"
- Solution: Check
GITHUB_TOKENis set in.envand hasreposcope
Issue: Docker compose fails to start
- Solution: Check ports 5000 and 80 are not in use (
lsof -i :5000)
Issue: Deployment workflow fails
- Solution: Check Action logs in GitHub UI, verify AWS credentials and permissions
Issue: WAF blocks spec-editor access
- Solution: Verify ALB rules allow
/specpath, check WAF rules in AWS Console
Issue: Changes not reflected after deployment
- Solution: Check Git branch matches
WORKFLOW_BRANCHin.env, verify workflow completed successfully
- Parent Project: See
../README.mdfor overall project goals and architecture - Enterprise PRD: See
../overengineered/PRD.mdfor planned enterprise features (archived) - Terraform Docs: Terraform AWS Provider
- GitHub Actions: Workflow Syntax
- AWS WAF: WAF Developer Guide
Version: v0.1.0 (Alpha) Maintained by: ActionSpec Team License: See parent repository LICENSE file