Configuring OpenID Connect for AWS with Pulumi Deployments
This document outlines the steps required to configure Pulumi Deployments to use OpenID Connect to authenticate with AWS. OIDC in AWS uses a web identity provider to assume an IAM role. Access to the IAM role is authorized using a trust policy that validates the contents of the OIDC token issued by Pulumi Cloud.
Create the identity provider
- In the navigation pane of the IAM console, choose Identity providers, and then choose Add provider.
- In the Provider type section, click the radio button next to OpenID Connect.
- For the Provider URL, provide the following URL:
https://api.pulumi.com/oidc - For the Audience field, enter the name of your Pulumi organization. Then select Add provider.
Configure the IAM role and trust policy
Once you have created the identity provider, you will see a notification at the top of your screen prompting you to assign an IAM role.
- Select the Assign role button.
- Select the Create a new role option, then select Next.
- On the IAM Create role page, ensure the Web identity radio button is selected.
- In the Web identity section:
- Select
api.pulumi.com/oidcunder Identity provider. - Select the name of your Pulumi organization under Audience. Then select Next.
- Select
- On the Add permissions page, select the permissions that you want to grant to your Pulumi deployments. Then select Next.
Many Pulumi programs create IAM roles, policies, or instance profiles (e.g., for Lambda, ECS, or EKS), which require IAM permissions. While AdministratorAccess is the simplest policy that covers all services including IAM, it is broader than most workloads need. For better security, consider one of these alternatives:
- PowerUserAccess + IAMFullAccess — provides broad service access with IAM permissions but excludes AWS Organizations management.
- Custom least-privilege policy — scoped to only the AWS services and IAM actions your Pulumi program uses (e.g.,
ec2:*,s3:*,iam:CreateRole,iam:AttachRolePolicy,iam:PassRole). - Permissions boundary — use a broader role policy but attach an IAM permissions boundary to cap the privileges of any IAM entities that Pulumi creates, preventing privilege escalation.
You can also further constrain the assumed role session using the Policy ARNs field in the Pulumi Deployments OIDC configuration.
Make a note of the IAM role’s ARN; it will be necessary to enable OIDC for your deployment.
Restricting role assumption to Pulumi Cloud scopes
The following restricts to any deployment in your organization:
"Condition": {
"StringEquals": {
"api.pulumi.com/oidc:aud": "<your-org-name>"
},
"StringLike": {
"api.pulumi.com/oidc:sub": "pulumi:deploy:org:<your-org-name>:*"
}
}
The following restricts to any stack within a specific project:
"Condition": {
"StringEquals": {
"api.pulumi.com/oidc:aud": "<your-org-name>"
},
"StringLike": {
"api.pulumi.com/oidc:sub": "pulumi:deploy:org:<your-org-name>:project:<your-project-name>:*"
}
}
The subject claim also includes the stack name and operation, so you can restrict further. See the full subject format and custom claims for details.
Configure OIDC via the Pulumi console
- Navigate to your stack in the Pulumi Console.
- Open the stack’s “Settings” tab.
- Choose the “Deploy” panel.
- Under the “OpenID Connect” header, toggle “Enable AWS Integration”.
- Enter the ARN of the IAM role created above in the “Role ARN” field.
- Enter a name for the assumed role session in the “Session Name” field. See Session name for the supported template variables.
- If you would like to use additional policies to further constrain the session’s capabilities, enter the policies’ ARNs separated by commas in the “Policy ARNs” field.
- If you would like to constrain the duration of the assumed role session, enter a duration in the form “XhYmZs” in the “Session Duration” field.
- Select the “Save deployment configuration” button.
With this configuration, each deployment of this stack will attempt to exchange the deployment’s OIDC token for AWS credentials using the specified IAM role prior to running any pre-commands or Pulumi operations. The fetched credentials are published in the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN environment variables. The raw OIDC token is also available for advanced scenarios in the PULUMI_OIDC_TOKEN environment variable and the /mnt/pulumi/pulumi.oidc file.
Session name
The session name becomes the RoleSessionName on the AWS STS AssumeRoleWithWebIdentity call and surfaces in every subsequent CloudTrail event as the last segment of the assumed-role principal ARN, so a templated session name makes each API call traceable to a specific Pulumi deployment.
Template variables
The session name supports ${var} placeholders that Pulumi substitutes when the deployment runs:
${organization.name}: Pulumi organization name.${project.name}: Pulumi project name.${stack.name}: Pulumi stack name.${deployment.operation}: operation type (for example,update,preview, ordestroy).${deployment.version}: deployment version number.${deployment.id}: deployment UUID.
A literal value with no ${...} placeholders is passed through unchanged.
Length and truncation
AWS caps RoleSessionName at 64 characters. If a rendered template would exceed that limit, Pulumi trims the truncatable name variables (${organization.name}, ${project.name}, ${stack.name}) from the end until the result fits. The protected variables (${deployment.operation}, ${deployment.version}, ${deployment.id}) are never trimmed, so each deployment remains identifiable.
For example, given the template:
${organization.name}-${project.name}-${stack.name}-${deployment.id}
with organization.name = "pulumi-local", project.name = "test-nocode-rtct-3", stack.name = "dev", and deployment.id = "806bf21f-444f-4825-a80c-afd12cd2526a", the full-length result would be 72 characters. Pulumi caps the three name variables to fit the budget while preserving the deployment UUID:
pulumi-loca-test-nocode-dev-806bf21f-444f-4825-a80c-afd12cd2526a
The result is exactly 64 characters: ${organization.name} and ${project.name} are each capped to 11 characters, ${stack.name} is 3 characters and fits as-is, and the deployment UUID is preserved in full.
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.