feat(iam): policy variables and ForAllValues over keys with no values - #2528
Merged
Merged
Conversation
- Version 2012-10-17 policies expand ${...} policy variables in the
resource part of Resource / NotResource and in String* / Arn*
condition values: any single-valued context key (aws:username,
aws:userid, aws:PrincipalTag/<key>, ...), ${key, 'default'}
defaults, and ${*} / ${?} / ${$} for literal characters. Substituted
values are literal. A variable with no value matches no resource,
fails positive operators and satisfies inverted ones. Other policy
versions read ${...} literally.
- ForAllValues is true when the request has no value for the key, as
AWS documents; it evaluated to false.
- ForAllValues is vacuously true when the service populated the key with no values. A key never populated -- one fakecloud does not extract -- still safe-fails to false, so an unextracted key never grants. - ConditionContext::lookup falls back to plain context entries for a global key with no typed value, so SimulateCustomPolicy / SimulatePrincipalPolicy ContextEntries resolve aws:username and friends (also as policy variables). An empty entry now means "populated, no values" instead of "absent".
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.
Summary
The IAM evaluator ignored policy variables.
${aws:username}in aResourceor a condition value was compared as literal text, so one reusable policy could never scope each caller to their own prefix, team or partition. This is the standard pattern for S3 home folders, tag-scoped resources, and DynamoDB fine-grained access control (dynamodb:LeadingKeys = ${aws:userid}). This PR adds policy variables and fixes howForAllValuestreats a key with no values.Behavior follows the IAM User Guide ("IAM policy elements: Variables and tags" and "Single-valued vs. multivalued context keys").
Policy variables
Version: "2012-10-17"policies, in the resource part ofResource/NotResourceARNs (after the fifth colon), and inString*/Arn*condition values. In any other version${...}stays literal, as on AWS.aws:username,aws:useridoraws:PrincipalTag/<key>, plus service keys. Key names are case-insensitive. A multivalued key can't be used as a variable.${key, 'default'}uses the default when the key has no value.${*},${?}and${$}stand for a literal*,?and$.*inside a principal tag is not a wildcard, so a tag value cannot widen what a policy grants.StringEquals,StringLike,ArnLike, ...) never match it, and inverted ones (StringNotEquals,StringNotLike, ...) do, as documented.ForAllValueswith no valuesAWS documents that
ForAllValuesis true when the request has no values for the key, and the evaluator returned false. That is fixed with one guard. The vacuous truth applies only when the service actually populated the key and there are no values in it (an empty entry). A key fakecloud never populated for the request may simply be one it doesn't extract, so it still fails the condition. An unextracted key never grants access.Context lookup
ConditionContext::lookupnow falls back to plain context entries for a global key with no typed value, tag keys included (the tag-key part compares exactly). SoSimulateCustomPolicy/SimulatePrincipalPolicyContextEntriesforaws:username,aws:TagKeys,aws:RequestTag/<key>and so on now resolve, including as policy variables. Before, they were ignored and the key was reported inMissingContextValues. A typed value still wins, so an entry can't override a key dispatch filled in.Test plan
policy_variables.rsunit tests: expansion, case-insensitive keys, defaults, special characters, literal substituted values, and resource-part-only expansion.ForAllValuestrue on a populated key with no values but false on an unpopulated key, andForAnyValuefalse in both casespolicy_variables_scope_one_policy_per_caller(iam_enforcement_abac, strict mode, S3):${aws:username}and${aws:PrincipalTag/team, 'no-team'}resources allow the caller's own prefixes and deny others.simulate_custom_policy_resolves_policy_variables_from_context_entries.cargo test -p fakecloud-iam(552) and-p fakecloud-core(321)iam_enforcement(50),iam_enforcement_abac(10),_boundary(5),_session_policy(4),_scheduler(3),iam_simulate(9),multi_account(6),ecr_cross_account(3): pass-D warnings(core, iam, e2e) andcargo fmt --all --check: cleanSurface
reference/security.mddescribes policy variables and theForAllValuesrule;services/iam.mdlists policy variables.Summary by cubic
The IAM evaluator previously treated
${aws:username}inResourceand condition values as literal text, andForAllValuesreturned false when the request had no values for a populated key. NowVersion: 2012-10-17policies expand supported policy variables, andForAllValuesfollows AWS's documented vacuous truth.2012-10-17policies, in the resource part ofResource/NotResourceARNs and inString*/Arn*condition values; other versions keep${...}literal.aws:username,aws:PrincipalTag/<key>, service keys), support${key, 'default'},${*},${?},${$}, and substituted values are literal (a*in a tag is not a wildcard).ForAllValuesis now true when the service populated the key and the request carries no values; a key fakecloud never populated still fails, so it never grants.ConditionContext::lookupnow falls back to plain context entries for global and tag keys, soSimulateCustomPolicy/SimulatePrincipalPolicyContextEntriesresolveaws:username,aws:TagKeys, etc., as variables and conditions.Written for commit 8ec597b. Summary will update on new commits.