# 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 use `sparkle-ed25519`, a non-exportable Google KMS key with algorithm `EC_SIGN_ED25519` and software protection level. Google KMS rejects Ed25519 at HSM protection level, so this key is intentionally separate from the HSM RSA keys used for Apple certificate CSRs and repository signing. The public EdDSA key embedded in macOS release builds is: ```text Myv9ZNZT6YGKMtMezh52ra4WqaeEKc4VlvVU0evhJeI= ``` The appcast signer is: ```sh Scripts/sparkle/sign-appcast-kms.py \ --appcast dist/builds//sparkle//appcast.xml \ --artifact-dir dist/builds//sparkle/ ``` ## 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.