- Newest
- Most votes
- Most comments
Hello.
"ForAnyValue" is considered an error because if there is no matching context key or the dataset is null, the condition returns false.
In other words, I think that the request context key does not include "aws:TagKeys", so it becomes False and causes an error in "StringEqualsIfExists".
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html
ForAnyValue – This qualifier tests whether at least one member of the set of request context key values matches at least one member of the set of context key values in your policy condition. The context key returns true if any one of the context key values in the request matches any one of the context key values in the policy. For no matching context key or a null dataset, the condition returns false.
I think this is correct, if not intuitive behaviour. It's caused by ...IfExists being part of the StringEquals comparison operator and not of the ForAnyValue set operator.
Your statement tells IAM to loop through all the values in aws:TagKeys and to return true if any of the values encountered either matches the string literal on the right side (=StringEquals) or is missing (...IfExists). Of course, it's logically impossible to encounter a non-existent value while iterating through a collection/array, which is why having an ...IfExists variant available for use in a loop is non-intuitive and can never make a difference to the outcome, as your example demonstrated.
The example of ForAnyValue:StringEqualsIfExists
in the link is simply an error in AWS's documentation. The example is evaluating aws:ResourceTag/SubnetType
, which is a single-valued condition key. ForAnyValue is a condition set operator, none of which are designed to work with single-valued condition keys. It's stated explicitly in the first bullet point on this page: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html
Since a resource tag key can have only a single tag value, aws:ResourceTag/tag-key is a single-valued context key. Do not use a condition set operator with a single-valued context key.
I understand your original scenario was just experimentation and isn't intended to make sense as such (allowing the operation if the "team" tag key is specified in the request -- but also if it isn't specified), but it would be expressed like this:
"Condition": {
"StringLikeIfExists": {
"aws:RequestTag/team": "*"
}
}
It would make practical sense if a list of allowed values were supplied in place of the single full wildcard "*". This would allow specifying any of the listed values for the "team" tag, or not specifying it at all, but wouldn't allow specifying any other value for it:
"Condition": {
"StringEqualsIfExists": {
"aws:RequestTag/team": ["teamA","teamB","teamC"]
}
}
Relevant content
- asked a year ago
- asked 3 years ago
- AWS OFFICIALUpdated 7 months ago
- AWS OFFICIALUpdated a year ago
- AWS OFFICIALUpdated a year ago
AWS has examples published which utilized
ForAnyValue:StringEqualsIfExists
. See: https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/deploy-preventative-attribute-based-access-controls-for-public-subnets.htmlI do understand that ForAnyValue would return false for no matching context key, but the purpose of the …IfExists variant of operators is to always evaluate the condition to true if the key is not present.
It seems like IfExists needs to have some affect when used with ForAnyValue, for AWS to include it in sample code.
I thought that the error might be occurring not because the value is Null, but because the key doesn't exist in the first place, since 'aws:TagKeys' is not included in the request context keys of the 'ListQueues' API. Therefore, I thought that it might not work for APIs where the request context key is not included in the first place.
Yeah I think that's the crux of the question.
ForAnyValue
is meant to behave one way when the key is missing, and…IfExists
is meant to behave the opposite way, so there's potentially a conflict. It seems like it would make sense for…IfExists
to have priority, though, because otherwiseForAnyValue
behaves the same with and without…IfExists
. Meaning, if…IfExists
has priority, that's a choice of how the policy should behave, and ifForAnyValue
has priory, there is no choice.I've received confirmation from AWS Support that when both
ForAnyValue
and…IfExists
are present,ForAnyValue
is resolved first, so a missing condition key will always return false.