fix(batch): skip deleted policies a mapping still names

Deleting a policy checks that no user or group mapping names it, but not
the STS mappings of OpenID parent users and LDAP user DNs. After such a
deletion the request path (MergePolicies) skips the confirmed-absent
policy and decides on the remaining mapped policies, while batch
authorization treated the absent document as a denial of the whole
action: jobs of such a submitter ended refused, although the same
principal's requests were allowed.

batchLocalPolicies now skips a policy document whose load reports that it
does not exist, as MergePolicies does, and still decides on the remaining
policies. Any other failure to read a document, and a load that returns
no document, still ends the attempt as unavailable, since it could hide a
Deny. With every mapped policy absent nothing allows the action, so the
job is refused as before.

TestBatchAuthorizeSkipsDeletedMappedPolicy maps an STS parent user to two
policies, deletes one, and requires the batch decision to agree with the
request decision, allowed with the other policy and denied once both are
deleted. Before this change the batch decision was a refusal while the
request was allowed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
Feng Ruohang
2026-11-07 16:04:51 +08:00
parent 9f9398a1a3
commit 5fb983d3d2
2 changed files with 55 additions and 2 deletions
+9 -2
View File
@@ -688,12 +688,19 @@ func (sys *IAMSys) batchLocalPolicies(p batchJobPrincipal, args policy.Args, wit
doc, ok := cache.iamPolicyDocsMap[name]
if !ok {
loaded := make(map[string]PolicyDoc)
if err := snap.loadPolicyDoc(name, loaded); err != nil {
err := snap.loadPolicyDoc(name, loaded)
if errors.Is(err, errNoSuchPolicy) {
// Confirmed absent, as when a mapping still names a
// deleted policy: it takes no part in the decision, as
// in MergePolicies. Any other failure could hide a Deny.
continue
}
if err != nil {
return nil, err
}
doc, ok = loaded[name]
if !ok {
return nil, errNoSuchPolicy
return nil, fmt.Errorf("load IAM policy %q returned no document", name)
}
}
selected = append(selected, doc.Policy)