Join our Newsletter — 33% off our NHI Course
Home› Guides› How to audit AWS IAM Roles Anywhere and…
Guide Cloud & Workload Identity

How to audit AWS IAM Roles Anywhere and OIDC identity providers: find loose trust and idle federation

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 28 October 2026 12 min read
On this page

Every IAM OIDC identity provider and every IAM Roles Anywhere trust anchor in an AWS account is a door that lets something outside AWS mint temporary credentials, and most accounts have doors nobody remembers opening. This guide is an audit procedure: how to enumerate OIDC providers and Roles Anywhere trust anchors, profiles and subjects in each account, which trust policy conditions to check, how to find federation that is no longer used, and how to remove it safely. It is for cloud security engineers, platform teams and identity teams reviewing workload federation across an AWS Organization. It does not repeat design guidance: for that see the AWS IAM Roles Anywhere Security Guide and the Workload Identity Federation Guide.

Key takeaways

  • Federation is configured per account: AWS states that an OIDC provider used in a role trust policy must be in the same account as the role, and Roles Anywhere trust anchors are account resources too, so the audit has to visit every account.
  • The trust policy is where the risk lives: an OIDC provider or trust anchor on its own grants nothing; the roles that trust it decide who gets in, so audit roles and providers together.
  • Check sub and aud on every OIDC role: AWS warns that if a GitHub role does not limit token.actions.githubusercontent.com:sub, workflows from organisations outside your control can assume it, and recommends immutable IDs such as repository_id over names.
  • Roles Anywhere needs certificate conditions: AWS strongly recommends aws:SourceArn, aws:SourceAccount or sts:SourceIdentity conditions plus certificate attributes in the role trust policy.
  • Both mechanisms record last use: ListSubjects returns lastSeenAt per certificate subject, and GetRole returns RoleLastUsed, so idle federation can be found from APIs before anyone is asked.

When you need this

  • Periodic access review: federation trust is an NHI entitlement like any other. See the How to find unused AWS IAM roles and access keys guide for the role side.
  • After migrating off access keys: teams that moved CI or on-premises servers to federation often leave test providers, broad trial roles and old anchors behind.
  • CI platform or CA change: a retired CI provider or decommissioned issuing CA should take its provider, anchor and roles with it.
  • Suspected trust tampering: adding a provider or anchor is a persistence route. MITRE ATT&CK lists it under T1484.002 Trust Modification, and adding roles under T1098.003 Additional Cloud Roles.
  • Issuer key exposure: AWS states that a private key published in an OIDC provider's JWKS must be treated as compromised, and that you should review AssumeRoleWithWebIdentity events for the exposure period.

Before you start

  • Access: a read-only audit role in every account with iam:List*, iam:Get* (including iam:GetAccountAuthorizationDetails) and rolesanywhere:List* and rolesanywhere:Get*, deployed through your organisation's account baseline.
  • Regions: IAM OIDC providers are global to the account; Roles Anywhere trust anchors, profiles and subjects are regional, so loop over every enabled Region.
  • CloudTrail: an organisation trail or log archive you can query for sts.amazonaws.com, iam.amazonaws.com and rolesanywhere.amazonaws.com events. See the AWS CloudTrail Guide.
  • Owner data: the list of CI organisations, Kubernetes clusters and issuing CAs your company actually runs, so you can recognise a provider or anchor that does not belong.
  • A findings register: one row per provider or anchor with account, Region, URL or CA, audiences, roles that trust it, conditions present, last use, owner and decision.

Step-by-step

1. Inventory IAM OIDC providers (read-only)

  1. In each account, run aws iam list-open-id-connect-providers, then aws iam get-open-id-connect-provider --open-id-connect-provider-arn ARN for each one.
  2. Record Url, ClientIDList (audiences), ThumbprintList, CreateDate and Tags.
  3. Match each URL to a platform you own. Typical issuers include token.actions.githubusercontent.com, GitLab, HCP Terraform (app.terraform.io), CircleCI and EKS cluster issuers. An EKS issuer for a cluster that no longer exists is a common leftover.
  4. Check audiences: AWS states that the token's aud claim must match an audience on the provider. An audience list padded with old client IDs widens what can be accepted.
  5. Note that Google, Facebook and Amazon Cognito are built into AWS and do not appear as IAM OIDC providers, so search trust policies for those principals separately.

2. Map roles to each provider and check the conditions

Pull every role's trust policy in one call with aws iam get-account-authorization-details --filter Role, then select roles whose Principal.Federated is an OIDC provider ARN or a built-in provider, with action sts:AssumeRoleWithWebIdentity.

ProviderWhat AWS documentsAudit finding if absent or loose
GitHub ActionsIAM checks on create or update that token.actions.githubusercontent.com:sub is present and not solely a wildcard or null; AWS recommends immutable claims such as repository_id, repository_owner_id and actor_idA sub of repo:org/* trusts every repository and branch in the organisation; name-based conditions break if a name is freed and re-registered
HCP TerraformTrust policy must evaluate app.terraform.io:sub; STS denies requests otherwiseRoles created before enforcement may still be too broad at workspace or project level
GitLab.com, Buildkite, CircleCIProvider-specific keys, for example GitLab project_id and namespace_id, Buildkite organization_id and pipeline_id, CircleCI oidc.circleci.com/project-id; AWS recommends immutable IDs over slugsRoles that check only aud trust every project on that provider's tenant for your audience
GoogleUse accounts.google.com:aud, oaud and sub; google/organization_number can restrict to one organisationA role trusting accounts.google.com with only aud trusts any Google identity for that client
Amazon CognitoRoles must contain at least one condition key to limit principals; cross-account roles use audMissing aud means a user from an unintended identity pool could assume the role
Any providerPair sub with aud; do not use email as the primary identifierTrust policies keyed on email or on StringLike with leading wildcards

For GitHub roles, check also whether you use job_workflow_ref or environment to pin access to approved workflows and protected environments. See the GitHub Actions OIDC Federation Hardening Guide and How to set up workload identity federation for GitHub Actions to AWS.

3. Inventory Roles Anywhere resources (read-only)

  1. In each account and Region, run aws rolesanywhere list-trust-anchors. For each anchor record name, enabled, source.sourceType (an AWS Private CA ARN or an uploaded certificate bundle), createdAt, updatedAt and notificationSettings.
  2. Run aws rolesanywhere list-profiles. Record roleArns, sessionPolicy, managedPolicyArns, durationSeconds, acceptRoleSessionName, attributeMappings and enabled.
  3. Run aws rolesanywhere list-crls and confirm every anchor whose CA revokes certificates has an enabled CRL. AWS states that revocation works only through imported CRLs, by API or CLI, and that callbacks to CRL distribution points or OCSP are not supported.
  4. Run aws rolesanywhere list-subjects. Each subject has x509Subject, createdAt (first use) and lastSeenAt (last credential request). aws rolesanywhere get-subject adds the certificates seen, with serial number, issuer, seenAt and whether the request failed.

4. Check Roles Anywhere trust policies

CheckWhyFinding
Trust policy names rolesanywhere.amazonaws.com with sts:AssumeRole, sts:TagSession, sts:SetSourceIdentityRequired for the service to assume the roleInventory every role that trusts the service, in or out of a profile
aws:SourceArn pinned to one trust anchorAWS sets aws:SourceArn to the anchor used in CreateSession; without it any anchor in the account can be usedMissing or wildcard source condition
Certificate attribute condition such as aws:PrincipalTag/x509Subject/CNMaps one certificate identity to one roleRole accepts any certificate the CA issues
Profile session policy and managed policiesCap what any session from the profile can doProfile with no session policy on an administrative role
durationSeconds and acceptRoleSessionNameSession lifetime and CloudTrail attributionLong sessions without a reason; custom session names accepted without need
CRL present and recently updatedRevocation at the CA does nothing in AWS without itAnchor with no CRL, or a CRL older than the CA's publication interval

5. Find idle federation

  • Roles: aws iam get-role returns RoleLastUsed.LastUsedDate and Region. AWS notes the field is null if the role has not been used within the IAM tracking period.
  • OIDC providers: a provider is idle when no role trusting it has been used, and when CloudTrail shows no AssumeRoleWithWebIdentity events naming it for your idle period.
  • Roles Anywhere: subjects with an old lastSeenAt show certificates no longer authenticating; anchors whose subjects are all idle, and profiles whose roles are all unused, are candidates for removal. CloudTrail records CreateSession under rolesanywhere.amazonaws.com.
  • Repeated failures: subject certificates with failed set, or bursts of failed AssumeRoleWithWebIdentity, show something still trying to use federation you thought was gone, or something probing it.

6. Remediate (destructive steps flagged)

  1. Tighten before deleting: add sub, immutable ID, aws:SourceArn and certificate attribute conditions to roles in use. Test in a non-production account with the real workload.
  2. Disable before deleting where AWS offers it: aws rolesanywhere disable-profile and disable-trust-anchor stop new sessions and can be reversed with the matching enable command. Watch for breakage over your notice period.
  3. Destructive: remove unused roles first, then aws iam delete-open-id-connect-provider for providers no role trusts, and delete-profile, delete-trust-anchor and delete-crl for Roles Anywhere resources. Record the configuration first so it can be recreated.
  4. Remove stale audiences with aws iam remove-client-id-from-open-id-connect-provider.
  5. If a credential or issuer key may have been exposed, revoke active sessions for affected roles, as AWS describes for exposed JWKS keys, and import an updated CRL for revoked certificates.

Verify it worked

MetricSourceTarget
OIDC roles without a sub or provider-specific identity conditionTrust policy scanZero
Roles Anywhere roles without aws:SourceArn and a certificate conditionTrust policy scanZero
Providers and anchors with no owner tag or no matching platformInventory joined with owner dataZero
Idle providers, anchors and subjects beyond policyRoleLastUsed, lastSeenAt, CloudTrailZero after each review
Federation changes outside change controlCloudTrail CreateOpenIDConnectProvider, AddClientIDToOpenIDConnectProvider, UpdateOpenIDConnectProviderThumbprint, CreateTrustAnchor, UpdateProfile, ImportCrl, UpdateAssumeRolePolicyEvery event matched to a ticket

Rollback and common errors

  • Deleting a provider that a role still trusts: the role's federated sign-ins stop. Recreate the provider with the recorded URL and audiences, and check the role trust policies still reference the same ARN.
  • Replacing thumbprints by mistake: AWS notes that UpdateOpenIDConnectProviderThumbprint replaces the whole list rather than merging. AWS verifies most issuers through its trusted root CAs and falls back to thumbprints only in some cases, so record the old list before any change.
  • Adding a GitHub condition that IAM rejects: IAM refuses a trust policy where the GitHub sub is missing or only a wildcard. Write a specific sub or immutable ID condition rather than a placeholder.
  • Trusting null last use: a null RoleLastUsed means no use inside the tracking period, not proof of no consumer. Confirm in CloudTrail and with the owning team.
  • Auditing one Region: Roles Anywhere resources are regional; an anchor in a Region nobody uses is exactly what an attacker would add.
  • Forgetting the CA: removing an anchor while the external CA keeps issuing certificates leaves a path that reopens the moment anyone recreates the anchor. Retire the issuing template too.

Hardening afterwards

  • Restrict who can create trust: AWS advises limiting CreateOpenIDConnectProvider and UpdateOpenIDConnectProviderThumbprint to highly privileged users. Use SCPs to deny those actions and Roles Anywhere administration outside a pipeline role. See the AWS Organizations and SCPs Guide.
  • Alert on trust changes: stream the CloudTrail events in the verification table to your SIEM.
  • Tag owners: tag every provider, anchor and profile with owner and platform, and treat untagged federation as a finding.
  • Use certificate expiry notifications: trust anchors can send expiry events to EventBridge and AWS Health, which doubles as a liveness signal for anchors nobody watches.
  • Repeat quarterly and on every platform change: retire the provider or anchor in the same change that retires a CI tenant, cluster or CA.
FrameworkReferenceRelevance
NIST CSF 2.0PR.AA-01, PR.AA-05, DE.CM-09Service credentials managed; entitlements reviewed for least privilege; runtime monitored
NIST SP 800-53 Rev 5AC-2, AC-6, IA-5, IA-5(2), CM-8, AU-6Account review, least privilege, authenticator and PKI-based authentication management, inventory, audit review
CIS Controls v8.1Controls 5 and 6Account and access control management for service accounts
MITRE ATT&CK v20T1484.002 Trust Modification; T1098.003 Additional Cloud Roles; T1649 Steal or Forge Authentication Certificates; T1078.004 Cloud AccountsAdding federation trust, widening roles, abusing certificates, and using cloud identities obtained through federation

Practitioner checklist

  • Deploy a read-only audit role to every account and loop over every Region for Roles Anywhere.
  • Inventory OIDC providers with URL, audiences, thumbprints and tags, and match each to a platform you own.
  • Map every role that trusts a provider or Roles Anywhere and record its conditions.
  • Require sub plus immutable IDs on OIDC roles and aws:SourceArn plus a certificate attribute on Roles Anywhere roles.
  • Confirm every Roles Anywhere anchor that needs revocation has a current imported CRL.
  • Use RoleLastUsed, lastSeenAt and CloudTrail to find idle federation.
  • Disable, observe, then delete; record configuration before each deletion.
  • Restrict federation administration with SCPs and alert on every trust change.

Standards and references

Related NHI Mgmt Group resources: AWS STS and AssumeRole Guide, Cloud Workload Identity Guide, Top 10 AWS IAM Mistakes, Identity Federation Failure Modes.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 28 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org