Two failures in one week. (1) A service's role allows `s3:GetObject` on `arn:aws:s3:::reports/*`, nothing on the role denies anything, yet a batch job using a library that defaulted to plain HTTP gets `AccessDenied`. (2) An analytics account's role is given a bucket policy statement allowing it to read the same bucket, and it is still denied. Walk the evaluation for each.
IAM evaluation is not first-match and not file order. Every applicable policy is considered, identity and resource together: first any matching explicit Deny anywhere ends it; otherwise an Allow in either the identity policy or the resource policy is enough within one account; otherwise the default deny stands. (1) The bucket policy has a Deny on requests where aws:SecureTransport is false. The request was plain HTTP, the deny matches, and it wins before the role's allow is even relevant; adding more allows cannot help, and the fix is the client using TLS. (2) Across accounts one side is not enough: the resource owner's policy must allow the external principal and that principal's own identity policy must allow the action. The analytics role has no identity policy granting s3:GetObject on this bucket, so it is denied.