Introduction
When configuring the Vault GCP Auth method with Workload Identity Federation (WIF), authentication fails even if the service account has the correct IAM roles. Errors appear as 403 Permission denied responses from the GCP IAM API.
This Knowledge Base article explains the root cause — a mismatch between the namespace name and the namespace ID used in Vault’s JWT claims — and provides guidance on how to correctly configure IAM bindings to resolve the issue.
Problem
During authentication with the GCP auth method, Vault may return errors related to service account impersonation or permission denied despite the service account having the roles/iam.serviceAccountTokenCreator role.
This issue has been reproduced following the official Vault GCP WIF Auth documentation
Example Errors
When attempting to authenticate with Vault using the GCP auth method, below are the Error outputs:
$ vault login -method=gcp role=<ROLE_NAME>
Error authenticating: Error making API request.
Namespace: <NAMESPACE>
URL: PUT https://<VAULT_ADDRESS>/v1/auth/gcp/login
Code: 400. Errors:
* 1 error occurred:
* error running lookahead function for mfa: could not find service account 'projects/-/serviceAccounts/<UNIQUE_ID>': Get "https://iam.googleapis.com/v1/projects/-/serviceAccounts/<UNIQUE_ID>?alt=json&prettyPrint=false": oauth2/google: status code 403: {
"error": {
"code": 403,
"message": "Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it does not exist).",
"status": "PERMISSION_DENIED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "IAM_PERMISSION_DENIED",
"domain": "iam.googleapis.com",
"metadata": {
"permission": "iam.serviceAccounts.getAccessToken"
}
}
]
}
}
In some cases, Vault may also report an error when trying to generate an access token via the IAM Credentials API:
Code: 400. Errors:
* 1 error occurred:
* error running lookahead function for mfa: could not find service account 'projects/-/serviceAccounts/<UNIQUE_ID>': Get "https://iam.googleapis.com/v1/projects/-/serviceAccounts/<UNIQUE_ID>?alt=json&prettyPrint=false": oauth2/google: unable to generate access token: Post "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/<SERVICE_ACCOUNT_EMAIL>:generateAccessToken": context canceled
Cause
Vault’s plugin-generated JWT include the namespace ID as part of the principal identity. Documentation previously referred to “namespace” without clarifying whether this meant the namespace name or the namespace ID.
If the IAM policy binding is created with the namespace name, the principal in the JWT does not match the IAM binding. GCP IAM requires the namespace ID, and without it the impersonation request fails with a 403 PERMISSION_DENIED error.
⚠️ Note: A PERMISSION_DENIED error can have multiple root causes (for example, missing IAM roles or incorrect identity pool bindings). This namespace ID mismatch is just one possible cause.
Overview of possible solutions (if applicable)
When creating IAM policy bindings for Workload Identity Federation:
-
Retrieve the namespace ID (not the namespace name) from Vault:
vault namespace list -detailedExample output:
Path ID ------ ----------------------- example/ 123e4567-e89b-12d3-a456-426614174000Here,
exampleis the namespace name, but123e4567-e89b-12d3-a456-426614174000is the namespace ID. -
Use the namespace ID in your IAM principal binding. For example:
gcloud iam service-accounts add-iam-policy-binding \ --role=roles/iam.serviceAccountTokenCreator \ --member="principal://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<POOL_NAME>/subject/plugin-identity:<NAMESPACE_ID>:auth:<MOUNT_ACCESSOR>" \ <SERVICE_ACCOUNT_EMAIL> -
Verify that the IAM binding has been applied correctly:
gcloud iam service-accounts get-iam-policy <SERVICE_ACCOUNT_EMAIL> -
Retry authentication with Vault:
vault login -method=gcp role=<ROLE_NAME>
Outcome
-
If configured correctly, Vault should be able to impersonate the target service account without returning 403 errors.
-
You can also manually validate impersonation using the IAM Credentials API:
curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json" \ -d '{"scope":["https://www.googleapis.com/auth/cloud-platform"],"lifetime":"3600s"}' \ "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/<SERVICE_ACCOUNT_EMAIL>:generateAccessToken"
Additional Information
-
This issue stemmed from unclear documentation. A documentation PR has been filed to clarify that the namespace ID (not name) must be used.