Configure Workload Identity Federation with X.509 certificates

This guide describes how to use Workload Identity Federation with X.509 certificates that are issued by your certificate authority (CA) to authenticate to Google Cloud and access Google Cloud resources.

If your workloads possess an mTLS client certificate, you can authenticate to Google Cloud by registering one or more CAs with Workload Identity Federation as trust anchors. You can also register intermediate CAs.

By using Workload Identity Federation, you can let these workloads obtain short-lived Google Cloud credentials through a mutual TLS (mTLS) connection. Workloads can use these short-lived credentials to access Google Cloud APIs.

Concepts

The X.509 certificate-based federation concepts include the following:

  • A trust anchor is a CA certificate that is considered as the root of trust. Any client certificate chains should be chained up to one of the trust anchors.

  • An intermediate CA is an optional certificate authority certificate that helps build the client certificate chain.

  • A trust store contains the trust anchor certificates and intermediate CA certificates that are used to validate the client certificate chain. A CA issues trusted certificates for the client.

    You can upload the following types of client certificates to the trust store:

    • Certificates issued by third-party CAs of your choice
    • Certificates issued by your private CAs
    • Signed certificates, as described in Create self-signed certificates

Before you begin

To start configuring Workload Identity Federation, do the following:

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. We recommend that you use a dedicated project to manage workload identity pools and providers.
  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the IAM, Resource Manager, Service Account Credentials, and Security Token Service APIs.

    Enable the APIs

Required roles

To get the permissions that you need to configure Workload Identity Federation, ask your administrator to grant you the following IAM roles on the project:

For more information about granting roles, see Manage access.

You might also be able to get the required permissions through custom roles or other predefined roles.

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.

Configure Workload Identity Federation

This section shows you how to configure Workload Identity Federation and your trust store. You need only perform these steps once for each trust store. You can then use the same workload identity pool and provider for multiple workloads and across multiple Google Cloud projects.

Create and configure a trust store

This section shows you how to create a trust store YAML configuration file and self-signed CA certificate.

Generate a key and signed certificates

This section uses openssl commands to create root and intermediate certificates.

If you already have certificates, you can skip this step and continue with Format the certificates.

To generate a root certificate and a signed intermediate certificate with valid keyUsage and extendedKeyUsage fields, do the following:

  1. Create a sample example.cnf file with the minimum configuration required to create valid signing certificates. You can edit this file to set additional fields on these certificates.

    cat > example.cnf << EOF
    [req]
    distinguished_name = empty_distinguished_name
    [empty_distinguished_name]
    # Kept empty to allow setting via -subj command line arg.
    [ca_exts]
    basicConstraints=critical,CA:TRUE
    keyUsage=keyCertSign
    extendedKeyUsage=clientAuth
    EOF
    
  2. Create the root certificate:

    openssl req -x509 \
        -new -sha256 -newkey rsa:2048 -nodes \
        -days 3650 -subj '/CN=root' \
        -config example.cnf \
        -extensions ca_exts \
        -keyout root.key -out root.cert
    
  3. Create the signing request for the intermediate certificate:

    openssl req \
        -new -sha256 -newkey rsa:2048 -nodes \
        -subj '/CN=int' \
        -config example.cnf \
        -extensions ca_exts \
        -keyout int.key -out int.req
    
  4. Create the intermediate certificate:

    openssl x509 -req \
        -CAkey root.key -CA root.cert \
        -set_serial 1 \
        -days 3650 \
        -extfile example.cnf \
        -extensions ca_exts \
        -in int.req -out int.cert
    

Format the certificates

To include new or existing certificates in a trust store, format the certificates into a single line and store them in environment variables, so that they can be read into the YAML file. The certificates need to be PEM-formatted. To format the certificates and store them in environment variables, do the following:

  1. Save the root certificate as a one-line string:

    export ROOT_CERT=$(cat root.cert | sed 's/^[ ]*//g' | sed -z '$ s/\n$//' | tr '\n' $ | sed 's/\$/\\n/g')
    
  2. Save an intermediate certificate as a one-line string:

    export INTERMEDIATE_CERT=$(cat int.cert | sed 's/^[ ]*//g' | sed -z '$ s/\n$//' | tr '\n' $ | sed 's/\$/\\n/g')
    

Create a trust store YAML file

In this section, you create a trust store YAML file that contains your trust anchors and intermediate CAs.

To create the trust store YAML file, run the following command. This file contains the certificate content from the environment variables that you created in Format the certificates. To add additional trust anchors, add additional trustAnchors entries under trustStore. To add additional intermediate CA certificates, add additional intermediateCas entries under trustStore.

cat << EOF > trust_store.yaml
trustStore:
  trustAnchors:
  - pemCertificate: "${ROOT_CERT}"
  intermediateCas:
  - pemCertificate: "${INTERMEDIATE_CERT}"
EOF

Define an attribute mapping and condition

The client X.509 certificate can contain multiple attributes. You must select which attribute you want to use as the subject identifier by mapping google.subject in Google Cloud to the attribute from your certificate. For example, if the attribute in the certificate is the subject common name, then the mapping would be as follows: google.subject=assertion.subejct.dn.cn

Optionally, you can map additional attributes. You can then refer to these attributes when granting access to resources.

Your attribute mappings can use the attributes within the client certificate, including the following:

  • serialNumberHex: the serial number
  • subject.dn.cn: the subject common name
  • subject.dn.o: the subject organization name
  • subject.dn.ou: the subject organization unit
  • issuer.dn.cn: the issuer common name
  • issuer.dn.o: the issuer organization name
  • issuer.dn.ou: the issuer organization unit
  • san.dns: the subject alternative name's first DNS name
  • san.uri: the subject alternative name's first URI

You must map one of these attributes to google.subject to uniquely identify the subject. To protect against spoofing threats, choose an attribute with a unique value that can't be changed. By default, the google.subject identifier is set to the client certificate subject common name, assertion.subject.dn.cn.

Optional: Define an attribute condition. Attribute conditions are CEL expressions that can check assertion attributes and target attributes. If the attribute condition evaluates to true for a given credential, the credential is accepted. Otherwise, the credential is rejected.

You can use an attribute condition to restrict which subjects can use Workload Identity Federation to obtain short-lived Google Cloud tokens.

For example, the following condition restricts access to client certificates containing SPIFFE ID spiffe://example/path:

assertion.san.uri=="spiffe://example/path"

Create the workload identity pool and provider

  1. To create a new workload identity pool, execute the following command:

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    Replace the following:

    • POOL_ID: the unique ID for the pool.
    • DISPLAY_NAME: the name of the pool.
    • DESCRIPTION: a description of the pool that you choose. This description appears when you grant access to pool identities.
  2. To add an X.509 workload identity pool provider, run the following command:

    gcloud iam workload-identity-pools providers create-x509 PROVIDER_ID \
        --location=global \
        --workload-identity-pool="POOL_ID" \
        --trust-store-config-path="TRUST_STORE_CONFIG" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS" \
        --billing-project="ALLOWLISTED_PROJECT"
    

    Replace the following:

    • PROVIDER_ID: A unique workload identity pool provider ID of your choice.
    • POOL_ID: The workload identity pool ID that you created earlier.
    • TRUST_STORE_CONFIG: The trust store YAML file.
    • MAPPINGS: A comma-separated list of attribute mappings that you created earlier in this guide. If you don't specify google.subject, the default mapping will be google.subject=assertion.subject.dn.cn
    • CONDITIONS: An optional attribute condition that you created earlier in this guide. Remove the parameter if you don't have an attribute condition.
    • ALLOWLISTED_PROJECT: The project ID.

Authenticate a workload

You must perform these steps once for each workload.

Allow your external workload to access Google Cloud resources

To provide your workload with access to Google Cloud resources, we recommend that you grant direct resource access to the principal. In this case, the principal is the federated user. Some Google Cloud products have Google Cloud API limitations. If your workload calls an API endpoint that has a limitation, you can instead use service account impersonation. In this case, the principal is the Google Cloud service account, which acts as the identity. You grant access to the service account on the resource.

Direct resource access

You can grant access to a federated identity directly on resources by using the Google Cloud console or the gcloud CLI.

Console

To use the Google Cloud console to grant IAM roles directly on a resource, you must go to the resource's page, and then grant the role. The following example shows you how to go to the Cloud Storage page and grant the role Storage Object Viewer (roles/storage.objectViewer) to a federated identity directly on a Cloud Storage bucket.

  1. In the Google Cloud console, go to the Cloud Storage Buckets page.

    Go to Buckets

  2. In the list of buckets, click the name of the bucket for which you want to grant the role.

  3. Select the Permissions tab near the top of the page.

  4. Click the Grant access button.

    The Add principals dialog appears.

  5. In the New principals field, enter one or more identities that need access to your bucket.

    By subject

    principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT
    

    Replace the following:

    • PROJECT_NUMBER: the project number
    • POOL_ID: the workload pool ID
    • SUBJECT: the individual subject mapped from your IdP—for example, [email protected]

    By group

    principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/group/GROUP
    

    Replace the following:

    • PROJECT_NUMBER: the project number
    • WORKLOAD_POOL_ID: the workload pool ID
    • GROUP: the group mapped from your IdP—for example: [email protected]

    By attribute

    principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.ATTRIBUTE_NAME/ATTRIBUTE_VALUE
    

    Replace the following:

    • PROJECT_NUMBER: the project number
    • WORKLOAD_POOL_ID: the workload pool ID
    • ATTRIBUTE_NAME: one of the attributes that was mapped from your IdP
    • ATTRIBUTE_VALUE: the value of the attribute
  6. Select a role (or roles) from the Select a role drop-down menu. The roles you select appear in the pane with a short description of the permissions they grant.

  7. Click Save.

gcloud

To use the gcloud CLI to grant IAM roles on a resource in a project, do the following:

  1. Obtain the project number of the project in which the resource is defined.

    gcloud projects describe $(gcloud config get-value core/project) --format=value\(projectNumber\)
    
  2. Grant access to the resource.

    To use the gcloud CLI to grant the role Workload Identity User (roles/iam.workloadIdentityUser) to external identities that meet certain criteria, run the following command.

    By subject

    gcloud storage buckets add-iam-policy-binding BUCKET_ID \
        --role=roles/storage.objectViewer \
        --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT"

    By group

    gcloud storage buckets add-iam-policy-binding BUCKET_ID \
        --role=roles/storage.objectViewer \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/group/GROUP"

    By attribute

    gcloud storage buckets add-iam-policy-binding BUCKET_ID \
        --role=roles/storage.objectViewer \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.ATTRIBUTE_NAME/ATTRIBUTE_VALUE"

    Replace the following:

    • BUCKET_ID: the bucket on which to grant access
    • PROJECT_NUMBER: the project number. of the project that contains the workload identity pool
    • POOL_ID: the pool ID of the workload identity pool
    • SUBJECT: the expected value for the attribute that you've mapped to google.subject
    • GROUP: the expected value for the attribute that you've mapped to google.groups
    • ATTRIBUTE_NAME: the name of a custom attribute in your attribute mapping
    • ATTRIBUTE_VALUE: the value of the custom attribute in your attribute mapping

    You can grant roles on any Google Cloud resource that supports IAM allow policies.

Service account impersonation

  1. To create a service account for the external workload, do the following:

    1. Enable the IAM, Security Token Service, and Service Account Credentials APIs.

      Enable the APIs

    2. Create a service account that represents the workload. We recommend that you use a dedicated service account for each workload. The service account doesn't need to be in the same project as the workload identity pool, but you must refer to the project that contains the service account.

    3. Grant the service account access to resources that you want external identities to access.

    4. Grant the Workload Identity User role (roles/iam.workloadIdentityUser) to the service account.

  2. To grant access to a federated identity using service account impersonation by using the Google Cloud console or the gcloud CLI, do the following:

    Console

    To use the Google Cloud console to grant IAM roles to a federated identity with service account, do the following:

    1. Create a service account that serves as the identity to impersonate, by doing the following:

      1. Enable the IAM, Security Token Service, and Service Account Credentials APIs.

        Enable the APIs

      2. Create a service account that represents the identity for the workload. We recommend that you use a dedicated service account for each workload.

        The service account doesn't need to be in the same project as the workload identity pool, but when you grant IAM access, you must refer to the project that contains the service account.

      3. Grant the service account access to resources that you want external identities to access.

    2. To grant access using service account impersonation, do the following.

      1. Go to the Workload Identity Pools page.

        Go to Workload Identity Pools

      2. Select Grant access.

      3. In the Grant access to service account dialog, select Grant access using Service Account impersonation.

      4. In the Service accounts list, select the service account for the external identities to impersonate, and do the following:

      5. To choose which identities in the pool can impersonate the service account, perform one of the following actions:

        • To allow only specific identities of the workload identity pool to impersonate the service account, select Only identities matching the filter.

        • In the Attribute name list, select the attribute that you want to filter on.

        • In the Attribute value field, enter the expected value of the attribute; for example, if you use an attribute mapping google.subject=assertion.sub, set Attribute name to subject and Attribute value to the value of the sub claim in tokens that are issued by your external identity provider.

      6. To save the configuration, click Save and then Dismiss.

    gcloud

    To use the gcloud CLI to grant the role Workload Identity User (roles/iam.workloadIdentityUser) to external identities that meet certain criteria, run the following command.

    By subject

    gcloud storage buckets add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
        --role=roles/storage.objectViewer \
        --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT"

    By group

    gcloud storage buckets add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
        --role=roles/storage.objectViewer \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/group/GROUP"

    By attribute

    gcloud storage buckets add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
        --role=roles/storage.objectViewer \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.ATTRIBUTE_NAME/ATTRIBUTE_VALUE"

    Replace the following:

    • SERVICE_ACCOUNT_EMAIL: the email address of the service account
    • PROJECT_NUMBER: the project number. of the project that contains the workload identity pool
    • POOL_ID: the pool ID of the workload identity pool
    • SUBJECT: the expected value for the attribute that you've mapped to google.subject
    • GROUP: the expected value for the attribute that you've mapped to google.groups
    • ATTRIBUTE_NAME: the name of a custom attribute in your attribute mapping
    • ATTRIBUTE_VALUE: the value of the custom attribute in your attribute mapping

Obtain an access token using plain request to access Google Cloud

To obtain the access token, do the following:

  1. Use curl to perform token exchange with mTLS and the client certificate:

    curl --key CLIENT_CERT_KEY \
    --cert CLIENT_CERT \
    --request POST 'https://sts.mtls.googleapis.com/v1/token' \
    --header "Content-Type: application/json" \
    --data-raw '{
        "subject_token_type": "urn:ietf:params:oauth:token-type:mtls",
        "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
        "audience": "WORKLOAD_IDENTITY_POOL_URI",
        "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
        "scope": "https://www.googleapis.com/auth/cloud-platform",
    }'
    

    Replace the following:

    • CLIENT_CERT_KEY: the client certificate private key
    • CLIENT_CERT: the client certificate
    • WORKLOAD_IDENTITY_POOL_URI: the URL of the workload identity pool provider
  2. Use the bearer access token generated in previous step to access Google Cloud resources—for example:

    curl -X GET 'https://storage.googleapis.com/my_object' -H "Authorization: Bearer $ACCESS_TOKEN"
    

Quotas and limits

The following table lists quotas and limits.

Item Quotas and limits Notes
Number of trust anchors Limit: 2 Each certificate must not exceed 32KB.
Number of intermediate certificates Limit: 10 Each certificate shouldn't exceed 32KB.
Number of name constraints allowed during validation of root and intermediate certificates Limit: 10
Intermediate certificates that share the same Subject and Subject Public Key information Limit: 5 This limit is for each trust store.
Certificate chain depth Limit: 5 The maximum depth for a certificate chain, including the root and client certificates.
Number of times intermediate certificates can be evaluated when attempting to build the chain of trust Limit: 100
Keys of certificates uploaded and passed from the client

Limit: RSA keys can be from 2048 to 4096 bits

ECDSA certificates must use either P-256 or P-384 curves

RSA-2048 and P-256 are recommended for normal use cases, use others for best security practice

What's next