gcp-wif-token-valid-for-sa

explicit gcp emits CredentialValidFor

match (record)

{ "field": "iamPolicy.bindings[role=roles/iam.workloadIdentityUser]", "resource_type": "google.iam.ServiceAccount" }

emit

source typeToken
target typeServiceIdentity
source<federated STS access token minted for the WIF principal>
target<impersonated ServiceAccount>

Narrative

A federated STS token for the WIF principal is valid for {sa.name} (short-lived, no static key), obtained via the token exchange + getAccessToken.

Raw rule rules/explicit/gcp-wif.yaml

id: gcp-wif-token-valid-for-sa
emits: CredentialValidFor
applies_to:
- gcp
match_record:
  resource_type: google.iam.ServiceAccount
  field: iamPolicy.bindings[role=roles/iam.workloadIdentityUser]
emit:
  source_type: Token
  target_type: ServiceIdentity
  source: <federated STS access token minted for the WIF principal>
  target: <impersonated ServiceAccount>
  api_source: sts.googleapis.com token-exchange + iamcredentials generateAccessToken
  evidence_field: presence of a roles/iam.workloadIdentityUser binding for a WIF principal
  properties:
    static_key: false
    mechanism: sts.googleapis.com token-exchange -> iam.serviceAccounts.getAccessToken
  false_positive_note: 'This is not a harvestable long-lived credential (no iam.serviceAccountKeys.create):
    the federated token is short-lived and only mintable by an external identity that satisfies the provider
    trust AND the workloadIdentityUser binding. Path value comes from the derived CanFederateAs, not from
    this fact alone. Do not emit if no workloadIdentityUser binding maps a WIF principal to the SA.'
  narrative: A federated STS token for the WIF principal is valid for {sa.name} (short-lived, no static
    key), obtained via the token exchange + getAccessToken.
move · open · esc close