Skip to main content
Requires Enterprise plan. Contact sales for access.
Ona environments can assume AWS IAM roles using OIDC federation. The Ona CLI generates a JWT token, which AWS STS exchanges for temporary credentials tied to an IAM role you configure. No static AWS credentials are needed.

Prerequisites

Step 1: Create an OIDC identity provider

Create an OIDC identity provider in AWS IAM:
  • Provider URL: https://app.gitpod.io
  • Audience: sts.amazonaws.com
Using the AWS CLI:
aws iam create-open-id-connect-provider \
  --url https://app.gitpod.io \
  --client-id-list sts.amazonaws.com \
  --thumbprint-list ""
AWS automatically fetches the OIDC configuration from https://app.gitpod.io/.well-known/openid-configuration and the signing keys from the JWKS endpoint.

Step 2: Create an IAM role with a trust policy

Create an IAM role that Ona environments can assume. The trust policy controls which tokens are accepted.

Inspect your token

Run this in an Ona environment to see the claims AWS will evaluate:
ona idp token --audience sts.amazonaws.com --decode
The V3 sub claim uses a key:value format:
organization_id:<orgID>:project_id:<projID>

Trust policy: allow all environments in an organization

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/app.gitpod.io"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "app.gitpod.io:aud": "sts.amazonaws.com"
        },
        "StringLike": {
          "app.gitpod.io:sub": "organization_id:<ORG_ID>:*"
        }
      }
    }
  ]
}

Trust policy: allow environments from a specific project

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/app.gitpod.io"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "app.gitpod.io:aud": "sts.amazonaws.com"
        },
        "StringLike": {
          "app.gitpod.io:sub": "organization_id:<ORG_ID>:project_id:<PROJECT_ID>:*"
        }
      }
    }
  ]
}
Replace <ACCOUNT_ID>, <ORG_ID>, <PROJECT_ID>, and <USER_ID> with your values. Find your organization and project IDs in the Ona dashboard URL or via the CLI.
Follow the principle of least privilege. Restrict trust policies to the narrowest scope needed.

Step 3: Assume the role

Use ona idp login aws to assume the role and configure your local AWS credentials:
ona idp login aws --role-arn arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>
This runs aws sts assume-role-with-web-identity under the hood and writes temporary credentials to your AWS config. Options:
  • --duration-seconds sets token expiry (default: 3600). Longer sessions require AWS admin approval.
  • --profile sets the AWS profile to configure (default: default).
  • --role-session-name sets a custom session name for audit trails.

Automate on environment startup

Add the login command to your automations so credentials are available when the environment starts:
# automations.yaml
tasks:
  aws-login:
    name: AWS Login
    command: |
      ona idp login aws --role-arn arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>
    triggeredBy:
      - postDevcontainerStart
After authentication, use AWS resources normally:
aws s3 ls
aws secretsmanager get-secret-value --secret-id my-secret --region us-east-1

Customizing the sub claim for AWS

By default, the sub claim for environment tokens includes organization_id and either project_id (if the environment belongs to a project) or environment_id. You can add extra fields to the sub claim on the OIDC Token Configuration page. This lets you write more specific trust policies.

Example: per-developer access

Add creator_email to the extra sub fields. The sub claim becomes:
organization_id:<orgID>:project_id:<projID>:creator_email:dev@example.com
Then restrict the trust policy:
{
  "Condition": {
    "StringEquals": {
      "app.gitpod.io:aud": "sts.amazonaws.com"
    },
    "StringLike": {
      "app.gitpod.io:sub": "organization_id:<ORG_ID>:*:creator_email:dev@example.com"
    }
  }
}

Example: restrict by repository

Add environment_initializers.git.remote_uri to the extra sub fields. The sub claim becomes:
organization_id:<orgID>:project_id:<projID>:environment_initializers.git.remote_uri:https%3A//github.com/org/repo.git
Colons in values are URL-encoded as %3A in the sub claim.
See Customizing the sub claim for the full list of available fields.

V2 trust policies

V2 is the previous token format. The examples below apply if your organization still uses V2 tokens. See the V2 AWS guide for the full V2 setup.
V2 tokens use a path-based sub format: org:<orgID>/prj:<projectID>/env:<envID>. Trust policies use StringLike on this format:
{
  "Condition": {
    "StringEquals": {
      "app.gitpod.io:aud": "sts.amazonaws.com"
    },
    "StringLike": {
      "app.gitpod.io:sub": "org:<ORG_ID>/*"
    }
  }
}

Troubleshooting

Token exchange fails with “Not authorized to perform sts:AssumeRoleWithWebIdentity”
  • Verify the OIDC provider URL is exactly https://app.gitpod.io (no trailing slash).
  • Check that the audience in the trust policy matches sts.amazonaws.com.
  • Decode your token (ona idp token --decode --audience sts.amazonaws.com) and verify the sub claim matches your trust policy conditions.
  • If you recently switched from V2 to V3, update your trust policy to use the V3 sub format.
Credentials expire during long-running tasks
  • Increase --duration-seconds (requires the IAM role’s max session duration to be increased in AWS).
  • Re-run ona idp login aws to refresh credentials.

Further reading