gcp-gcs-hmac-key-create

storage.hmacKeys.create generates a long-lived HMAC key (ID + secret) for a Service Account; the secret grants S3-compatible access to all GCS buckets the SA can reach but is scoped to the GCS API only, not full SA impersonation.

derived gcp emits CanCreateCredentialFor

match (effective permission)

{ "action": "storage.hmacKeys.create", "resource_type": "google.storage.HmacKey" }

where

principal has EFFECTIVE storage.hmacKeys.create at the project scope (included in roles/storage.hmacKeyAdmin) principal also has EFFECTIVE iam.serviceAccounts.actAs on the target SA (to create a key FOR another SA; if creating for self, actAs is not required)

emit

source typeIdentity
target typeServiceAccount
source<principal>
target<Service Account (HmacKey target)>
permissionsstorage.hmacKeys.create iam.serviceAccounts.actAs?
conditionsiam_permission role_compatibility
state logicCONDITIONAL(iam_permission) as default: the HMAC key secret grants S3-compatible GCS access only (NOT full Google Cloud API access). ACTIVE when storage.hmacKeys.create is confirmed at the project scope AND (the target SA is the calling SA itself OR iam.serviceAccounts.actAs is also confirmed on the target SA); CONDITIONAL(iam_permission) when actAs grant is uncertain for a cross-SA key creation; BLOCKED when an org policy disables HMAC key creation (constraints/storage.hmacKeyServiceAccount restrictions) or an IAM deny targets storage.hmacKeys.create. Note: this edge grants S3-compatible credential creation, not full SA impersonation across Google APIs.

Narrative

{principal.name} holds storage.hmacKeys.create and can generate a long-lived HMAC key (access-key ID + secret) for service account {sa.name}; the returned secret grants S3-compatible access to all GCS buckets {sa.name} can reach via the GCS S3 API only (NOT full Google Cloud API access).

Raw rule rules/derived/gcp/gcs.yaml

id: gcp-gcs-hmac-key-create
emits: CanCreateCredentialFor
description: storage.hmacKeys.create generates a long-lived HMAC key (ID + secret) for a Service Account;
  the secret grants S3-compatible access to all GCS buckets the SA can reach but is scoped to the GCS
  API only, not full SA impersonation.
match_effective_permission:
  action: storage.hmacKeys.create
  resource_type: google.storage.HmacKey
where:
- principal has EFFECTIVE storage.hmacKeys.create at the project scope (included in roles/storage.hmacKeyAdmin)
- principal also has EFFECTIVE iam.serviceAccounts.actAs on the target SA (to create a key FOR another
  SA; if creating for self, actAs is not required)
emit:
  source_type: Identity
  target_type: ServiceAccount
  source: <principal>
  target: <Service Account (HmacKey target)>
  permissions:
  - storage.hmacKeys.create
  - iam.serviceAccounts.actAs?
  conditions:
  - iam_permission
  - role_compatibility
  scope_qualifier: gcs_s3_compatible_api_only
  state_logic: 'CONDITIONAL(iam_permission) as default: the HMAC key secret grants S3-compatible GCS access
    only (NOT full Google Cloud API access). ACTIVE when storage.hmacKeys.create is confirmed at the project
    scope AND (the target SA is the calling SA itself OR iam.serviceAccounts.actAs is also confirmed on
    the target SA); CONDITIONAL(iam_permission) when actAs grant is uncertain for a cross-SA key creation;
    BLOCKED when an org policy disables HMAC key creation (constraints/storage.hmacKeyServiceAccount restrictions)
    or an IAM deny targets storage.hmacKeys.create. Note: this edge grants S3-compatible credential creation,
    not full SA impersonation across Google APIs.'
  confidence: min(contributing_confidences) * 0.97
  derived_from:
  - storage.hmacKeys.create effective permission at project scope
  - iam.serviceAccounts.actAs on target SA (if cross-SA)
  false_positive_note: "The HMAC secret is returned ONLY at creation time (CreateHmacKeyResponse.secret);\
    \ storage.hmacKeys.get / storage.hmacKeys.list return only the key metadata (ID, state, SA email)\
    \ \u2014 NOT the secret. Only emit CanCreateCredentialFor from the CREATE action, not from list/get.\
    \ Callers need iam.serviceAccounts.actAs on the target SA when the key is for a SA other than themselves\
    \ \u2014 without actAs, the Storage API returns 403; downgrade to CONDITIONAL(iam_permission). The\
    \ HMAC secret is valid only while the key state is ACTIVE; if the SA is disabled or the key is deactivated,\
    \ the credential is not usable. An org policy constraints/storage.hmacKeyServiceAccount that restricts\
    \ which SAs can have HMAC keys may block creation for certain SAs -> CONDITIONAL(scp_or_org_policy).\
    \ CRITICAL: HMAC keys authenticate ONLY to the GCS S3-compatible XML API endpoint \u2014 NOT to the\
    \ JSON API or other Google Cloud APIs. This is storage-scoped credential creation, not full SA impersonation.\
    \ Query filters should exclude this edge from general CanImpersonate/CanExecuteAs paths unless explicitly\
    \ scoped to GCS operations."
  narrative: '{principal.name} holds storage.hmacKeys.create and can generate a long-lived HMAC key (access-key
    ID + secret) for service account {sa.name}; the returned secret grants S3-compatible access to all
    GCS buckets {sa.name} can reach via the GCS S3 API only (NOT full Google Cloud API access).'
move · open · esc close