A batch job is authorized without a request, so a policy statement that
depends on request context the job does not have (source address,
transport, headers) was taken to refuse the action. Two parts of that
rule refused jobs that no request would refuse:
- The scan for unsupplied policy variables ran over the whole statement
before its resources were matched. A Deny on an unrelated bucket whose
condition value held a variable such as ${aws:UserAgent} refused every
job of the user. Resources are now matched first; a variable in a
resource still means the statement may apply.
- An Allow that needs absent context, such as an IP-restricted read,
refused the job even when another Allow granted the action. Such an
Allow now grants nothing to the job: it is dropped from the policy that
is evaluated, not merely exempted, since IfExists and Null conditions
hold for an absent key and would grant. Dropping an Allow can only
narrow the decision. A Deny that needs the context still refuses.
The narrowed policy is a new policy.Policy, because the statement index
of the original points into its own statements and the original may be a
cached document. For a session policy, whether one applies and its first
decision still come from the claims as before; only an allow is
re-evaluated on the narrowed policy.
Tests cover an unrelated Deny with a variable, a Deny with an unsupplied
variable in its resource, an IP-restricted Allow next to a plain one, a
Null Allow that plain evaluation without the address would grant, and
the same for session policies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>