Configuring OIDC with Amazon Web Services
Use OpenID Connect within your tasks to authenticate with Amazon Web Services.
OpenID Connect (OIDC) allows your tasks to access resources in Amazon Web Services (AWS) without
needing to store the 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 AWS to trust Airplane's OIDC. See
Airplane OpenID Connect provider for an overview of how to generate tokens and the
token format.
Add Airplane as an identity provider to AWS
To add the Airplane OIDC provider to IAM, see the AWS documentation on
Creating OpenID Connect (OIDC) identity providers.
Use the following configuration:
- Provider URL: https://api.airplane.dev
- Audience: Set the audience you are setting when generating the OIDC token. For example, if you
are generating in a JST as
{{auth.idToken('sts.amazonaws.com')}}
, set the audience in your AWS configuration tosts.amazonaws.com
.
For an example Terraform configuration, see the Advanced section below.
Configure a role and trust policy
Next, create an IAM role that can be assumed by Airplane tasks via web identity.
To configure the role, see the AWS documentation for
creating a role for web identity.
Airplane's OIDC token can be used to obtain temporary credentials using
AWS Security Token Service.
Be sure to edit the trust policy to add the
sub
field to the validation conditions. Doing so
will ensure that tokens from other Airplane teams or tasks cannot be used to access your cloud
resources. The subject is formatted as team:{$team_id}:env:{$env_slug}:task:{$task_slug}
. For
example:jsonCopied1"Condition": {2"StringEquals": {3"api.airplane.dev:aud": "sts.amazonaws.com",4"api.airplane.dev:sub": "team:tea20010101aaaaaaaaaa:env:prod:task:add_s3_bucket_tag"5}6}
StringLike
can be used with a wildcard operator (*) to allow any tasks in your team to assume the
role. For example:jsonCopied1"Condition": {2"StringEquals": {3"api.airplane.dev:aud": "sts.amazonaws.com"4},5"StringLike": {6"api.airplane.dev:sub": "team:tea20010101aaaaaaaaaa:*"7}8}
You can find your team ID under Team settings.
Generate a token with the Airplane SDK to assume an AWS role
Now that AWS is configured to accept Airplane OIDC tokens, you can generate a token from within an
Airplane task.
typescriptCopied1import { STSClient } from "@aws-sdk/client-sts";2import { AssumeRoleWithWebIdentityCommand } from "@aws-sdk/client-sts";3import airplane from "airplane";45const getAWSCredentials = async () => {6const client = new STSClient({ region: "us-east-1" });78const token = await airplane.auth.idToken("sts.amazonaws.com");910const response = await client.send(11new AssumeRoleWithWebIdentityCommand({12RoleArn: "arn:aws:iam::000000000000:role/my_aws_role",13WebIdentityToken: token,14RoleSessionName: "my_session",15})16);17return response.Credentials;18};
javascriptCopied1import { STSClient } from "@aws-sdk/client-sts";2import { AssumeRoleWithWebIdentityCommand } from "@aws-sdk/client-sts";3import airplane from "airplane";45const getAWSCredentials = async () => {6const client = new STSClient({ region: "us-east-1" });78const token = await airplane.auth.idToken("sts.amazonaws.com");910const response = await client.send(11new AssumeRoleWithWebIdentityCommand({12RoleArn: "arn:aws:iam::000000000000:role/my_aws_role",13WebIdentityToken: token,14RoleSessionName: "my_session",15})16);17return response.Credentials;18};
pythonCopied1import airplane2import boto334def get_aws_credentials():5sts = boto3.client("sts")67token = airplane.auth.id_token("sts.amazonaws.com")89credentials = sts.assume_role_with_web_identity(10RoleArn="arn:aws:iam::000000000000:role/my_aws_role",11WebIdentityToken=token,12RoleSessionName="my_session",13)1415return credentials["Credentials"]
Use the token to make an AWS API call
You can now use the generated AWS credentials to initiate an AWS client like you normally would.
typescriptCopied1import { S3Client, PutBucketTaggingCommand } from "@aws-sdk/client-s3";2import { STSClient, AssumeRoleWithWebIdentityCommand } from "@aws-sdk/client-sts";3import airplane from "airplane";45export default airplane.task(6{7slug: "add_s3_bucket_tag",8},9async (params) => {10const credentials = await getAWSCredentials();1112const client = new S3Client({13region: "us-east-1",14credentials: {15accessKeyId: credentials.AccessKeyId,16secretAccessKey: credentials.SecretAccessKey,17sessionToken: credentials.SessionToken,18},19});2021const putBucketTaggingCommand = new PutBucketTaggingCommand({22Bucket: "your-bucket-name",23Tagging: {24TagSet: [25{26Key: "example-key",27Value: "example-value",28},29],30},31});3233const response = await client.send(putBucketTaggingCommand);3435console.log("Successfully added tag to bucket:", response);36}37);3839const getAWSCredentials = async () => {40const client = new STSClient({ region: "us-east-1" });4142const token = await airplane.auth.idToken("sts.amazonaws.com");4344const response = await client.send(45new AssumeRoleWithWebIdentityCommand({46RoleArn: "arn:aws:iam::000000000000:role/my_aws_role",47WebIdentityToken: token,48RoleSessionName: "my_session",49})50);51return response.Credentials;52};
javascriptCopied1import { S3Client, PutBucketTaggingCommand } from "@aws-sdk/client-s3";2import { STSClient, AssumeRoleWithWebIdentityCommand } from "@aws-sdk/client-sts";3import airplane from "airplane";45export default airplane.task(6{7slug: "add_s3_bucket_tag",8},9async (params) => {10const credentials = await getAWSCredentials();1112const client = new S3Client({13region: "us-east-1",14credentials: {15accessKeyId: credentials.AccessKeyId,16secretAccessKey: credentials.SecretAccessKey,17sessionToken: credentials.SessionToken,18},19});2021const putBucketTaggingCommand = new PutBucketTaggingCommand({22Bucket: "your-bucket-name",23Tagging: {24TagSet: [25{26Key: "example-key",27Value: "example-value",28},29],30},31});3233const response = await client.send(putBucketTaggingCommand);3435console.log("Successfully added tag to bucket:", response);36}37);3839const getAWSCredentials = async () => {40const client = new STSClient({ region: "us-east-1" });4142const token = await airplane.auth.idToken("sts.amazonaws.com");4344const response = await client.send(45new AssumeRoleWithWebIdentityCommand({46RoleArn: "arn:aws:iam::000000000000:role/my_aws_role",47WebIdentityToken: token,48RoleSessionName: "my_session",49})50);51return response.Credentials;52};
pythonCopied1import airplane2import boto334@airplane.task()5def add_s3_bucket_tag():6credentials = get_aws_credentials()78s3 = boto3.client(9"s3",10aws_access_key_id=credentials["AccessKeyId"],11aws_secret_access_key=credentials["SecretAccessKey"],12aws_session_token=credentials["SessionToken"],13)1415s3.put_bucket_tagging(16Bucket="my-bucket-name",17Tagging={18"TagSet": [19{20"Key": "example-key",21"Value": "example-value",22},23],24},25)2627print("Successfully added tag to bucket")2829def get_aws_credentials():30sts = boto3.client("sts")3132token = airplane.auth.id_token("sts.amazonaws.com")3334credentials = sts.assume_role_with_web_identity(35RoleArn="arn:aws:iam::000000000000:role/my_aws_role",36WebIdentityToken=token,37RoleSessionName="my_session",38)3940return credentials["Credentials"]
Advanced
Managing the OIDC provider using Infrastructure as Code
You can use Infrastructure as Code tools like Terraform to manage the IAM OIDC provider in your AWS
account. To add Airplane as an OIDC provider, you will need to specify a thumbprint, which can be
obtained by following
these instructions.
This Terraform example uses the current thumbprint, which is subject to change.
hclCopied1resource "aws_iam_openid_connect_provider" "airplane" {2url = "https://api.airplane.dev"34client_id_list = [5"sts.amazonaws.com",6]78thumbprint_list = ["08745487E891C19E3078C1F2A07E452950EF36F6"]9}