Repository navigation
fix: read policy conditions and session tags in name order on all builds - #783
Open
LeeroyHannigan wants to merge 1 commit into
Open
LeeroyHannigan wants to merge 1 commit into
LeeroyHannigan wants to merge 1 commit into
Conversation
Any build that compiles the MongoDB backend crate, which includes a build of the whole workspace, depends on bson, which turns on serde_json's preserve_order feature for every crate in that build. There a parsed JSON map keeps the order it was written in; a build of the extenddb package without the MongoDB backend sorts it by name. Three loops over such maps stop at the first fault, so on a preserve_order build a request with two faults got an error chosen by written order: - parse_conditions, for identity policies and permissions boundaries, stopped at the first unknown operator or malformed value, and its conditions came out in written order. - validate_trust_condition, the trust policy check of CreateRole and the console, returned the first invalid operator. - session_tag_pairs, for object-form AssumeRole session tags, gave the pairs in which validate_iam_tags reports the first violation and duplicate_tag_key_ci names the later of two keys that differ only in case. All three now read the map through a by_name helper in extenddb_auth::policy::document, which returns the entries in name order. A sort of the whole document after serde_json::from_str in PolicyDocument would not reach the other two: CreateRole's trust policy arrives through axum's Json extractor, and AssumeRole's session tags through serde_json::from_slice. Unit tests check, each in both written orders: a policy Condition with two unknown operators reports the one whose name sorts first; conditions come out in name order of operator, then key; a trust policy Condition with two unknown operators reports the first in name order; and object-form session tags come out in name order, so duplicate_tag_key_ci names the same key. cargo test --workspace, which CI runs, builds these crates with preserve_order. With --features serde_json/preserve_order, extenddb-auth and extenddb-server pass; with the loops reading the maps directly, the four tests fail. Fixes #780
LeeroyHannigan
requested review from
amrith,
c33howard,
eliseong,
hitesh96db,
jcshepherd,
navareamol,
pdf-amzn and
robinnsc
as code owners
November 3, 2026 03:09
This branch has not been deployed
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.
On a build with
serde_json'spreserve_orderfeature, a policy document, a trust policy or a set of session tags with two faults got a different error than on other builds, chosen by the order the request wrote them in.Which builds
bsondeclaresserde_jsonwithpreserve_order, and Cargo turns the feature on for every crate in a build that compiles the MongoDB backend crate. That is a--features mongodbbinary, and also any build of the whole workspace, such as CI'scargo build --releaseandcargo test --workspace. There a parsed JSON map keeps its written order. A build of theextenddbpackage without the MongoDB backend (-p extenddb, as the Dockerfiles build it) sorts maps by name, so nothing changes there.Change
Three loops over a parsed map stop at the first fault. Each now reads the map through
by_name, a new helper inextenddb_auth::policy::documentthat returns the entries in name order:parse_conditions, for identity policies and permissions boundaries (throughPolicyDocument::from_json). It reported the first unknown operator or malformed value, and its conditions came out in written order, so a later check that names the first bad condition, such as the CIDR check, differed too.validate_trust_condition, the trust policy check of CreateRole and the console, which reported the first invalid operator.session_tag_pairs, for object-form AssumeRole session tags.validate_iam_tagsreports the first violation in these pairs, andduplicate_tag_key_cinames the later of two keys that differ only in case, so{"team": "a", "Team": "b"}reportedTeamon apreserve_orderbuild andteamelsewhere.#780 proposed sorting the whole document after
serde_json::from_strinPolicyDocument. That would not reach the other two loops: CreateRole's trust policy arrives through axum'sJsonextractor, and AssumeRole's session tags throughserde_json::from_slice. The loops are where the order is read.Tests
Each test runs both written orders:
two_unknown_operators_report_the_first_in_name_order(policy document): aConditionwith the operatorsBadAandBadBreportsunknown operator: BadA.conditions_are_read_in_name_order(policy document):StringLikeonaws:bandaws:awithBoolonaws:cgives the keysaws:c,aws:a,aws:b.validate_reports_the_first_bad_operator_in_name_order(trust policy):invalid Condition operator: BadA.session_tag_pairs_are_in_name_order:Teamthenteam, andduplicate_tag_key_cinamesteam.cargo test --workspace, which CI runs, builds these crates withpreserve_order. Locally:cargo +1.88.0 test --locked -p extenddb-auth -p extenddb-server: 276 and 252 passed (plus 3 doc tests).--features serde_json/preserve_order: the same counts passed. With the loops reading the maps directly, all four new tests fail there.cargo +1.97.0 fmt --all -- --checkandcargo +1.97.0 clippy -p extenddb-auth -p extenddb-server --all-targets -- -D warnings: clean.git merge-treeagainst the open PRs that edit these files (fix: limit failed logins per source address and bound bcrypt verification #718, fix(auth): match Arn condition values as IAM does and reject at write the values IAM rejects #692, fix(auth): follow IAM's rules for policy variables in condition values #541, fix(auth): expand policy variables in Resource and NotResource #535): no conflict. fix(server): honor explicit Deny in role trust policies #402 already conflicts with main inassume_role.rs, with the same 12 blocks with or without this change.IAM's and STS's answers to a request with two such faults were not measured; this change makes the builds agree with each other.
Fixes #780