Cross-Account Access for a Shared Logging Bucket
A company has three application accounts (App-A, App-B, App-C) and one central security account. Each app account writes audit logs to a bucket owned by the security account. The security team wants app roles to be able to PutObject only, never read or delete, and wants the bucket policy to be the single source of truth so that app teams cannot widen access themselves. An engineer proposes giving each app role a role in the security account and having them assume it. A second engineer proposes a bucket policy that grants the app account principals PutObject with a condition restricting the source account. The compliance officer asks which approach better satisfies least privilege and auditability, and whether either introduces a confused-deputy risk.
1. Compare the two proposals for least privilege, auditability, and confused-deputy risk. Recommend one and justify it.
Read the worked answer
Proposal 1 (assume a role in the security account): The app assumes a role owned by security. The trust policy on that role controls exactly which app principals may assume it, and the role's permissions can be scoped to PutObject only. This centralizes control in the security account, which matches the 'single source of truth' requirement. Auditability is strong because each write is attributed to the assumed role session, and the trust policy is visible to security only.
Proposal 2 (bucket policy granting app principals directly): The bucket policy names the app account principals. This also centralizes the grant in the bucket policy, but it requires the app account to still have an identity policy allowing the write (in most providers, cross-account access needs both sides to allow). That means app teams retain a lever, weakening the 'single source of truth' goal. It also risks a confused-deputy problem if the bucket policy grants to a broad principal without a condition tying the request to the intended account.
Recommendation: Proposal 1. The assumed role keeps the grant in the security account's trust and permission policies, gives clean session-level audit trails, and lets security revoke access by editing one trust policy. Add a condition on the trust policy requiring the calling account ID (and optionally an external ID) to prevent confused-deputy abuse. Proposal 2 is acceptable only as a defense-in-depth layer, not the primary control.
2. The compliance officer asks how to prove, during an audit, that no app account could read or delete logs over the past quarter. Describe the evidence you would collect and any gap you would disclose.
Read the worked answer
Collect: (1) the bucket policy and any ACLs, with version history showing no read/delete grants to app principals; (2) the trust policies of any roles app accounts can assume, showing permissions limited to PutObject; (3) access logs or a data-event trail showing only PutObject calls from app sessions and no GetObject/DeleteObject from app identities; (4) IAM/identity policy change history for the app accounts to show no widening.
Disclose the gap: policy documents prove current state, not historical state unless versioning of policies is enabled and retained. If policy version history was not retained for the full quarter, the auditor cannot rely on policy snapshots alone and must lean on access logs. Also note that logs themselves may be incomplete if data-event logging was not enabled for the bucket; that is a real evidentiary gap and should be stated rather than papered over.