Skip to content

fix: read policy conditions and session tags in name order on all builds - #783

Open
LeeroyHannigan wants to merge 1 commit into
mainfrom
fix/780-sort-policy-documents
Open

LeeroyHannigan wants to merge 1 commit into
mainfrom
fix/780-sort-policy-documents

Conversation

@LeeroyHannigan

Copy link
Copy Markdown
Collaborator

On a build with serde_json's preserve_order feature, 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

bson declares serde_json with preserve_order, and Cargo turns the feature on for every crate in a build that compiles the MongoDB backend crate. That is a --features mongodb binary, and also any build of the whole workspace, such as CI's cargo build --release and cargo test --workspace. There a parsed JSON map keeps its written order. A build of the extenddb package 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 in extenddb_auth::policy::document that returns the entries in name order:

  • parse_conditions, for identity policies and permissions boundaries (through PolicyDocument::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_tags reports the first violation in these pairs, and duplicate_tag_key_ci names the later of two keys that differ only in case, so {"team": "a", "Team": "b"} reported Team on a preserve_order build and team elsewhere.

#780 proposed sorting the whole document after serde_json::from_str in PolicyDocument. That would not reach the other two loops: CreateRole's trust policy arrives through axum's Json extractor, and AssumeRole's session tags through serde_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): a Condition with the operators BadA and BadB reports unknown operator: BadA.
  • conditions_are_read_in_name_order (policy document): StringLike on aws:b and aws:a with Bool on aws:c gives the keys aws: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: Team then team, and duplicate_tag_key_ci names team.

cargo test --workspace, which CI runs, builds these crates with preserve_order. Locally:

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

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

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MongoDB build: a policy document with two faults reports a different first error than on the other backends

1 participant