Skip to content

GCP: Support service account impersonation (keyless auth from Workload Identity Federation / external_account sources) #3004

Description

@wandering-walnut

Support GCP service account impersonation (keyless auth from Workload Identity Federation)

Description

The GCP module resolves credentials with Application Default Credentials and hands the result straight to the Google API clients. That supports two auth methods today: a JSON key file via GOOGLE_APPLICATION_CREDENTIALS, or the GCE/host default service account.

There's no way to run keylessly from a federated identity. If ADC resolves to a Workload Identity Federation source (an external_account credential), the client build fails:

source credential of type external_account is not supported

I'd like to add a third option: impersonation. Cartography uses whatever ADC it resolves (JSON key, GCE default, or a keyless external_account source) as a source identity, and mints short-lived impersonated credentials for a target service account that holds the read roles.

Two flags following the existing --gcp-* convention:

  • --gcp-impersonate-service-account <email> - target SA to impersonate. When set, the resolved ADC is wrapped with google.auth.impersonated_credentials.Credentials before any client is built. That class accepts an external_account source, which is what makes the keyless case work.
  • --gcp-impersonate-delegates <sa-a,sa-b> - optional comma-separated delegation chain for multi-hop impersonation, ignored unless the target SA is set.

With neither flag set, nothing changes for existing key/GCE users.

On IAM: the source identity needs roles/iam.serviceAccountTokenCreator on the target SA (and each delegate needs it on the next principal in a chain). The target SA keeps the read roles already documented in the config guide (roles/iam.securityReviewer, roles/resourcemanager.organizationViewer, and so on).

One clarification, since it comes up: this is separate from the existing WIF support, which enumerates GCPWorkloadIdentityPool / GCPWorkloadIdentityProvider resources into the graph. That models WIF; this authenticates using a WIF source identity.

Motivation

Exported JSON service-account keys are long-lived static credentials, and WIF plus impersonation lets you drop them entirely - useful when running Cartography from CI or across a trust boundary. Impersonating a target SA from a federated source is the pattern GCP recommends for this, and it's what other tools in the space do (Prowler, for example, builds the impersonated credential in-SDK rather than passing the raw external_account source to the client).

The change is contained: it sits at the one credential-resolution entrypoint (cartography/intel/gcp/clients.py::get_gcp_credentials), so every downstream client picks it up without per-module changes, and the no-flag path is untouched.

Alternatives Considered

  • Exchanging the federated token for an SA access token out-of-band (e.g. via gcloud) before running Cartography. Pushes token refresh/expiry handling onto the operator and doesn't sit well with long-running syncs.
  • Patching client construction to accept the raw external_account source. The Google clients don't support that by design; impersonation is the supported bridge and gives short-lived, auditable tokens.
  • Impersonating automatically when a target is discoverable. Impersonation changes the effective identity and the required IAM, so it should be explicit.

Relevant Links


I have a working branch for this with unit tests and updated docs, and can open a PR. Wanted to check the flag naming and approach here first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions