This document shows you how to use identity federation to access Google Cloud resources from Microsoft Azure.
Traditionally, applications running outside Google Cloud have used service account keys to access Google Cloud resources. Using identity federation, you can let a managed identity for an Azure resource impersonate a service account. This lets your workload access Google Cloud resources directly, using a short-lived access token, and eliminates the maintenance and security burden associated with service account keys.
Before you begin
Enable the IAM, Resource Manager, Service Account Credentials, and Security Token Service (STS) APIs.
Ensure you have the Workload Identity Pool Admin role (
roles/iam.workloadIdentityPoolAdmin
).Alternatively, the IAM Owner (
roles/owner
) basic role also includes permissions to configure identity federation. You should not grant basic roles in a production environment, but you can grant them in a development or test environment.Update the organization policy for your organization to allow federation from Azure.
Grant the service account access to call the Google Cloud APIs required by your workload.
Creating a workload identity pool
You can use a workload identity pool to organize and manage external identities. Workload identity pools are isolated from each other, but a single pool can impersonate any number of service accounts. In general, we recommend creating a new pool for each of your environments, such as development, staging, or production.
To create a new workload identity pool, you'll need to provide an ID. You
can also provide an optional description and display name. The ID cannot
begin with gcp-
; this prefix is reserved for use by Google.
gcloud
Execute the gcloud iam workload-identity-pools create
command to create a
workload identity pool:
gcloud iam workload-identity-pools create pool-id \ --location="global" \ --description="description" \ --display-name="display-name"
The response looks like:
Created workload identity pool [pool-id].
REST
The
projects.locations.workloadIdentityPools.create
method creates a workload identity pool.
HTTP method and URL:
POST https://iam.googleapis.com/v1/projects/project-id/locations/global/workloadIdentityPools?workloadIdentityPoolId=pool-id
Request JSON body:
{ "description": "description", "display-name": "display-name" }
To send your request, expand one of these options:
The method returns a long-running
Operation
similar to the following:
{ "name": "projects/project-number/locations/global/workloadIdentityPools/pool-id/operations/operation-id" }
Adding Azure as an identity provider
To configure Azure as an identity provider for your workload identity pool, supply at least the following:
An ID for the provider.
The workload identity pool ID from the previous section in this document.
Your Azure Tenant ID.
A list of attribute mappings that map the claims on a token for an Azure-managed identity to the attributes on a Google token. Use
assertion
to refer to the Azure token,google
for Google attributes, andattribute
for custom attributes.There are two Google attributes:
google.subject
andgoogle.groups
. You can reference these attributes in IAM role bindings.google.subject
also appears in Cloud Logging log entries.You must provide a mapping for
google.subject
. In general, we recommend mapping it toassertion.sub
, which contains the object ID of a managed identity that you'll create in the next section. This provides a stable identifier for use in IAM role bindings. The mapping looks like this:google.subject=assertion.sub
For more complex assertions, you can use the Common Expression Language. For example, if your workload identity pool contains multiple identity providers, you can append a prefix to disambiguate between them:
google.subject="azure::" + assertion.tid + "::" + assertion.sub
The
google.subject
field cannot exceed 127 characters.You can also specify custom attributes. For example, the following maps
assertion.tid
toattribute.tid
:attribute.tid=assertion.tid
The following example assigns a display name based on the value of
assertion.oid
:attribute.managed_identity_name={ "8bb39bdb-1cc5-4447-b7db-a19e920eb111":"workload1", "55d36609-9bcf-48e0-a366-a3cf19027d2a":"workload2" }[assertion.oid]
To obtain a complete list of claims you can reference, get an access token for an Azure VM in your workload. In your request, replace the
resource
parameter with the full resource name of your workload identity pool.For example:
curl
curl -s \ 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id&object_id=managed-identity-object-id' \ -H Metadata:true -H "Cache-Control: no-cache"
PowerShell
Invoke-WebRequest \ -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id&object_id=managed-identity-object-id' \ -Headers @{Metadata="true"}
The response is a JSON object with an
access_token
field, which contains an access token for the Azure VM. To decode the access token and view the available claims, follow these steps:- Copy the entire access token.
- In a web browser, go to https://jwt.ms/.
- Paste the access token into the text box.
- Click Claims.
To refer to a specific part of a claim in an expression, use the CEL
extract()
function, which extracts a value from a claim based on a template you provide. To learn more aboutextract()
, see Extracting values from attributes.To check if a credential contains an claim, use the
has()
function.
You can also provide several optional parameters:
A display name and description.
A condition specifying attributes that the principal must present. The condition can apply to claims on the Azure credential, or attributes on the Google credential. Any request that does not meet the condition is rejected.
Conditions are formatted as a CEL expression that returns a boolean. For example, the following rejects requests from any identity that isn't a member of a specific group:
"e968c2ef-047c-498d-8d79-16ca1b61e77e" in assertion.groups
To learn more about common use cases for conditions, see the workload identity federation overview.
The following example demonstrates adding Azure as an identity provider:
gcloud
Execute the gcloud iam workload-identity-pools providers create-oidc
command to add Azure as an identity provider:
gcloud iam workload-identity-pools providers create-oidc provider-id \ --workload-identity-pool="pool-id" \ --issuer-uri="https://sts.windows.net/azure-tenant-id" \ --location="global" \ --attribute-mapping="google.subject=assertion.sub"
The response looks like:
Created workload identity pool provider [provider-id].
REST
The
projects.locations.workloadIdentityPools.providers.create
method adds Azure as a provider.
HTTP method and URL:
POST https://iam.googleapis.com/v1/projects/project-id/locations/global/workloadIdentityPools/pool-id/providers?workloadIdentityPoolProviderId=provider-id
Request JSON body:
{ "attributeMapping": { "google.subject": "assertion.sub" }, "oidc": { "issuerUri": "https://sts.windows.net/azure-tenant-id" } }
To send your request, expand one of these options:
The method returns a long-running
Operation
similar to the following:
{ "name": "projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id/operations/operation-id" }
Configuring your Azure tenant for identity federation
To prepare your Azure tenant for identity federation:
Create an Azure AD application and service principal, and set its Application ID URI to the full resource name of the provider you created in the previous section:
https://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id
Create a managed identity, and take note of its object ID.
Assign the managed identity to a virtual machine that you want to grant access to Google Cloud resources.
Giving permission to impersonate a service account
External identities can't access most Google Cloud resources directly.
Instead, you let the identities impersonate a service account by granting them
the Workload Identity User role (roles/iam.workloadIdentityUser
).
To add this role binding for a specific managed identity:
gcloud iam service-accounts add-iam-policy-binding service-account-email \ --role roles/iam.workloadIdentityUser \ --member "principal://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/subject/managed-identity-object-id"
To add this binding for all identities in a pool:
gcloud iam service-accounts add-iam-policy-binding service-account-email \ --role roles/iam.workloadIdentityUser \ --member "principalSet://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/group/azure-tenant-id"
You can also grant access based on custom attributes. For example:
gcloud iam service-accounts add-iam-policy-binding service-account-email \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/attribute.custom-attribute-name/custom-attribute-value"
To revoke access, replace add-iam-policy-binding
with
remove-iam-policy-binding
.
You can also add or revoke bindings using the REST API or client libraries. To learn more, see Granting, changing, and revoking access to resources.
Generating Google credentials
If you use a supported client library, you can configure the client library so that it generates Google credentials automatically. Alternatively, you can generate Azure credentials manually, then exchange them for Google credentials.
When possible, we recommend that you generate credentials automatically, so that you do not need to implement the token-exchange process yourself.
Automatically generating credentials
If you access Google Cloud with a client library for one of the following languages, you can configure the client library to automatically generate credentials by using identity federation:
C++
Most of the
Google Cloud Client Libraries for C++
support identity federation by using a ChannelCredentials
object, which is
created by calling grpc::GoogleDefaultCredentials()
. To initialize this
credential, you must build the client libraries with version 1.36.0 or later of
gRPC.
The Cloud Storage Client Library for C++ uses the REST API, not gRPC, so it does not support identity federation.
Go
Client libraries for Go support identity federation if they use version
v0.0.0-20210218202405-ba52d332ba99 or later of the golang.org/x/oauth2
module.
To check which version of this module your client library uses, run the following commands:
cd $GOPATH/src/cloud.google.com/go
go list -m golang.org/x/oauth2
Java
Client libraries for Java support identity federation if they use version 0.24.0
or later of the
com.google.auth:google-auth-library-oauth2-http
artifact.
To check which version of this artifact your client library uses, run the following Maven command in your application directory:
mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http
Node.js
Client libraries for Node.js support identity federation if they use version
7.0.2 or later of the
google-auth-library
package.
To check which version of this package your client library uses, run the following command in your application directory:
npm list google-auth-library
When you create a GoogleAuth
object, you can specify a project ID, or you can
allow GoogleAuth
to find the project ID automatically. To find the project ID
automatically, the service account in the configuration file must have the
Browser role (roles/browser
), or a role with equivalent permissions, on your
project. For details, see the
README
for the google-auth-library
package.
Python
Client libraries for Python support identity federation if they use version
1.27.0 or later of the
google-auth
package.
To check which version of this package your client library uses, run the following command in the environment where the package is installed:
pip show google-auth
To specify a project ID for the authentication client, you can set the
GOOGLE_CLOUD_PROJECT
environment variable, or you can allow the client to find
the project ID automatically. To find the project ID automatically, the service
account in the configuration file must have the Browser role (roles/browser
),
or a role with equivalent permissions, on your project. For details, see the
user guide for the google-auth
package.
To configure the client library to generate credentials automatically, run the
gcloud iam workload-identity-pools create-cred-config
command to generate a JSON configuration file:
gcloud iam workload-identity-pools create-cred-config \ projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id \ --service-account=service-account-email \ --output-file=filepath \ --azure
Replace the following values:
project-number
: The numeric ID for the project.pool-id
: The ID for the workload identity pool.provider-id
: The ID for the workload identity pool provider.service-account-email
: The email address of the service account to impersonate.filepath
: The filepath for the configuration file.
After you generate the configuration file, set the environment variable
GOOGLE_APPLICATION_CREDENTIALS
to the filepath for the configuration file.
This environment variable tells the client library to use Application Default
Credentials to authenticate. For details, see
Finding credentials automatically.
Manually exchanging credentials
Once your Azure-managed identity has the ability to impersonate a service account, you can manually exchange its credentials for Google credentials.
To exchange credentials:
Use the Azure Instance Metadata Service (IMDS) to obtain an Azure access token.
Set the
resource
query parameter to the following value:https://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id
Set the
object_id
query parameter to the object ID for the managed identity that you created earlier.Pass the Azure access token to the Security Token Service
token()
method to get a federated access token:REST
The
token
method exchanges a third-party token for a Google token.Before using any of the request data below, make the following replacements:
-
project-number
: Your Google Cloud project number. -
pool-id
: The ID of the workload identity pool you created earlier in this tutorial. -
provider-id
: The ID of the identity provider you configured earlier in this tutorial.
HTTP method and URL:
POST https://sts.googleapis.com/v1/token
Request JSON body:
{ "audience": "//iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id", "grantType": "urn:ietf:params:oauth:grant-type:token-exchange", "requestedTokenType": "urn:ietf:params:oauth:token-type:access_token", "scope": "https://www.googleapis.com/auth/cloud-platform", "subjectTokenType": "urn:ietf:params:oauth:token-type:jwt", "subjectToken": "azure-id-token" }
To send your request, expand one of these options:
The method returns a federated token.
-
Call
generateAccessToken()
to exchange the federated token for a service account access token. A limited number of Google Cloud APIs support federated tokens; all Google Cloud APIs support service account access tokens.REST
The Service Account Credentials API's
serviceAccounts.generateAccessToken
method generates an OAuth 2.0 access token for a service account.Before using any of the request data below, make the following replacements:
PROJECT_ID
: Your Google Cloud project ID. Project IDs are alphanumeric strings, likemy-project
.SA_ID
: The ID of your service account. This can either be the service account's email address in the formSA_NAME@PROJECT_ID.iam.gserviceaccount.com
, or the service account's unique numeric ID.token
: The federated access token.
HTTP method and URL:
POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com:generateAccessToken
Request JSON body:
{ "scope": [ "https://www.googleapis.com/auth/cloud-platform" ] }
To send your request, expand one of these options:
If the
generateAccessToken
request was successful, the response body contains an OAuth 2.0 access token and an expiration time. TheaccessToken
can then be used to authenticate a request on behalf of the service account until theexpireTime
has been reached:{ "accessToken": "eyJ0eXAi...NiJ9", "expireTime": "2020-04-07T15:01:23.045123456Z" }
Once you have an access token for a service account, you can use it to call
Google Cloud APIs by including the token in the Authorization
header of
your requests:
Authorization: Bearer service-account-access-token
The request is authorized as the service account.
What's next
Use identity federation to access resources from AWS or access resources from an OIDC provider.