observability: Google Play analytics through WIF (read-only play-reports service account, no JSON key) #174
No reviewers
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
key-store/key.store!174
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "claude/kse-0191-play-reports-wif"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
KSE-0191 follow-up. Google revoked the
release@key-d0t-storeservice-account key on 2026-08-17 (the publish lane already moved to WIF inpublish-store-uploads.yml), sostore-analyticshas been failing its Play leg withinvalid_grant: Invalid JWT Signature. Rather than mint a new long-lived key:infra/identity/play-reports.tf: read-onlyplay-reports@key-d0t-store.iam.gserviceaccount.com(no project roles — Play Console attaches permissions to the e-mail), an authoritativeroles/iam.workloadIdentityUserbinding for the forge-host WIF principal only,playdeveloperreporting.googleapis.comenabled (disable_on_destroy=false). Outputgoogle_play_reports_service_account_email. Gated onmanage_google_play_reports_service_account(default true).lib/common.cjsgoogleWorkloadIdentityToken(): external_account file → STS token exchange →generateAccessTokenon the target SA.store-analytics.cjsgooglePlayCredential(): WIF first (GOOGLE_APPLICATION_CREDENTIALS+GOOGLE_PLAY_IMPERSONATE_SERVICE_ACCOUNT), JSON key only for local use;key_store_store_auth_mode{provider="google-play",mode}./run/google-wif/credentials.json+ the target SA and orders aftergoogle-wif-credentials; the revoked key is no longer handed to it.Validation:
tofu validate(identity) ok;node --self-testok; forge toplevel builds (…-26.05.20260822.93478b31, unit env/ordering verified); live on the forge with the real forge-host credential: STS exchange ok, impersonation 404 (SA does not exist yet — expected).cloud-tofuonly runs onmain, so the identity plan appears after merge (expected: 3 to add).After merge (founder): 1)
cloud-tofustackidentityplan→apply; 2) Play Console → Users and permissions → inviteplay-reports@key-d0t-store.iam.gserviceaccount.com→store.key.application→ "View app information and download bulk reports" (read-only); 3)deploy-forge-host(switch) — also shipsbcbe0659(ClickHouse readonly=2) already on main; 4)systemctl start store-analyticson the forge or wait for the timer;key_store_store_auth_mode{mode="wif"}= 1 andkey_store_store_config_missing{item="play_reports_bucket_access"}disappears once the invite is accepted.STORE_ANALYTICS_PLAY_REPORTS_BUCKET(pubsite_prod_…) still needs to go into/etc/key-store/store-analytics.envfor the bulk-report CSVs; the vitals (crash/ANR) leg works without it.🤖 Generated with Claude Code
Google revoked the release@key-d0t-store service-account key on 2026-08-17 (the publish lane already moved to WIF), so store-analytics could not reach Play Console reports. Rather than mint a new long-lived key: - infra/identity/play-reports.tf: a read-only play-reports service account (no project roles; Play Console attaches its permissions to the e-mail) with an authoritative roles/iam.workloadIdentityUser binding for the forge-host WIF principal, plus playdeveloperreporting.googleapis.com. Output google_play_reports_service_account_email. Founder step: invite that e-mail in Play Console with "View app information and download bulk reports". - lib/common.cjs googleWorkloadIdentityToken(): external_account file → STS token exchange → generateAccessToken on the target SA. - store-analytics.cjs googlePlayCredential(): WIF first (GOOGLE_APPLICATION_CREDENTIALS + GOOGLE_PLAY_IMPERSONATE_SERVICE_ACCOUNT), JSON key only for local use; key_store_store_auth_mode{mode} gauge. - forge: the unit gets the WIF credential + target SA and orders after google-wif-credentials; the revoked key is no longer handed to it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>93478b3121to9a493e3ed4