Design Secure Architectures · Lesson 1

Secure cross-account access

6 min read

Lesson objectives

  • Analyze Secure cross-account access and justify decision limits.

Skill and boundary

This skill decides who can request a role in another account, what that role session can do after assumption, and which organization guardrail can still block the action despite an IAM allow. Seeing a switch-role option does not prove access to data. A role trust policy is not a grant to read an object. The account numbers and names below are fictional training inputs. The lesson covers SAA-C03 task 1.1, designing secure access to AWS resources.

Decision model

Split the request into two operations. First, `sts:AssumeRole`: the source identity must be allowed to call it on the target role ARN, and the target role's trust policy must accept that principal. Second, the temporary role session requests a resource action: the role permission policy must allow the action on the right resource, while no applicable explicit deny or organization, resource, or key constraint blocks it. Trust answers who may assume the role. The role permission policy answers what the resulting session may do. A service control policy, or SCP, grants no permissions; it limits the maximum available permissions of member-account principals. It does not affect principals in the organization's management account. Identify the account type before invoking an SCP explanation.

Start with principal, action, and resource rather than a service name. An analyst reading monthly reports in one S3 prefix needs `s3:ListBucket` on the bucket ARN with a prefix condition, and `s3:GetObject` on object ARNs under that prefix. `GetObject` on only the bucket ARN targets the wrong resource type. `PutObject` is unnecessary just because both actions concern S3. If objects use a customer managed KMS key, also check decrypt authorization and the key policy. This case does not assume such encryption and does not add an invented KMS grant.

Worked case

Locate the first failure before editing. STS succeeds because the source grant and target trust align. The failure is in the second operation, not the role switch. Add `s3:GetObject` to the target role permission policy on `arn:aws:s3:::monthly-reports-demo/2026/*`, and constrain `s3:ListBucket` on `arn:aws:s3:::monthly-reports-demo` with the matching `s3:prefix` condition. Do not grant `s3:*` or use a wildcard resource. Test an object under `2026/` for success, an object under `2025/` for denial, and a write request for denial. Inspect CloudTrail evidence and policy evaluation where applicable, since a live test could expose policies or conditions not included in this paper case.

The decision table is: source `AssumeRole` allow plus target trust yields a temporary session; bucket `ListBucket` with prefix restricts listing; object `GetObject` under `2026/*` restricts reads; absent `PutObject` rejects writes. If an organization SCP explicitly denies `s3:GetObject` in the target member account, widening IAM permissions cannot solve the problem. Request a review of the organization guardrail through its owner or redesign within the policy; do not bypass it. This is a concrete counterexample: the immediate decision changes from adding the role permission to resolving the organizational conflict, while the role permission remains necessary if the restriction is removed.

Turn that decision into three separate policy-review lines rather than “grant S3 access.” The source line is `Action=sts:AssumeRole` and `Resource=arn:aws:iam::444455556666:role/ReadMonthlyReports`. The target trust line names `arn:aws:iam::111122223333:role/ReportAnalyst` as principal for `sts:AssumeRole`. The target permission line is `Action=s3:GetObject` and `Resource=arn:aws:s3:::monthly-reports-demo/2026/*`. A separate bucket-ARN statement with a prefix condition supports listing. These lines are an analytical sketch, not deployable JSON; implementation requires valid policy documents and condition testing.

Before copying the pattern, identify the trust relationship. A third-party provider using its own account for multiple customers can require an ExternalId condition to address the confused-deputy risk; the value and relationship must be managed for the intended customer. Do not impose ExternalId merely because two accounts inside the same organization differ. Federation through IAM Identity Center changes how the source identity is managed, but the resulting role session still needs an authorization analysis.

Test a cross-account design as two recorded requests. First identify the source principal and target role ARN at STS; if this step fails, editing S3 cannot help. Then evaluate object access as the temporary session principal, including the exact GetObject ARN, list prefix, and KMS permissions when encryption is specified. A useful test checks positive access to the intended object and negative access to another prefix and writes. If a resource policy grants a different principal directly, redraw the authorization path rather than copying a role policy mechanically. Successful role assumption and successful data access are distinct observations.

Exercise and product review

Request stageSupplied evidenceBefore repairCorrection or check
Source authorization for STSAllow on target roleSatisfiedNo change
Target role trustNames `OldAnalyst`AssumeRole deniedReplace ARN after confirming analyst identity
Object read after sessionGetObject on `2026/*`Not evaluated yetTest inside and outside the prefix after trust repair
Organization guardrailNo deny suppliedDoes not explain the stated failureInspect applicable SCP if the live test differs

Readiness takeaway

In an exam scenario, “the user can assume the role but cannot read the object” is evidence that the trust stage worked, not evidence that the resource grant is sufficient. Start at the first failing request and inspect action ARN, resource ARN, conditions, and guardrails. An S3 resource policy can support a different cross-account pattern, so this role solution is not a universal sharing recipe. The point is to explain the access decision from the facts supplied, not memorize one JSON policy for every case.

Lesson summary

The case scopes GetObject to the 2026 prefix and tests denied writes and other prefixes. If trust names OldAnalyst, AssumeRole fails before S3 and the repair moves to trust.