Configuring OIDC with Google Cloud Platform

Use OpenID Connect within your tasks to authenticate with Google Cloud Platform.
OpenID Connect (OIDC) allows your tasks to access resources in Google Cloud Platform (GCP) without needing to store the GCP credentials. This enables a seamless and safe interaction between your tasks and the cloud services they rely on.
This guide will walk you through how to configure GCP to trust Airplane OIDC. See Airplane OpenID Connect provider for an overview of how to generate tokens and the token format.

Add Airplane as a Workload Identity Provider

To create a new Workload Identity Provider, you first have to create a Workload Identity Pool. Once that is done, you need to create a new Workload Identity Provider inside the Workload Identity Pool. Provide the following configuration for your Workflow Identity Provider:
  • Provider type: OpenID Connect (OIDC)
  • Issuer (URL): https://api.airplane.dev
  • Audiences: You can optionally provide a custom audience that can be set when generating the OIDC token. For example, if you are generating in a JST as {{auth.idToken('https://your-app.example.com')}}, set the audience in your GCP configuration to https://your-app.example.com.
  • Provider attributes mapping: The attribute mappings map claims in the token JWT to assertions you can make about the request (like the task slug or email of the user executing a task). Attributes used in a Common Expression Language (CEL) expression or IAM policy must be mapped from the incoming token attributes. For example, to use the task slug claim in a policy, you can map the Google attribute attribute.task_slug to the OIDC assertion.task_slug.

Connect the Workload Identity Pool to a GCP Service Account

If you do not already have a GCP Service Account, create one with the desired IAM permissions you want your Airplane task to be able to access. See the GCP documentation for how to create a service account.
Once you have a service account, you need to grant the external identity permissions to impersonate your service account. You will need to add an IAM permission on the service account itself. See the GCP documentation for how to do so. You can reference the Workload Identity Pool you created in the previous step via the principalSet:// protocol.
Be sure to configure the external identity to restrict the identities allowed to impersonate the account. Doing so will ensure that tokens from other Airplane teams or tasks cannot be used to access your cloud resources. For example, to restrict impersonation to only Airplane tasks with the slug test_oidc_gcp, grant the roles/iam.workloadIdentityUser IAM role to the external identity (note the attribute.task_slug/test_oidc_gcp suffix):
Copied
1
principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.task_slug/test_oidc_gcp
where PROJECT_NUMBER is your Google Cloud project number, and POOL_ID is the ID of the Workload Identity Pool you created. This also assumes you added task_slug as a mapped attribute.

Generate a token with the Airplane SDK to impersonate an GCP service account

Now that GCP is configured to accept Airplane OIDC tokens, you can generate a token from within an Airplane task to impersonate your service account.
typescript
Copied
1
import airplane from "airplane";
2
3
const getGCPCredentials = async () => {
4
const token = await airplane.auth.idToken("https://your-app.example.com");
5
6
const resp = await fetch("https://sts.googleapis.com/v1/token", {
7
method: "POST",
8
body: JSON.stringify({
9
// This is the audience of the Workload Identity Pool you created
10
audience:
11
"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
12
grantType: "urn:ietf:params:oauth:grant-type:token-exchange",
13
requestedTokenType: "urn:ietf:params:oauth:token-type:access_token",
14
scope: "https://www.googleapis.com/auth/cloud-platform",
15
subjectTokenType: "urn:ietf:params:oauth:token-type:jwt",
16
subjectToken: token,
17
}),
18
});
19
20
// credentials will look like:
21
// {
22
// access_token: ...,
23
// issued_token_type: 'urn:ietf:params:oauth:token-type:access_token',
24
// token_type: 'Bearer',
25
// expires_in: 3599
26
// }
27
const credentials = await resp.json();
28
return credentials.access_token;
29
};

Use the token to make an GCP API call

You can now use the generated GCP credentials to interact with the GCP API.
typescript
Copied
1
import airplane from "airplane";
2
3
export default airplane.task(
4
{
5
slug: "get_gcs_bucket",
6
},
7
async (params) => {
8
const accessToken = getGCPCredentials();
9
10
const bucketName = "your-bucket-name";
11
const objectName = "your-object-name";
12
13
const resp = await fetch(`https://storage.googleapis.com/${bucketName}/${objectName}`, {
14
headers: {
15
Authorization: `Bearer ${accessToken}`,
16
},
17
});
18
19
console.log(resp.text());
20
},
21
);
22
23
const getGCPCredentials = async () => {
24
const token = await airplane.auth.idToken("https://your-app.example.com");
25
26
const resp = await fetch("https://sts.googleapis.com/v1/token", {
27
method: "POST",
28
body: JSON.stringify({
29
// This is the audience of the Workload Identity Pool you created
30
audience:
31
"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
32
grantType: "urn:ietf:params:oauth:grant-type:token-exchange",
33
requestedTokenType: "urn:ietf:params:oauth:token-type:access_token",
34
scope: "https://www.googleapis.com/auth/cloud-platform",
35
subjectTokenType: "urn:ietf:params:oauth:token-type:jwt",
36
subjectToken: token,
37
}),
38
});
39
40
const credentials = await resp.json();
41
return credentials.access_token;
42
};

SDK reference

See Auth SDK reference for more information.