Skip to content

Cross-Account Role Access

Duplicating IAM users across accounts is a liability: every copy is a separate credential to rotate, revoke and audit, and in practice none of them ever are. A cross-account role replaces them. The role lives in the account that owns the resources, its trust policy names who may assume it, and anyone who does gets temporary credentials from AWS STS that expire on their own.

The same mechanism covers three situations that look different but are not:

  • A person in the organization’s identity account reaching a workload account.
  • A contractor or temporary employee who should never hold a long-lived key.
  • A third-party company — an auditor, a cost-optimisation vendor, a monitoring provider — operating from their own AWS account.

The third-party case needs one more control than the others, and it is the one most often omitted. A vendor who monitors many customers assumes a role in each of them. If your role’s trust policy names only the vendor’s account ID, then any of that vendor’s customers can ask the vendor to assume your role, and the vendor — having no way to tell the request apart from a legitimate one — will comply. This is the confused deputy problem.

The fix is an external ID: an identifier the third party generates, unique per customer, that they must present on every sts:AssumeRole call and that your trust policy checks.

{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Principal": { "AWS": "111122223333" },
"Condition": {
"StringEquals": { "sts:ExternalId": "unique-id-issued-by-the-third-party" }
}
}

To set this up, the third party must give you three things: their AWS account ID, the external ID they have assigned to you, and the permissions they need. You create the role with those, and give them the role ARN in return.

Points that matter in practice:

  • The external ID is not a secret. Anyone who can read the role can read it. Its job is uniqueness, not confidentiality.
  • It must be generated by the third party, not by you — that is what guarantees no two of their customers share a value.
  • Grant the narrowest permission policy that does the job. For an auditor that is normally a read-only policy; AWS provides ReadOnlyAccess and SecurityAudit as starting points.
  • Test that the role cannot be assumed without the correct external ID. If it can, the condition is not doing its job.
  • Anything the third party does with your resources is billed to you.

Do not create an IAM user for a contractor, an auditor or a vendor and hand over an access key. A key has no expiry, leaves no indication of who is really using it, and survives the end of the engagement unless someone remembers to delete it. If a long-lived credential already exists for one of these cases, replacing it with a role is usually a half-hour change.