OIDC trust policy builder for GitHub, GitLab and Bitbucket
Pick your CI system and cloud, fill in the repository, and get the trust policy, provider settings or federated credential, plus the CI snippet that asks for the token. Covers GitHub's new subject format for repositories created after July 15, 2026.
Runs in your browser. Nothing you type is sent anywhere.
The tool is code on this page. It makes no network requests while you use it, stores nothing in cookies or local storage, and keeps working if you go offline after the page loads.
OIDC trust policy builder
Runs in your browser
Repository
Numeric IDs: gh api repos/OWNER/REPO --jq '.owner.id, .id'
Cloud settings
Result: GitHub Actions → AWS
Result: GitHub Actions, AWS
Before you apply it
- Words in capitals, such as ACCOUNT_ID or PROJECT_ID, are placeholders: fill in the fields above or replace them before you apply the result.
IAM role trust policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:kiteline/web-app:ref:refs/heads/main"
}
}
}
]
}
GitHub Actions workflow
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v6.3.0
with:
role-to-assume: arn:aws:iam::ACCOUNT_ID:role/web-app-deploy
aws-region: us-east-1
- run: aws sts get-caller-identity
Example values use Kiteline, a fictional company.
How to use it
- Choose the CI system and the cloud. The fields change to what that combination needs.
- Fill in the repository or project and, if you have them, the numeric IDs. Leave a field empty to get a placeholder in capitals.
- Read the notes under the result. They point out the settings that are easy to get wrong for this combination.
- Copy each block to where it belongs: the trust policy or credential to your cloud, the snippet to your CI file. Deploy from a test branch first.
The same without a browser
The values the builder asks for, looked up from a terminal.
gh api repos/OWNER/REPO --jq '.owner.id, .id'gh api repos/OWNER/REPO/actions/oidc/customization/subgcloud projects describe PROJECT_ID --format='value(projectNumber)'aws sts get-caller-identity --query Account --output textWhat the cloud checks in the token
Every CI system signs a short-lived token for the job. The cloud accepts it only if three things match: who issued it, who it was issued for, and what it describes.
- iss
Issuer
Who signed the token: https://token.actions.githubusercontent.com for GitHub, your GitLab address, or a Bitbucket address that includes your workspace. The cloud trusts the issuer's published keys, not a stored password.
- aud
Audience
Who the token is for. AWS expects sts.amazonaws.com, Azure recommends api://AzureADTokenExchange, and Google expects the provider's own address unless you allow another. A separate audience per receiving service keeps a token minted for one from working at another.
- sub
Subject and other claims
Which job asked: repository, branch, tag or environment. This is the part to keep narrow. Prefer IDs over names where the cloud can check them, because a deleted name can be registered again by someone else.
GitHub's new subject format
GitHub now puts numeric IDs in the subject: repo:kiteline@123456/web-app@456789:ref:refs/heads/main instead of repo:kiteline/web-app:ref:refs/heads/main. Repositories created after July 15, 2026 use it automatically, as do repositories renamed or transferred after that date and those that opt in; older repositories keep the name-based format until then. A trust policy that only lists the old string fails on a new repository with Not authorized to perform sts:AssumeRoleWithWebIdentity. Choose Accept both while you switch, and add the IDs so the policy no longer depends on the name.
Read the full write-upHow Crunu handles this
The same check for secrets that aren't cloud keys
A Crunu service token can carry a CI binding (OIDC). The server then accepts the token only together with a JWT from GitHub Actions, GitLab CI or Bitbucket Pipelines whose claims match your rules for repository, branch and environment. GitHub rules match individual claims, so the new subject format doesn't break them, and adding the repository and owner IDs pins a token to one repository. A replayed JWT is refused.
Read about CI bindingsQuestions about this tool
Found a case the tool gets wrong? Write to support@crunu.com
Why does a new repository fail with Not authorized to perform sts:AssumeRoleWithWebIdentity?
A likely cause is GitHub's new subject format. Repositories created after July 15, 2026 get a sub with numeric IDs, so a policy that lists only repo:OWNER/REPO:… no longer matches. Choose the new or both formats here, or match repository_id and repository_owner_id instead.
Can I use a wildcard like repo:my-org/*?
It makes the error go away and gives the role to every repository, branch, pull request run and workflow in the organization, including ones created later. For anything that can deploy, match one repository by ID and a protected branch or an environment with reviewers.
Branch or deployment environment?
For production, an environment. A branch subject matches any workflow run on that branch, including a workflow file someone changed there; an environment can require reviewers before a job that uses it starts.
Does the builder create anything in my cloud account?
No. It only produces text in your browser. Nothing is sent to AWS, Google, Microsoft or us; you apply the result yourself.
Why can't Bitbucket Pipelines sign in to Azure here?
Bitbucket's subject includes a step UUID that changes on every run, and Azure federated credentials accept only one exact subject. AWS and Google Cloud can match patterns or individual claims, so they work.
Read more
Other free tools
- Secret key generatorRandom secrets in Base64, Base64URL, hex or letters and digits, from 128 to 512 bits, with a ready .env line.
- .env linterFinds lines that loaders read differently, values that run as commands when sourced, duplicates and values that look like real keys.
- .env converterTurns a .env file into JSON, YAML, a Docker --env-file or a systemd EnvironmentFile, and back again.
- Compare two .env filesShows which variables exist in only one file and which have different values, with values hidden until you ask.
- Offboarding checklist generatorPick the services someone could reach and get an ordered checklist of what to close and which keys to reissue, with links.
When the values need a home
Crunu is a vault for your team's environment variables and keys. Values are encrypted on your devices, so the server stores them only as ciphertext. Free during early access.