Phase 4: Security & Compliance

Cross-account roles, assume-role chains & trust policies

Advanced ~3 min read
Think of it this way A friendly analogy. Read this if the technical version feels dense. Show Hide

You know how sometimes you need a special tool or book that isn't in your own backpack or even your classroom? Maybe your friend Alex has a super cool art kit, or the school library has a secret collection of ancient maps that only certain people can access. We have a similar situation when building big computer programs. Different parts of our computer system (we call these "accounts") might need to share special tools or information with each other, but we don't want to just give everyone permanent keys to everything. That would be messy and unsafe!

This is where "cross-account roles" come in. Imagine the school library has a special "Ancient Scrolls Room" with really old, fragile maps. To even open the door, you don't use your regular student ID; you need a "Special Librarian's Pass." This "Special Librarian's Pass" is like a special temporary job title with a list of things you’re allowed to do, like "borrow maps," but not "rearrange all the shelves." These passes aren't given to one person permanently; they’re more like a magical key that different people can temporarily borrow.

Now, let's say your class (which is like one "account") needs to look at a map from that Ancient Scrolls Room (which is in a different "account," the library's special collection). Instead of the librarian making a brand new pass just for your teacher, your teacher can ask to "assume" (fancy word for temporarily use) the existing "Special Librarian's Pass." But there's a catch! The "Special Librarian's Pass" has a secret rulebook attached to it, called a "trust policy." This rulebook says exactly who is allowed to even ask to borrow that pass. It might say, "Only teachers from the 5th grade can assume this pass," or "Only the principal can assume this pass." If your teacher matches the rules, they get to "assume" the pass, use its powers to grab the map, and then give the pass back.

This smart way of sharing means nobody has to give out permanent keys or copies of special tools. Instead, different "accounts" can temporarily "borrow" the right permissions to do their job, and the "trust policy" makes sure only the right people are allowed to ask. So, when you’re building big, complex computer systems, this lets you set up safe ways for your different projects or teams to work together and share without anyone accidentally messing up another team's stuff. It’s all about teamwork and safety!

Cross-account roles are fundamental to building secure, scalable multi-account AWS environments. Instead of creating duplicate users or credentials in every account, you leverage IAM roles to grant specific permissions to principals (users, roles, or services) residing in other AWS accounts. The core mechanism here is the sts:AssumeRole API call. Account A, the "assuming account," grants a principal (e.g., an IAM user or role) the permission to call sts:AssumeRole. Account B, the "trusting account," defines an IAM role with a trust policy that explicitly allows principals from Account A to assume it. Once assumed, the principal temporarily inherits the permissions defined in the trusting account's role, enabling delegated access without sharing long-lived credentials. This pattern is crucial for centralized security operations, shared services, and partner integrations.

The trust policy is the critical component defining who can assume a role. It's a resource-based policy attached directly to the role, specifying Principal elements that are permitted to invoke sts:AssumeRole on that role. This Principal can be an entire AWS account, specific IAM users, services, or, crucially, other IAM roles (e.g., arn:aws:iam::111122223333:role/MyAnotherRole). When a role's trust policy specifies another role as its Principal, you enable assume-role chains. An entity (user or role) assumes Role A, then uses Role A's temporary credentials to assume Role B, and potentially Role C, creating a secure, multi-step privilege escalation or access path. This chaining is powerful for advanced security architectures, allowing for "break-glass" scenarios where higher privileges are only accessed through an auditable, multi-step process, or for compartmentalizing access across different functional accounts.

For Cloud Architects, mastering cross-account roles, assume-role chains, and trust policies is non-negotiable for designing robust multi-account strategies. Proper configuration ensures adherence to the principle of least privilege, as permissions are granted only when necessary and often for limited durations (via role session duration). CloudTrail logs provide comprehensive audit trails, tracking not only which role was assumed but also the original caller who initiated the AssumeRole operation, even through a chain. Practical considerations include using ExternalId in trust policies for third-party access to prevent the confused deputy problem and carefully managing MaxSessionDuration to enforce temporary access. These mechanisms are the backbone of secure inter-account communication and delegated administration in AWS.

Key Takeaways

  • Cross-account roles facilitate secure, delegated access across AWS accounts using sts:AssumeRole.
  • A role's trust policy explicitly defines which principals (accounts, users, roles) are allowed to assume it.
  • Assume-role chains enable multi-step privilege escalation or access paths by having one role assume another.
  • CloudTrail provides complete auditability, showing the original caller through any assume-role chain.
  • Design with least privilege, ExternalId for third parties, and appropriate session durations.

Code Example

yaml
# IAM Role for cross-account access or assume-role chain
MyCrossAccountRole:
  Type: AWS::IAM::Role
  Properties:
    RoleName: MyCrossAccountRoleExample
    AssumeRolePolicyDocument:
      Version: '2012-10-17'
      Statement:
        - Effect: Allow
          Principal:
            AWS:
              - arn:aws:iam::111122223333:root # Allow account 111122223333 to assume this role
              - arn:aws:iam::444455556666:role/AnotherAccountRole # Or allow a specific role from account 444455556666
          Action: sts:AssumeRole
          Condition:
            StringEquals:
              sts:ExternalId: "my-secure-external-id" # Recommended for third-party access
    Path: "/"
    Policies:
      - PolicyName: MyCrossAccountPermissions
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action: s3:GetObject
              Resource: arn:aws:s3:::my-secure-bucket/*

How this code works

This code defines an IAM role, MyCrossAccountRole, designed to allow other AWS accounts or specific roles to temporarily gain its permissions. This is fundamental for building secure cross-account access or setting up assume-role chains where one role assumes another. The AssumeRolePolicyDocument is the crucial "trust policy" that dictates who is allowed to assume this role. Within its Principal section, it explicitly lists either an entire AWS account (arn:aws:iam::111122223333:root) or a particular role from another account (arn:aws:iam::444455556666:role/AnotherAccountRole). The Action: sts:AssumeRole is the specific API call permitted. A vital security measure, especially for third-party access, is the Condition block requiring a matching sts:ExternalId, preventing confused deputy attacks by ensuring the caller intended to assume this specific role.

Once a trusted entity successfully assumes MyCrossAccountRole, they then inherit the permissions defined in the Policies section. Here, the MyCrossAccountPermissions policy grants the assumed role the ability to perform s3:GetObject actions on my-secure-bucket/*, allowing it to read objects from that S3 bucket. A subtle but important distinction is understanding that the AssumeRolePolicyDocument only controls who can assume the role, while the separate Policies section defines what the role can do after it's been assumed. Without both, the role would either be unassumable or have no useful permissions.