Issue certificates that attest to third-party identity
This tutorial demonstrates how you can issue certificates that attest to a third-party identity using identity reflection and workload identity pools.
You can use identity reflection to create certificates that match the verified identity of a certificate requester. Using identity reflection, you can limit an unprivileged certificate requester to requesting only certificates with a subject alternative name (SAN) corresponding to the identity in their credential.
Objectives
This tutorial provides information about how you can use CA Service with workload identity pools to federate a third-party identity and obtain a certificate that attests to this identity.
Before you begin
Before you begin, make sure that you understand the following concepts:
- Workload identity pools: Workload identity pools let you manage third-party identity providers. For more information, see Manage workload identity pools and providers.
- Workload identity federation: Workload identity federation leverages workload identity pools to give third-party identities access to Google Cloud services. For more information, see Workload identity federation.
- Security Token Service (STS): The Security Token Service lets you exchange third-party credentials for first-party (Google Cloud) tokens. For more information, see Security Token Service.
- Identity reflection: The identity reflection feature lets the verified identity of a certificate requester go on to the requested certificate. For more information, see Identity reflection.
Make sure that you have the following IAM roles:
- To manage certificate authorities (CAs) and CA pools, and request
certificates, you must have the CA Service Operation Manager
(
privateca.caManager
) role. For more information about IAM roles for CA Service, see Access control with IAM. - To manage workload identity pools and providers, you must have the
Workload Identity Pool Admin (
iam.workloadIdentityPoolAdmin
) role. - To create a service account, you must have the Service Account Admin
(
iam.serviceAccountAdmin
) role.
For information about granting IAM roles, see Manage access to projects, folders, and organizations. You can grant the required IAM roles to a Google Account, a service account, a Google group, a Google Workspace account, or a Cloud Identity domain.
Set up a workload identity pool and provider
This tutorial explains how you can use a Google OpenID Connect (OIDC) provider combined with a service account to act as a third-party identity. The Google Accounts OIDC provider acts as a third-party identity provider (IDP) and the Google Cloud service account is a sample third-party identity asserted by this IDP.
Workload identity pools support a variety of identity providers, including Microsoft Azure/On-premises Active Directory, AWS, and SAML-based identity providers.
To set up a workload identity pool and provider, do the following: 1. To represent a trusted set of federated identities, create a workload identity pool:
```
gcloud iam workload-identity-pools create IDENTITY_POOL_ID --location global --display-name "tutorial-wip"
```
Replace the following:
- <var>IDENTITY_POOL_ID</var>: The unique identifier of the new workload
identity pool.
Create a workload identity pool provider for your third-party identity provider:
gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID --location global --workload-identity-pool IDENTITY_POOL_ID --display-name "tutorial-oidc" --attribute-mapping "google.subject=assertion.sub" --issuer-uri="https://accounts.google.com"
Replace the following:
- PROVIDER_ID: The unique identifier of the identity provider that you want to create in the workload identity pool.
You can customize the following flags to your use case:
attribute-mapping
: This flag sets the mapping between the third-party claims to the Google principal claim,google.subject
.google.subject
is a required mapping that you can set to any claims or combination of claims using a CEL expression. For more information, see Define an attribute mapping and condition.issuer-uri
: For OIDC providers, this flag is a publicly accessible endpoint that Google reaches out to for verification of third-party tokens. For more information, see Preparing an external identity provider.
For more information about setting up a workload identity provider, see Configuring workload identity federation.
Create a CA pool and an issuing CA
This section explains how you can create a CA pool and add a root CA to it. You can use this CA pool to issue identity-reflected certificates. If you want to use an existing CA pool and CA, you can skip this section.
Instead of a root CA, you can also choose to create a subordinate CA. Creating a root CA helps shorten the procedure.
Create a CA pool in the DevOps tier:
gcloud privateca pools create CA_POOL_ID --location LOCATION --tier devops
Replace the following:
- CA_POOL_ID - The ID of the CA Service CA pool that issues certificates.
- LOCATION - The location of the CA pool.
For more information about creating CA pools, see Create a CA pool.
Create a root CA:
gcloud privateca roots create CA_ID --pool CA_POOL_ID --location LOCATION --subject "CN=test,O=test-org"
Replace the following:
- CA_ID - The ID of certificate authority that issues certificates.
- CA_POOL_ID - The ID of the CA Service CA pool that issues certificates.
- LOCATION - The location of the CA pool.
For more information about creating a root CA, see Create a root CA.
Enable identities federated from the workload identity pool to issue certificates from the CA Pool. Identity reflection requires the CA Service Workload Certificate Requester (
roles/privateca.workloadCertificateRequester
) IAM role for the requesters ofCreateCertificate
.You can represent workload identity pool principals in various granularities, ranging from a single subject to all identities in the pool across providers. For more information, see the principals or principal sets that are available (use the Google Cloud CLI tab) to best suit your use case.
gcloud privateca pools add-iam-policy-binding CA_POOL_ID --location LOCATION --role roles/privateca.workloadCertificateRequester --member "principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/*"
Replace the following:
- PROJECT_NUMBER - The project number of the project in which you created the workload identity pool.
Create a service account that represents a third-party identity
The following procedure assumes that a service account represents a
third-party. This section shows how you can use the
GenerateIdToken
IAM endpoint to retrieve a third-party identity in the form of
an OIDC token. Depending on your use case, you might need different steps to
obtain the third-party identity token of your choosing.
gcloud iam service-accounts create SERVICE_ACCOUNT
Replace the following:
- SERVICE_ACCOUNT - The ID of the service account that represents the third-party identity.
Issue a certificate attesting to a third-party identity
Before you begin, make sure that you have the Service Account Token Creator
(roles/iam.serviceAccountTokenCreator
) IAM role. You need this
IAM role to call the GenerateIdToken
API.
To obtain a certificate that attests to a third-party identity, do the following:
Obtain a third-party identity token from your third-party identity provider.
curl
export ID_TOKEN=`curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json;print(json.load(sys.stdin)['token'])"`
Replace the following:
- PROJECT_ID - The Google Cloud project id for the project you want to create resources in.
Client libraries
To access the third-party token programmatically, you can obtain a token from a file-sourced credential or a url-sourced credential. For more information, see Authenticating by using client libraries, the gcloud CLI, or Terraform. In this tutorial, we follow a file-source credential workflow.
Load your credential into a path readable by your certificate requester:
curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json; print(json.load(sys.stdin)['token']) > /tmp/oidc_token.txt
Replace the following:
- PROJECT_ID: The project ID of the project you want to create resources in.
Exchange your third-party token for a federated OAuth token using the STS
token
endpoint:curl
export STS_TOKEN=`curl -L -X POST 'https://sts.googleapis.com/v1/token' -H 'Content-Type: application/json' \ -d '{ "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID", "requested_token_type": "urn:ietf:params:oauth:token-type:access_token", "scope": "https://www.googleapis.com/auth/cloud-platform", "subject_token": "'$ID_TOKEN'", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt" }' | python3 -c "import sys;import json; print(json.load(sys.stdin)['access_token'])"`
Client libraries
- Create a credential
configuration file named
oidc_token.txt
that the certificate requesting code can read to perform a token exchange.
gcloud iam workload-identity-pools create-cred-config projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID --output-file=/tmp/cred_config.json --credential-source-file=/tmp/oidc_token.txt
- Read the
oidc_token.txt
file to set the authorization mechanism in the client library:
python
import json from google.auth import identity_pool with open('/tmp/cred_config.json', 'r') as f: json_config_info = json.loads(f.read()) credentials = identity_pool.Credentials.from_info(json_config_info) scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/cloud-platform'])
- Create a credential
configuration file named
Make a request to CA Service with the
REFLECTED_SPIFFE
subject request mode:curl
Optional: If you don't have a CSR, create a CSR by executing the following command.
export TUTORIAL_CSR=$(openssl req -newkey rsa:2048 -nodes -subj / -keyout tutorial_do_not_use.key)
Request a certificate with the CSR, a lifetime, and a reflected subject request mode:
curl -H "Authorization: Bearer $(echo $STS_TOKEN)" https://privateca.googleapis.com/v1/projects/PROJECT_NUMBER/locations/LOCATION/caPools/CA_POOL_ID/certificates\?alt\=json -X POST -H "Content-Type: application/json" -H 'Accept: application/json' --data '{"lifetime": "100s", "pemCsr": "'$TUTORIAL_CSR'", "subjectMode": "REFLECTED_SPIFFE"}'
Client libraries
To forward the first-party token to CA Service, you must create a credentialed client. You can then use this credentialed client to make certificate requests:
Initiate a credentialed CA Service client:
python
caServiceClient = privateca_v1.CertificateAuthorityServiceClient(credentials=scoped_credentials)
Request a certificate.
Python
To authenticate to CA Service, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Verify the certificate. Your certificate should have a subject containing a single URI SAN. The SAN that attests to an identity is in the following format:
spiffe://IDENTITY_POOL_ID.PROJECT_NUMBER.global.workload.id.goog/subject/<oidc_subject_number>
Replace:
- IDENTITY_POOL_ID: The unique identifier of the workload identity pool.
- PROJECT_NUMBER - The project number of the project in which you created the workload identity pool.
Clean up
To avoid incurring charges to your Google Cloud account for the CA Service resources you created following this document, perform the following operations using the Google Cloud CLI:
Delete the CA you created.
Disable the CA:
gcloud privateca roots disable CA_ID --pool CA_POOL_ID --location LOCATION
Replace:
- CA_ID: The unique identifier of the CA.
- CA_POOL_ID: The unique identifier of the CA pool.
- LOCATION: The location of the CA pool.
Delete the CA:
gcloud privateca roots delete CA_ID --pool CA_POOL_ID --location LOCATION --ignore-active-certificates
Replace:
- CA_ID: The unique identifier of the CA.
- CA_POOL_ID: The unique identifier of the CA pool.
- LOCATION: The location of the CA pool.
Delete the CA pool you created.
gcloud privateca pools delete CA_POOL_ID --location LOCATION
Replace:
- CA_POOL_ID: The unique identifier of the CA pool.
- LOCATION: The location of the CA pool.
For more information about the
gcloud privateca pools delete
command, see gcloud privateca pools delete.Delete the workload identity pool you created:
gcloud iam workload-identity-pools delete IDENTITY_POOL_ID --location global
Replace:
- IDENTITY_POOL_ID: The unique identifier of the workload identity pool.
Delete the service account that you created:
gcloud iam service-accounts delete SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com
Replace:
- SERVICE_ACCOUNT: The unique identifier of the workload identity pool.
- PROJECT_ID: The project that owns the service account.
The CA Service Workload
Certificate Requester (privateca.workloadCertificateRequester
)
IAM role restricts the subject of the issued certificate to only
the identity of the requester. Ensure that users or workloads using the identity
reflection feature are only granted the CA Service
Workload Certificate Requester (privateca.workloadCertificateRequester
)
IAM role. To abide by the principle of least privilege, you can
avoid granting the CA Service Certificate Requester
(privateca.certificateRequester
) IAM role.
What's next
- Read about the various policy controls that let you control the properties of the requested certificate beyond a reflected identity.
- Read how you can configure and manage various policy controls.