audit-labs/gh-attest

GitHub Audit Evidence Extractor

clone: git clone https://gitbay.org/audit-labs/gh-attest.git

v1.0.3: README.md · raw

  1# gh-attest
  2
  3[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=audit-labs_gh-attest&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=audit-labs_gh-attest)
  4[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=audit-labs_gh-attest&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=audit-labs_gh-attest)
  5[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=audit-labs_gh-attest&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=audit-labs_gh-attest)
  6[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=audit-labs_gh-attest&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=audit-labs_gh-attest)
  7[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE)
  8
  9Turns GitHub security settings into auditor-ready evidence. A GitHub App that
 10records branch protection, scanning alerts, and organization access as they
 11change, maps them to SOC 2 and ISO 27001 controls, and exports point-in-time
 12CSV and PDF evidence packages.
 13
 14Read-only — it never modifies your repositories, permissions, or membership.
 15
 16![GitHub Attest Dashboard](./preview.png "GitHub Attest Dashboard")
 17
 18## What it collects
 19
 20| Signal | Evidence for |
 21| --- | --- |
 22| Branch protection, repository rulesets | SOC 2 CC8.1 · ISO 27001 A.8.32 |
 23| Secret scanning alerts | SOC 2 CC6.1, CC6.6 · ISO 27001 A.5.17 |
 24| Dependabot alerts | SOC 2 CC7.1, CC7.2 · ISO 27001 A.8.8 |
 25| Code scanning alerts | SOC 2 CC7.1 · ISO 27001 A.8.28, A.8.29 |
 26| Organization / team membership | SOC 2 CC6.2, CC6.3 · ISO 27001 A.5.18 |
 27| Repository inventory | ISO 27001 A.5.9 |
 28
 29Mappings live in `migrations/` and are applied as a join at query time, so a
 30mapping can be corrected without re-ingesting history. Every mapping — and the
 31plain-language rationale for why each signal is evidence for its control — is
 32documented in [docs/framework-mapping.md](docs/framework-mapping.md).
 33
 34## How it works
 35
 36Webhooks capture changes as they happen; an hourly cron polls for state that
 37webhooks never announce (protection that existed before install, and current
 38membership). Each observation is stored as a timestamped snapshot in D1.
 39Exports render off the request path via a queue, into R2.
 40
 41**Stack:** Cloudflare Workers · D1 · R2 · Queues. All storage is provisioned
 42under Cloudflare's `eu` jurisdiction.
 43
 44## Endpoints
 45
 46| Route | Auth | Purpose |
 47| --- | --- | --- |
 48| `GET /` | session | Dashboard: current posture, exports |
 49| `GET /access-review` | session | Membership changes since a date |
 50| `POST /exports`, `/resync`, `/switch` | session | Dashboard actions |
 51| `GET /exports/:id[/download]` | session | Export status / file |
 52| `POST /webhooks/github` | HMAC | App events |
 53| `POST /webhooks/marketplace` | HMAC | Marketplace events |
 54| `POST /admin/{poll,export,cleanup,purge}` | bearer | Operations |
 55
 56Session routes are scoped by installation; admin routes require `ADMIN_TOKEN`.
 57
 58## Development
 59
 60```sh
 61npm install
 62cp .dev.vars.example .dev.vars   # fill in, see below
 63npm run db:migrate:local
 64npm run dev
 65```
 66
 67Type checking: `npm run typecheck`. Generate binding types after editing
 68`wrangler.jsonc`: `npm run types`.
 69
 70## Deployment
 71
 72```sh
 73npm run db:migrate:remote
 74npm run deploy
 75```
 76
 77Secrets are set with `wrangler secret put <NAME>` — never in `wrangler.jsonc`:
 78
 79| Secret | Purpose |
 80| --- | --- |
 81| `GITHUB_APP_ID`, `GITHUB_APP_PRIVATE_KEY` | Mint installation tokens |
 82| `GITHUB_WEBHOOK_SECRET` | Verify webhook signatures |
 83| `GITHUB_APP_CLIENT_ID`, `GITHUB_APP_CLIENT_SECRET` | Dashboard OAuth |
 84| `SESSION_SECRET` | Sign session cookies |
 85| `ADMIN_TOKEN` | Bearer for `/admin/*` |
 86
 87Pipe the private key from its file rather than pasting it:
 88`wrangler secret put GITHUB_APP_PRIVATE_KEY < key.pem`
 89
 90> Cron triggers occasionally stop firing after a deploy. If the hourly poll
 91> goes quiet, set `triggers.crons` to `[]`, deploy, restore it, and deploy
 92> again — a same-value redeploy does not clear it.
 93
 94## Data handling
 95
 96Evidence is retained for 13 months and exports for 90 days; everything for an
 97installation is deleted when the App is uninstalled. No source code or access
 98tokens are stored. See [PRIVACY.md](PRIVACY.md).
 99
100Retention periods are defined in `src/index.ts` and restated in `PRIVACY.md`101change both together.
102
103## License
104
105GPL-3.0. See [LICENSE](LICENSE).