Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ RATE_LIMIT_ENABLED=True
RATE_LIMIT_PER_MINUTE=60

# Security
SECRET_KEY=dev-secret-key-change-in-production-UNSAFE
# CRITICAL: Generate a secure random key for production!
# Run: python -c "import secrets; print(secrets.token_urlsafe(32))"
SECRET_KEY=<REQUIRED_SET_IN_PRODUCTION>
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

Expand Down Expand Up @@ -58,5 +60,19 @@ TEMPORAL_HOST=localhost:7233
TEMPORAL_NAMESPACE=default
TEMPORAL_TASK_QUEUE=fastapi-tasks

# External Services
EMAIL_API_KEY=dev-email-api-key-UNSAFE
# External Services - Email Configuration
EMAIL_PROVIDER=smtp
EMAIL_FROM_ADDRESS=noreply@example.com
EMAIL_FROM_NAME=Python Fast Forge

# SMTP Configuration (for EMAIL_PROVIDER=smtp)
SMTP_HOST=localhost
SMTP_PORT=587
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_USE_TLS=True
SMTP_USE_SSL=False

# Email API Key (for SendGrid, SES, Mailgun)
# REQUIRED: Set your email provider API key (SendGrid/SES/Mailgun)
EMAIL_API_KEY=<REQUIRED_SET_IN_PRODUCTION>
7 changes: 6 additions & 1 deletion .github/workflows/database-migrations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ jobs:
name: Validate Migrations
runs-on: ubuntu-latest
timeout-minutes: 10
needs: check-token
if: needs.check-token.outputs.has_token == 'true'

services:
postgres:
Expand Down Expand Up @@ -128,6 +130,8 @@ jobs:
name: Test Migration Application
runs-on: ubuntu-latest
timeout-minutes: 10
needs: check-token
if: needs.check-token.outputs.has_token == 'true'

services:
postgres:
Expand Down Expand Up @@ -181,7 +185,8 @@ jobs:
name: Check Schema Drift
runs-on: ubuntu-latest
timeout-minutes: 10
if: github.event_name == 'pull_request'
needs: check-token
if: needs.check-token.outputs.has_token == 'true' && github.event_name == 'pull_request'

services:
postgres:
Expand Down
144 changes: 144 additions & 0 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
name: Security & Compliance Scan

on:
push:
branches: [ main, master, develop ]
pull_request:
branches: [ main, master, develop ]
schedule:
# Run daily at 2 AM UTC
- cron: '0 2 * * *'
workflow_dispatch: # Allow manual trigger

permissions:
contents: read
security-events: write # For uploading SARIF results

jobs:
trivy-scan:
name: Trivy Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'HIGH,CRITICAL'
exit-code: '0' # Don't fail build, just report

- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'

- name: Run Trivy in table format
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'table'
severity: 'HIGH,CRITICAL'
exit-code: '0'

python-security:
name: Python Security Audit
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Install dependencies
run: |
uv sync --group security

- name: Run Bandit security linter
run: |
uv run bandit -c pyproject.toml -r src/ -f json -o bandit-report.json || true
uv run bandit -c pyproject.toml -r src/ -f screen || true

- name: Run Safety scan
run: |
uv run safety scan --output json > safety-report.json || true
uv run safety scan || true

- name: Run pip-audit
run: |
uv run pip-audit --format json --output pip-audit-report.json || true
uv run pip-audit --desc || true

- name: Generate SBOM
run: |
uv run cyclonedx-py environment -o sbom.json --of JSON --sv 1.5 || true

- name: Upload SBOM artifact
uses: actions/upload-artifact@v4
if: always()
with:
name: sbom
path: sbom.json
if-no-files-found: ignore

- name: Upload security reports
uses: actions/upload-artifact@v4
if: always()
with:
name: security-reports
path: |
bandit-report.json
safety-report.json
pip-audit-report.json
if-no-files-found: ignore

license-compliance:
name: License Compliance Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Install dependencies
run: |
uv sync --group security

- name: Check license compatibility
run: |
timeout 60 uv run licensecheck --format text || true

- name: Generate license report
run: |
uv run pip-licenses --format=markdown --output-file=licenses.md || true

- name: Upload license report
uses: actions/upload-artifact@v4
if: always()
with:
name: license-report
path: licenses.md
if-no-files-found: ignore
32 changes: 32 additions & 0 deletions .github/workflows/test-and-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,38 @@ jobs:
python-version: ${{ matrix.python-version }}
dependency-groups: dev test

- name: Verify service connectivity
run: |
echo "Checking PostgreSQL..."
timeout 10 bash -c 'until pg_isready -h localhost -p 5432; do sleep 1; done' || {
echo "::error::PostgreSQL is not ready"
docker ps
exit 1
}

echo "Checking Redis..."
timeout 10 bash -c 'until nc -z localhost 6379; do sleep 1; done' || {
echo "::error::Redis is not ready"
docker ps
exit 1
}

echo "✅ All services are ready"

- name: Verify dependencies installed
run: |
echo "Checking critical dependencies..."
uv pip list | grep -E "dependency-injector|fastapi|sqlalchemy|pytest" || true
echo ""
echo "Python version:"
python --version
echo ""
echo "Attempting test imports..."
python -c "import dependency_injector; print('✅ dependency_injector imported')" || echo "❌ dependency_injector failed"
python -c "import fastapi; print('✅ fastapi imported')" || echo "❌ fastapi failed"
python -c "import sqlalchemy; print('✅ sqlalchemy imported')" || echo "❌ sqlalchemy failed"
python -c "import pytest; print('✅ pytest imported')" || echo "❌ pytest failed"

- name: Run unit tests
run: |
uv run pytest tests/unit/ \
Expand Down
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ coverage.xml
.hypothesis/
.pytest_cache/

# Security & compliance reports
compliance-reports/
sbom.json
sbom.xml
licenses.md
licenses.json
dependencies.json
bandit-report.json
safety-report.json
pip-audit-report.json
trivy-report.json
trivy-results.sarif

# Environments
.env
.venv
Expand Down Expand Up @@ -81,3 +94,6 @@ dmypy.json
tmp/
temp/
*.tmp

# Development JWT keys (auto-generated)
.dev_jwt_private_key.pem
Loading
Loading