»Google Cloud Auth Method

The gcp auth method allows Google Cloud Platform entities to authenticate to Vault. Vault treats Google Cloud as a trusted third party and verifies authenticating entities against the Google Cloud APIs. This backend allows for authentication of:

  • Google Cloud IAM service accounts
  • Google Compute Engine (GCE) instances

This backend focuses on identities specific to Google Cloud and does not support authenticating arbitrary Google or G Suite users or generic OAuth against Google.

This plugin is developed in a separate GitHub repository at hashicorp/vault-plugin-auth-gcp, but is automatically bundled in Vault releases. Please file all feature requests, bugs, and pull requests specific to the GCP plugin under that repository.

»Authenticate

»Via the CLI Helper

Vault includes a CLI helper that obtains a signed JWT locally and sends the request to Vault. This helper is only available for IAM-type roles.

$ vault login -method=gcp \
    role="my-role" \
    service_account="authenticating-account@my-project.iam.gserviceaccount.com" \
    jwt_exp="15m" \
    credentials=@path/to/signer/credentials.json
$ vault login -method=gcp \    role="my-role" \    service_account="authenticating-account@my-project.iam.gserviceaccount.com" \    jwt_exp="15m" \    credentials=@path/to/signer/credentials.json

For more usage information, run vault auth help gcp.

»Via the CLI

$ vault write -field=token auth/gcp/login \
    role="my-role" \
    jwt="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
$ vault write -field=token auth/gcp/login \    role="my-role" \    jwt="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

See Generating JWTs for ways to obtain the JWT token.

»Via the API

$ curl \
    --request POST \
    --data '{"role":"my-role", "jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}' \
    http://127.0.0.1:8200/v1/auth/gcp/login
$ curl \    --request POST \    --data '{"role":"my-role", "jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}' \    http://127.0.0.1:8200/v1/auth/gcp/login

See API docs for expected response.

»Configuration

Auth methods must be configured in advance before users or machines can authenticate. These steps are usually completed by an operator or configuration management tool.

  1. Enable the Google Cloud auth method:

    $ vault auth enable gcp
    
    $ vault auth enable gcp
  2. Configure the auth method credentials:

    $ vault write auth/gcp/config \
        credentials=@/path/to/credentials.json
    
    $ vault write auth/gcp/config \    credentials=@/path/to/credentials.json

    If you are using instance credentials or want to specify credentials via an environment variable, you can skip this step. To learn more, see the Google Cloud Authentication section below.

  3. Create a named role:

    For an iam-type role:

    $ vault write auth/gcp/role/my-iam-role \
        type="iam" \
        policies="dev,prod" \
        bound_service_accounts="my-service@my-project.iam.gserviceaccount.com"
    
    $ vault write auth/gcp/role/my-iam-role \    type="iam" \    policies="dev,prod" \    bound_service_accounts="my-service@my-project.iam.gserviceaccount.com"

    For a gce-type role:

    $ vault write auth/gcp/role/my-gce-role \
        type="gce" \
        policies="dev,prod" \
        bound_projects="my-project1,my-project2" \
        bound_zones="us-east1-b" \
        bound_labels="foo:bar,zip:zap" \
        bound_service_accounts="my-service@my-project.iam.gserviceaccount.com"
    
    $ vault write auth/gcp/role/my-gce-role \    type="gce" \    policies="dev,prod" \    bound_projects="my-project1,my-project2" \    bound_zones="us-east1-b" \    bound_labels="foo:bar,zip:zap" \    bound_service_accounts="my-service@my-project.iam.gserviceaccount.com"

    Note that bound_service_accounts is only required for iam-type roles.

    For the complete list of configuration options for each type, please see the API documentation.

»Authentication

The Google Cloud Vault auth method uses the official Google Cloud Golang SDK. This means it supports the common ways of providing credentials to Google Cloud.

  1. The environment variable GOOGLE_APPLICATION_CREDENTIALS. This is specified as the path to a Google Cloud credentials file, typically for a service account. If this environment variable is present, the resulting credentials are used. If the credentials are invalid, an error is returned.

  2. Default instance credentials. When no environment variable is present, the default service account credentials are used.

For more information on service accounts, please see the Google Cloud Service Accounts documentation.

To use this auth method, the service account must have the following minimum scope:

https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/cloud-platform

»Required GCP Permissions

»Vault Server Permissions

For iam-type Vault roles, Vault can be given the following roles:

roles/iam.serviceAccountKeyAdmin
roles/iam.serviceAccountKeyAdmin

For gce-type Vault roles, Vault can be given the following roles:

roles/compute.viewer
roles/compute.viewer

If you instead wish to create a custom role with only the exact GCP permissions required, use the following list of permissions:

iam.serviceAccounts.get
iam.serviceAccountKeys.get
compute.instances.get
compute.instanceGroups.list
iam.serviceAccounts.getiam.serviceAccountKeys.getcompute.instances.getcompute.instanceGroups.list

These allow Vault to:

  • verify the service account, either directly authenticating or associated with authenticating GCE instance, exists
  • get the corresponding public keys for verifying JWTs signed by service account private keys.
  • verify authenticating GCE instances exist
  • compare bound fields for GCE roles (zone/region, labels, or membership in given instance groups)

If you are using Group Aliases as described below, you will also need to add the resourcemanager.projects.get permission.

»Permissions For Authenticating Against Vault

Note that the previously mentioned permissions are given to the Vault servers. The IAM service account or GCE instance that is authenticating against Vault must have the following role:

roles/iam.serviceAccountTokenCreator
roles/iam.serviceAccountTokenCreator

»Group Aliases

As of Vault 1.0, roles can specify an add_group_aliases boolean parameter that adds group aliases to the auth response. These aliases can aid in building reusable policies since they are available as interpolated values in Vault's policy engine. Once enabled, the auth response will include the following aliases:

[
  "project-$PROJECT_ID",
  "folder-$SUBFOLDER_ID",
  "folder-$FOLDER_ID",
  "organization-$ORG_ID"
]
[  "project-$PROJECT_ID",  "folder-$SUBFOLDER_ID",  "folder-$FOLDER_ID",  "organization-$ORG_ID"]

If you are using a custom role for Vault server, you will need to add the resourcemanager.projects.get permission to your custom role.

»Implementation Details

This section describes the implementation details for how Vault communicates with Google Cloud to authenticate and authorize JWT tokens. This information is provided for those who are curious, but these details are not required knowledge for using the auth method.

»IAM Login

IAM login applies only to roles of type iam. The Vault authentication workflow for IAM service accounts looks like this:

Vault Google Cloud IAM Login Workflow

  1. The client generates a signed JWT using the Service Account Credentials projects.serviceAccounts.signJwt API method. For examples of how to do this, see the Generating JWTs section.

  2. The client sends this signed JWT to Vault along with a role name.

  3. Vault extracts the kid header value, which contains the ID of the key-pair used to generate the JWT, and the sub ID/email to find the service account key. If the service account does not exist or the key is not linked to the service account, Vault denies authentication.

  4. Vault authorizes the confirmed service account against the given role. If that is successful, a Vault token with the proper policies is returned.

»GCE Login

GCE login only applies to roles of type gce and must be completed on an instance running in GCE. These steps will not work from your local laptop or another cloud provider.

Vault Google Cloud GCE Login Workflow

  1. The client obtains an instance identity metadata token on a GCE instance.

  2. The client sends this JWT to Vault along with a role name.

  3. Vault extracts the kid header value, which contains the ID of the key-pair used to generate the JWT, to find the OAuth2 public cert to verify this JWT.

  4. Vault authorizes the confirmed instance against the given role, ensuring the instance matches the bound zones, regions, or instance groups. If that is successful, a Vault token with the proper policies is returned.

»Generating JWTs

This section details the various methods and examples for obtaining JWT tokens.

»Service Account Credentials API

This describes how to use the GCP Service Account Credentials API method directly to generate the signed JWT with the claims that Vault expects. Note the CLI does this process for you and is much easier, and that there is very little reason to do this yourself.

»curl Example

Vault requires the following minimum claim set:

{
  "sub": "$SERVICE_ACCOUNT_EMAIL_OR_ID",
  "aud": "vault/$ROLE",
  "exp": "$EXPIRATION"
}
{  "sub": "$SERVICE_ACCOUNT_EMAIL_OR_ID",  "aud": "vault/$ROLE",  "exp": "$EXPIRATION"}

For the API method, providing the expiration claim exp is required. If it is omitted, it will not be added automatically and Vault will deny authentication. Expiration must be specified as a NumericDate value (seconds from Epoch). This value must be before the max JWT expiration allowed for a role. This defaults to 15 minutes and cannot be more than 1 hour.

One you have all this information, the JWT token can be signed using curl and oauth2l:

ROLE="my-role"
SERVICE_ACCOUNT="service-account@my-project.iam.gserviceaccount.com"
OAUTH_TOKEN="$(oauth2l header cloud-platform)"
EXPIRATION="<your_token_expiration>"
JWT_CLAIM="{\\\"aud\\\":\\\"vault/${ROLE}\\\", \\\"sub\\\": \\\"${SERVICE_ACCOUNT}\\\", \\\"exp\\\": ${EXPIRATION}}"

curl \
  --header "${OAUTH_TOKEN}" \
  --header "Content-Type: application/json" \
  --request POST \
  --data "{\"payload\": \"${JWT_CLAIM}\"}" \
  "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${SERVICE_ACCOUNT}:signJwt"
ROLE="my-role"SERVICE_ACCOUNT="service-account@my-project.iam.gserviceaccount.com"OAUTH_TOKEN="$(oauth2l header cloud-platform)"EXPIRATION="<your_token_expiration>"JWT_CLAIM="{\\\"aud\\\":\\\"vault/${ROLE}\\\", \\\"sub\\\": \\\"${SERVICE_ACCOUNT}\\\", \\\"exp\\\": ${EXPIRATION}}"
curl \  --header "${OAUTH_TOKEN}" \  --header "Content-Type: application/json" \  --request POST \  --data "{\"payload\": \"${JWT_CLAIM}\"}" \  "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${SERVICE_ACCOUNT}:signJwt"

»gcloud Example

You can also do this through the (currently beta) gcloud command. Note that you will be required to provide the expiration claim exp as a part of the JWT input to the command.

$ gcloud beta iam service-accounts sign-jwt $INPUT_JWT_CLAIMS $OUTPUT_JWT_FILE \
    --iam-account=service-account@my-project.iam.gserviceaccount.com \
    --project=my-project
$ gcloud beta iam service-accounts sign-jwt $INPUT_JWT_CLAIMS $OUTPUT_JWT_FILE \    --iam-account=service-account@my-project.iam.gserviceaccount.com \    --project=my-project

»Golang Example

Read more on the Google Open Source blog.

»GCE

GCE tokens can only be generated from a GCE instance. The JWT token can be obtained from the service-accounts/default/identity endpoint for a instance's metadata server.

»curl Example

ROLE="my-gce-role"

curl \
  --header "Metadata-Flavor: Google" \
  --get \
  --data-urlencode "audience=http://vault/${ROLE}" \
  --data-urlencode "format=full" \
  "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity"
ROLE="my-gce-role"
curl \  --header "Metadata-Flavor: Google" \  --get \  --data-urlencode "audience=http://vault/${ROLE}" \  --data-urlencode "format=full" \  "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity"

»API

The GCP Auth Plugin has a full HTTP API. Please see the API docs for more details.