|
| 1 | +# Architecture overview (ons-github-app) |
| 2 | + |
| 3 | +This folder documents how `ons-github-app` is put together, why key design decisions were made, and what the security posture looks like. |
| 4 | + |
| 5 | +Audience: |
| 6 | + |
| 7 | +- Technical architects (cloud topology, IaC, operational model) |
| 8 | +- Security colleagues (threat model, key controls, “what could go wrong”) |
| 9 | +- Interested engineers (how the pieces fit) |
| 10 | + |
| 11 | +If you want to *deploy* the system end-to-end, start with the setup tutorial at `docs/tutorial/README.md`. |
| 12 | + |
| 13 | +## What the system does (today) |
| 14 | + |
| 15 | +`ons-github-app` is a small FastAPI service that receives GitHub webhooks at `POST /webhooks/github`. |
| 16 | + |
| 17 | +Current demo behavior: |
| 18 | + |
| 19 | +- Verify webhook authenticity using `X-Hub-Signature-256` (HMAC-SHA256) |
| 20 | +- For `pull_request` events with `action=opened`, post a comment back to the PR as the GitHub App |
| 21 | + |
| 22 | +## High-level topology |
| 23 | + |
| 24 | +Inbound webhook traffic flows through API Gateway to Cloud Run. |
| 25 | + |
| 26 | +```mermaid |
| 27 | +flowchart LR |
| 28 | + GH[GitHub Webhooks] -->|HTTPS POST /webhooks/github| GW[GCP API Gateway] |
| 29 | + GW -->|HTTPS| CR[Cloud Run service] |
| 30 | + CR --> APP[FastAPI app] |
| 31 | +
|
| 32 | + APP -->|Reads secrets as files| SM[GCP Secret Manager] |
| 33 | + APP -->|JWT -> installation token| GHA[GitHub REST API] |
| 34 | +``` |
| 35 | + |
| 36 | +Key components: |
| 37 | + |
| 38 | +- **FastAPI app** (runtime): `src/app.py`, `src/webhook.py`, `src/github_app.py`, `src/config.py` |
| 39 | +- **Cloud Run** (compute): runs the container and scales based on request volume |
| 40 | +- **API Gateway** (ingress): routes `POST /webhooks/github` to Cloud Run |
| 41 | +- **Secret Manager** (secrets): stores the GitHub App private key and webhook secret |
| 42 | +- **Artifact Registry** (images): stores container images deployed to Cloud Run |
| 43 | +- **Terraform** (IaC): declares and provisions all the above |
| 44 | + |
| 45 | +## Endpoints |
| 46 | + |
| 47 | +- `GET /healthz` — liveness/health endpoint |
| 48 | +- `POST /webhooks/github` — GitHub webhook receiver |
| 49 | + |
| 50 | +## Data flow: webhook verification and response |
| 51 | + |
| 52 | +1. GitHub sends a webhook payload and includes `X-Hub-Signature-256: sha256=<digest>` |
| 53 | +2. The app reads the raw request body bytes |
| 54 | +3. The app recomputes the expected digest using the shared webhook secret |
| 55 | +4. The app compares digests using a constant-time comparison |
| 56 | +5. If valid and the event is accepted, the app executes the handler (e.g. post PR comment) |
| 57 | + |
| 58 | +## Secrets and configuration model |
| 59 | + |
| 60 | +This repo documents a single recommended approach: |
| 61 | + |
| 62 | +- Secrets are **stored as files** |
| 63 | +- The app receives **non-secret** environment variables that point at those files: |
| 64 | + - `GITHUB_PRIVATE_KEY_FILE` |
| 65 | + - `GITHUB_WEBHOOK_SECRET_FILE` |
| 66 | + |
| 67 | +Local development: |
| 68 | + |
| 69 | +- Keep secret files under `./local-secrets/` (ignored by git) |
| 70 | + |
| 71 | +Cloud Run: |
| 72 | + |
| 73 | +- Terraform provisions the Secret Manager *secret containers* |
| 74 | +- Secret *values* are added outside Terraform using `gcloud secrets versions add ...` |
| 75 | +- Terraform mounts the secrets into the container filesystem, and sets the `*_FILE` env vars |
| 76 | + |
| 77 | +## Infrastructure (Terraform) shape |
| 78 | + |
| 79 | +This repo is designed for a two-phase apply, described in `docs/tutorial/README.md`: |
| 80 | + |
| 81 | +1. **Bootstrap/shared infra** (no image) |
| 82 | + - APIs enabled |
| 83 | + - service account |
| 84 | + - Artifact Registry |
| 85 | + - Secret Manager secrets (containers only) |
| 86 | + |
| 87 | +2. **Deploy** (image provided) |
| 88 | + - Cloud Run service |
| 89 | + - API Gateway |
| 90 | + - IAM binding granting API Gateway permission to invoke Cloud Run |
| 91 | + |
| 92 | +## Operational notes |
| 93 | + |
| 94 | +- Logging: the app logs to stdout/stderr; on Cloud Run this lands in Cloud Logging. |
| 95 | +- Scaling: Cloud Run scales horizontally with incoming requests. (No explicit autoscaling tuning is configured in Terraform today.) |
| 96 | +- CI: GitHub Actions runs Checkov and Trivy filesystem scans; locally, `pre-commit` includes detect-secrets and terraform checks. |
| 97 | + |
| 98 | +## Design decisions (where to read more) |
| 99 | + |
| 100 | +- See `docs/architecture/design-decisions.md` for the short “why we chose X” list. |
| 101 | +- See `docs/architecture/security.md` for a security-focused view (threats, controls, and open gaps). |
0 commit comments