burrow/infra/identity/README.md
Conrad Kramer 640d4693ac
Some checks failed
Cache: Publish Nix / Publish Nix Cache (push) Successful in 3m4s
Build Rust / Cargo Test (push) Successful in 4m5s
Build Site / Next.js Build (push) Failing after 4s
Infra: OpenTofu / OpenTofu (grafana) (push) Successful in 4s
Lint Governance / BEP Metadata (push) Successful in 1s
Sign Sparkle appcasts in Python
2026-06-07 16:56:18 -07:00

147 lines
5.6 KiB
Markdown

# Burrow Identity KMS and WIF
This OpenTofu stack owns Google Cloud KMS and Workload Identity Federation
resources for Burrow identity and release automation.
It may manage:
- the `burrow-identity` Google KMS key ring
- non-exportable KMS signing keys for Authentik, the SAML CA, and release
signing
- dedicated non-exportable KMS signing keys for APT, RPM, pacman, Flatpak, and
AUR source release surfaces
- a non-exportable KMS signing key for the Apple Developer ID Application CSR
path (`apple-developer-id-application`)
- a non-exportable KMS signing key for the Apple iOS Distribution CSR path
(`apple-ios-distribution`)
- a non-exportable software KMS signing key for Sparkle Ed25519 appcast
signatures (`sparkle-ed25519`)
- an Authentik-backed WIF pool/provider for Forgejo runners
- the runner service account and its narrow IAM binding for the Authentik WIF
audience/client value `google-wif.burrow.net`; human/group grants are opt-in
It must not manage:
- Authentik private signing key material
- OpenBao bootstrap tokens
- store credentials or service-account JSON keys
Forgejo CI should authenticate with `Scripts/ci/google-wif-auth.sh`. That helper
uses Authentik to obtain an OIDC token and lets Google WIF impersonate
`burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com`
in project `project-88c23ce9-918a-470a-b33`.
## Apple Developer ID CSR
`Scripts/apple/google-kms-csr.py` builds a standard PKCS#10 CSR using the public
key from `projects/project-88c23ce9-918a-470a-b33/locations/global/keyRings/burrow-identity/cryptoKeys/apple-developer-id-application`
and asks Google KMS to sign the CSR payload. The private key remains
non-exportable in KMS.
Forgejo can generate the Apple-uploadable CSR with:
```sh
Scripts/forgejo-dispatch.sh apple-developer-id-kms-csr.yml --ref main
```
Apple currently documents Developer ID certificate creation through the
Developer website or Xcode. After downloading the returned `.cer`, keep it with
release artifacts; do not convert this key path into an exportable `.p12`.
The active certificate created from this path is Apple certificate
`9JKN6HXBHC`, stored at
`Apple/Certificates/developer-id-application-9JKN6HXBHC.cer`. Its public key
matches KMS key version `apple-developer-id-application/cryptoKeyVersions/1`.
## Apple iOS Distribution CSR
The iOS App Store distribution certificate uses the same CSR builder with the
`apple-ios-distribution` KMS key:
```sh
Scripts/apple/google-kms-csr.py \
--kms-key apple-ios-distribution \
--common-name "Burrow iOS Distribution" \
--output ios-distribution.certSigningRequest
```
The App Store Connect API can create the certificate from that CSR:
```sh
Scripts/apple/create-asc-certificate.mjs \
--certificate-type IOS_DISTRIBUTION \
--csr-file ios-distribution.certSigningRequest \
--out-dir Apple/Certificates
```
The active certificate created from this path is Apple certificate
`3G42677598`, stored at `Apple/Certificates/ios-distribution-3G42677598.cer`.
Its public key matches KMS key version
`apple-ios-distribution/cryptoKeyVersions/1`.
## Sparkle Appcast Signing
Sparkle appcasts keep `sparkle-ed25519`, a Google KMS key with algorithm
`EC_SIGN_ED25519` and software protection level, for small signing probes and
future signing-service work. Google KMS rejects Ed25519 at HSM protection level
and also rejects full-size macOS release archives as direct Ed25519 messages.
The tester pipeline therefore signs normal Sparkle archives directly from the
decrypted `SPARKLE_EDDSA_KEY_PATH` release seed so the appcast contains the
standard full-archive EdDSA signature Sparkle verifies.
The public EdDSA key embedded in macOS release builds is:
```text
uugZuJeqvvKd91NZ6F1Fv2cQenUbIG/ZW3L9MuaEz30=
```
The appcast signer is:
```sh
Scripts/sparkle/sign-appcast-kms.py \
--appcast dist/builds/<build>/sparkle/<channel>/appcast.xml \
--artifact-dir dist/builds/<build>/sparkle/<channel>
```
## Run
```sh
Scripts/identity-tofu.sh init -backend-config=backend.hcl
Scripts/identity-tofu.sh plan -var-file=terraform.tfvars
```
For local syntax work without remote state:
```sh
Scripts/identity-tofu.sh init -backend=false
Scripts/identity-tofu.sh validate
```
Start with `manage_google = false`. Import existing resources before enabling
management, then turn on one resource group at a time.
## Bootstrap Imports
The first live Apple Developer ID pass may need these resources imported before
an `identity` apply can own them:
```sh
Scripts/identity-tofu.sh import 'google_kms_key_ring.identity[0]' \
projects/project-88c23ce9-918a-470a-b33/locations/global/keyRings/burrow-identity
Scripts/identity-tofu.sh import 'google_kms_crypto_key.signing["apple_developer_id_application"]' \
projects/project-88c23ce9-918a-470a-b33/locations/global/keyRings/burrow-identity/cryptoKeys/apple-developer-id-application
Scripts/identity-tofu.sh import 'google_kms_crypto_key.signing["apple_ios_distribution"]' \
projects/project-88c23ce9-918a-470a-b33/locations/global/keyRings/burrow-identity/cryptoKeys/apple-ios-distribution
Scripts/identity-tofu.sh import 'google_kms_crypto_key.signing["sparkle_ed25519"]' \
projects/project-88c23ce9-918a-470a-b33/locations/global/keyRings/burrow-identity/cryptoKeys/sparkle-ed25519
Scripts/identity-tofu.sh import 'google_service_account.runner[0]' \
projects/project-88c23ce9-918a-470a-b33/serviceAccounts/burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com
```
Run imports with the same `manage_google`, key-ring, and service-account
variables that will be used for apply. Key-level IAM bindings should be imported
after the signing keys and service account exist.