Repository navigation
acl/v2: add the v2 ACL format and validator - #360
Open
shubh-stripe wants to merge 1 commit into
Open
shubh-stripe wants to merge 1 commit into
shubh-stripe wants to merge 1 commit into
Conversation
shubh-stripe
force-pushed
the
shubh/aclv2-2-policy
branch
from
October 28, 2026 20:43
d07a3d0 to
d4b8b71
Compare
A v2 ACL keeps v1's shape of one entry per service, and adds structure where v1 hides behavior. A service has allow entries, each holding domains and its options, so MITM sits on the allow entry it applies to. A domain is a string or a mapping that sets cross_public_suffix for that domain only. Service and global deny lists are plain strings, and a deny glob always matches across public suffixes, as v1's global deny list does, so a deny list is as broad as it reads. A service allow entry can win over the global deny list only when it sets override_global_policy: true, so every exception is visible on the entry that makes it. By default, a service allow entry that overlaps the global deny list without the field fails validation. Options.Compat keeps the v1 behavior for these entries and reports each one as a warning, so existing ACLs have a migration path. Parsing is strict: unknown keys, a second YAML document, and a version other than v2 are errors, including inside a domain mapping, which yaml.Node.Decode does not check on its own. A policy marshals back to YAML that Parse accepts. The overlap check compares globs by concrete host rules, not by glob text, so it can't be bypassed by spelling a domain differently in the two lists. For two confined label wildcards it compares every label, so sts.* against iam.*, or api* against admin*, is not flagged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Committed-By-Agent: claude
shubh-stripe
force-pushed
the
shubh/aclv2-2-policy
branch
from
October 31, 2026 07:55
d4b8b71 to
48fa07d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #359, which moves the glob matcher to
acl/v2. This PR adds the v2 ACL format and its validator. It has no engine yet, and nothing decides with it. The engine comes in the next PR.Shape
cican reachpypi.orgbecause its allow entry setsoverride_global_policy: true. The exception covers only the domains of that entry, socistill can't reachgithub.com. If the field is missing, the file fails to load.What changes
A v2 ACL keeps one entry per service, as v1 does, and makes these rules explicit:
allowentries. Each entry holds its domains and options, so a MITM config sits on the entry it applies to. v1 needed a separatemitm_domainslist that repeated each domain.denylists are plain strings. A deny glob always matches across public suffixes, the same as v1's global deny list, so a deny list blocks every host that its text describes.cross_public_suffixfor that domain only. v1 used one flag for the whole file.global.denyonly if it setsoverride_global_policy: true. Validation rejects a service allow entry that overlapsglobal.denywithout the field.Options.Compatkeeps the v1 behavior for these entries: the ACL loads, and validation reports each entry toOptions.Warn. This gives existing ACLs a migration path. The CLI flag comes in a later PR.Parsing is strict. Unknown keys, a second YAML document and a version other than
v2are errors. This includes unknown keys inside a domain mapping, whichyaml.Node.Decodedoes not check by itself. A policy also marshals back to YAML thatParseaccepts.LoadFilesjoins several files into one policy, so you can split an ACL by service.The overlap check compares globs by the rules that match hosts, not by glob text. Spelling a domain differently in the two lists does not hide an overlap. For two label wildcards, the check compares every label, so
sts.*againstiam.*andapi*againstadmin*are not flagged.Test plan
Table tests cover parsing (including unknown keys, multiple documents and a mapping in a deny list), the marshal round trip, validation in strict and compat modes,
LoadFiles, and the overlap check (case, a trailing dot, the wildcard forms, differing fixed labels, sibling labels,cross_public_suffix, and deny globs that cross public suffixes).I also checked locally that a translated v1 ACL gives the same decision as v1 for about 85,000 requests. I checked two ways: with
override_global_policyset on overlapping entries in strict mode, and with no fields set in compat mode.🤖 Generated with Claude Code