All Tools View Categories About Contact Privacy

IAM Trust Policy Generator

Build a role trust relationship — who may assume this role, with the correct AssumeRole/SAML/OIDC action and optional External ID / MFA conditions.

Runs entirely in your browser — account IDs and ARNs never leave this page.
-
action
-
resource field
0
conditions
-
structurally valid

  

About IAM Trust Policy Generator

A trust policy is the half of IAM role configuration that looks deceptively like a normal permissions policy but plays a completely different role: it does not grant the role any AWS permissions at all, it decides who — which account, which specific role or user, which AWS service, or which federated identity provider — is allowed to assume the role in the first place. IAM Trust Policy Generator builds exactly that shape of statement, gets the principal syntax right for each of the four common trust scenarios, and implements the real branching AWS requires between them.

Pick a principal type and the form adapts. An AWS account produces a root-account principal (arn:aws:iam::ACCOUNT:root) meaning any sufficiently-permissioned identity in that account can assume the role — the common shape for delegating within an organization or to a trusted partner account at the account level. A specific IAM role or user ARN narrows that down to exactly one identity. An AWS service — picked from a short preset list covering Lambda, EC2, ECS tasks, EKS, Glue, Step Functions and CodeBuild, or typed freely for any other service principal — is what lets a Lambda function or an EC2 instance profile assume the role on your behalf, the standard mechanism behind service roles. A Federated provider ARN, for SAML or OIDC identity providers, covers workforce SSO and things like GitHub Actions' OIDC-based AWS access.

The Federated case is where this tool does real conditional work rather than a cosmetic label swap: AWS requires a different STS action depending on how the federated caller authenticates. Choosing SAML sets the statement's action to sts:AssumeRoleWithSAML; choosing OIDC sets it to sts:AssumeRoleWithWebIdentity. Every other principal type — account, specific ARN, or AWS service — uses the ordinary sts:AssumeRole. That branching is implemented in the action-selection logic itself and covered by this page's self-tests, not asserted only in prose.

Two optional conditions cover the trust-policy hardening patterns that come up constantly in real deployments. An External ID adds a StringEquals condition on sts:ExternalId — the standard mitigation AWS documents for third-party cross-account access, preventing a confused-deputy attack where a third party is tricked into assuming a role on your behalf using someone else's credentials, because the exact agreed-upon external ID string must be present on every assume-role call. A Require MFA switch adds a Bool condition on aws:MultiFactorAuthPresent, so STS refuses the assume-role call unless the calling principal authenticated with multi-factor authentication. Both conditions can be combined in the same statement.

The most consequential structural detail this tool gets right by construction is the absence of a Resource field. Trust policies attach to a role and describe who may assume that specific role — the role is the implicit resource, and AWS trust policy statements use Principal in its place. Because the shared statement-building logic this page uses (the same engine behind the other policy tools here) defaults to filling in Resource: "*" for any statement that does not specify one, this generator explicitly strips that field back out after building the statement, so the JSON you copy never contains a stray Resource key that does not belong in a trust policy.

As with the other tools here, validation is structural rather than exhaustive: it confirms Version, a non-empty Statement array, a recognized Effect, an Action, and — since trust policies lack Resource — a Principal. It does not verify that an account ID, role ARN, or SAML provider ARN you typed actually exists in AWS. Everything runs client-side; account IDs and ARNs you enter are never uploaded.

Features

  • Four principal types — AWS account (root), specific IAM role/user ARN, AWS service (preset list + free text), Federated (SAML/OIDC).
  • Real action branching for Federated principals — SAML uses sts:AssumeRoleWithSAML, OIDC uses sts:AssumeRoleWithWebIdentity, everything else uses sts:AssumeRole.
  • Resource field correctly omitted — trust policies use Principal, not Resource, and the tool actively strips the default.
  • Optional External ID condition for the standard confused-deputy mitigation in cross-account trust.
  • Optional Require MFA condition on aws:MultiFactorAuthPresent.
  • Both conditions combine into one Condition block when both are set.
  • Structural validation confirming Effect/Action/Principal presence.
  • Pretty-printed JSON with Copy and Download .json.
  • Sample trust policy preloads a realistic cross-account example with External ID.
  • 100% client-side — account IDs and ARNs never leave the page.

How to Use

  1. Pick a principal type — AWS account, specific role/user ARN, AWS service, or Federated.
  2. Fill in the value — account ID, ARN, service principal (pick a preset or type your own), or provider ARN.
  3. For Federated, choose SAML or OIDC to set the correct STS action.
  4. Optionally set an External ID for cross-account trust.
  5. Optionally require MFA on the assume-role call.
  6. Click Build trust policy — check the stat cards and any validation warning.
  7. Copy or download the JSON and attach it as the role's trust relationship.

Examples

Example 1 — Lambda execution role. Principal type AWS service, value lambda.amazonaws.com (preset) — produces {"Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}, the standard shape for a Lambda function's execution role.

Example 2 — cross-account access with External ID. Principal type AWS account, value 444455556666, External ID vendor-portal-8842 — produces a root-account principal with a StringEquals condition guarding against confused-deputy misuse.

Example 3 — CI/CD via OIDC. Principal type Federated, value arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com, Federated kind OIDC — the action automatically becomes sts:AssumeRoleWithWebIdentity.

Example 4 — workforce SSO via SAML. Principal type Federated, value arn:aws:iam::123456789012:saml-provider/CorpOkta, Federated kind SAML — the action automatically becomes sts:AssumeRoleWithSAML.

Example 5 — break-glass admin role requiring MFA. Principal type specific IAM role/user ARN, value arn:aws:iam::123456789012:user/oncall-admin, Require MFA checked — the assume-role call succeeds only if the on-call engineer authenticated with MFA.

Benefits

  • Gets the Principal-not-Resource shape right by construction, a common source of confusion when hand-writing trust policies.
  • Correct STS action for every principal type, including the SAML/OIDC distinction that is easy to get wrong.
  • Built-in confused-deputy and MFA hardening as one-field, one-checkbox options.
  • Structural validation before you attach the policy to a real role.
  • Copy or download straight into the IAM console or IaC.
  • Private — account IDs and ARNs never leave your browser.

Frequently Asked Questions

Why does a trust policy have no "Resource" field?
A trust policy is attached to an IAM role and controls who may call <code>sts:AssumeRole</code> (or a SAML/OIDC variant) against that role — the role itself is the implicit resource. AWS trust policies name a <code>Principal</code> instead of a <code>Resource</code>. The shared statement builder this tool uses always fills in <code>Resource: "*"</code> by default for identity-based statements, so this generator explicitly deletes that field after building the statement — you can see this in the output: the JSON never contains a Resource key.
What principal types are supported?
Four: an AWS account (rendered as its root ARN, <code>arn:aws:iam::ACCOUNT:root</code>, meaning any principal in that account with permission to assume can do so), a specific IAM role or user ARN (only that exact identity), an AWS service (a short preset list — Lambda, EC2, ECS tasks, EKS, Glue, Step Functions, CodeBuild — plus free text for any other <code>*.amazonaws.com</code> service principal), or a Federated identity provider ARN (SAML or OIDC).
Why does the action change for Federated principals?
Because it genuinely must — AWS uses a different STS API depending on how the caller authenticates. A SAML-federated principal calls <code>sts:AssumeRoleWithSAML</code>, and an OIDC-federated principal (Cognito, GitHub Actions OIDC, etc.) calls <code>sts:AssumeRoleWithWebIdentity</code>. Every other principal type (account, specific ARN, or AWS service) uses the standard <code>sts:AssumeRole</code>. This is implemented as real branching logic on the principal type and a SAML/OIDC selector, not just a note in the FAQ — pick Federated and switch between SAML and OIDC to see the action change in the output.
What does the External ID condition do?
It adds <code>"Condition":{"StringEquals":{"sts:ExternalId":"<your value>"}}</code>, which is the standard defense against the "confused deputy" problem in third-party cross-account access: the third party must present the exact external ID you agreed on, or the assume-role call is denied even from the correct account.
What does "Require MFA" do?
It adds <code>"Condition":{"Bool":{"aws:MultiFactorAuthPresent":"true"}}</code>, meaning STS only allows the assume-role call if the calling principal authenticated with multi-factor authentication. If you also set an External ID, both conditions are merged into the same Condition block under their respective operators.
Does this tool validate against AWS's live trust policy grammar?
No — it runs the same structural check used across these tools: <code>Version</code> present and recognized, <code>Statement</code> non-empty, each statement has a valid <code>Effect</code>, an <code>Action</code>, and (since trust policies have no Resource) a <code>Principal</code>. It does not verify that a service principal string is a real AWS service, or that an account ID or ARN you entered actually exists.
Can I add multiple trusted principals to one role?
This generator builds one statement per trust policy. To trust more than one principal, add a second statement using the same shape — for example run this tool twice and merge the two <code>Statement</code> array entries, or give each principal its own statement with its own conditions if they need different External IDs or MFA requirements.
Where does this JSON go?
The output is a trust policy document — attach it as the role's "Trust relationship" (the <code>AssumeRolePolicyDocument</code>) in the IAM console or via <code>aws iam update-assume-role-policy</code>, not as a permissions policy on the role.
Is my account ID or ARN sent anywhere?
No — principal assembly, action branching, condition building and validation all run locally in your browser.
Can I export the result?
Yes, Copy as JSON and Download .json buttons appear once the trust policy is built.