Policy JSON, condition operators and the keys that matter
The policy elements and which ones exclude each other, how Condition blocks combine, every operator family with its traps (missing keys, IfExists, ForAllValues), the global keys agents use most, and where to look up exact action names.
markdownreferencev4NV25-312Xstage: referencetrust: officialservice: iaminterface: iacpolicy grammarpolicy elementsConditioncondition operatorsStringEqualsStringLikeArnLikeBoolNullIfExistsForAllValuesForAnyValuepolicy variablesglobal condition keysService Authorization Reference
Policy grammar and conditions
Never guess an action, resource type or condition key name. Look it up for the exact service (last section), write the narrowest statement, and remember the rule that catches most agents: a condition on a key the request does not carry evaluates to false, so an Allow silently stops applying, except with negated operators and IfExists, which flip that.
Elements
A policy has a Version and one or more Statement entries. Each statement has an Effect (Allow or Deny), what it applies to, and optionally a Sid and a Condition. Element order does not matter.
| Element | Notes |
|---|---|
Principal / NotPrincipal | Only in resource-based policies (including trust policies); an identity-based policy cannot contain Principal. |
Action / NotAction | service-prefix:ActionName; * and ? wildcards allowed. |
Resource / NotResource | ARNs; the ARN format for each resource type is in the service reference. |
Condition | Optional; see below. |
Each pair is mutually exclusive in one statement: Action or NotAction, Principal or NotPrincipal, Resource or NotResource. Use "Version": "2012-10-17".
How a Condition block combines
"Condition": {
"StringEquals": { "aws:PrincipalOrgID": "o-example", "aws:SourceVpce": ["vpce-1111aaaa", "vpce-2222bbbb"] },
"Bool": { "aws:SecureTransport": "true" }
}
- Several values under one key: OR. Either endpoint above matches.
- Several keys, or several operators: AND. Every key under every operator must match.
- In a Deny, the same AND applies: the Deny only fires when all of its conditions match.
- Condition key names are case-insensitive. Two request keys differing only in case can make a condition behave unexpectedly.
Operators and their traps
| Family | Operators | Notes |
|---|---|---|
| String | StringEquals, StringNotEquals, StringEqualsIgnoreCase, StringNotEqualsIgnoreCase, StringLike, StringNotLike | Equals and Like are case-sensitive; Like supports * and ?. |
| ARN | ArnEquals, ArnLike, ArnNotEquals, ArnNotLike | ArnEquals and ArnLike behave the same; each of the six ARN fields is matched separately and may contain wildcards. Use for aws:SourceArn, aws:PrincipalArn. |
| Numeric | NumericEquals, …NotEquals, …LessThan(Equals), …GreaterThan(Equals) | No wildcards, no policy variables. |
| Date | DateEquals, …NotEquals, …LessThan(Equals), …GreaterThan(Equals) | ISO 8601 or epoch; with aws:CurrentTime, aws:EpochTime, aws:TokenIssueTime. |
| Bool | Bool | true / false. |
| IP | IpAddress, NotIpAddress | CIDR; a bare address means /32. aws:SourceIp is absent through a VPC endpoint, and is the calling service's IP when a service calls on your behalf. |
| Binary | BinaryEquals | Base64 value. |
| Presence | Null | "true" = key absent, "false" = key present. |
Missing keys. A plain operator on an absent key is false. A negated operator (StringNotEquals, ArnNotLike, …) on an absent key is true. That is why a Deny with a negated operator also denies requests that lack the key.
IfExists (on any operator except Null): if the key is present, test it; if absent, the condition is true. Use it when one statement covers several resource types and only some carry the key. With Deny and a negated …IfExists operator, a missing key still leads to a deny.
MFA. aws:MultiFactorAuthPresent is absent for long-term access keys and federated identities. A Deny using "BoolIfExists": {"aws:MultiFactorAuthPresent": "false"} therefore also blocks scripts using access keys. A plain Bool with false is not a reliable MFA check.
Multivalued keys: ForAllValues and ForAnyValue
For keys that carry a set (such as aws:TagKeys), prefix a string, ARN or Bool operator:
| Qualifier | True when |
|---|---|
ForAnyValue: | at least one request value matches |
ForAllValues: | every request value matches one of the policy values |
ForAllValues:…Not… | no request value matches |
ForAnyValue:…Not… | at least one request value does not match |
Trap: ForAllValues is true when the key is missing or empty, so an Allow restricted with it can be satisfied by sending nothing. Pair it with a Null check that requires the key:
"Condition": {
"ForAllValues:StringEquals": { "aws:TagKeys": ["environment", "team"] },
"Null": { "aws:TagKeys": "false" }
}
Policy variables
${aws:username}, ${aws:PrincipalTag/<key>} and similar work with string, ARN and Bool operators. They do not work with numeric, date, IP, binary or Null operators.
Global keys agents use most
| Key | Holds | Note |
|---|---|---|
aws:PrincipalArn | ARN of the caller; for a role session, the role ARN, not the session ARN | Survives role deletion and recreation, unlike a Principal ARN |
aws:PrincipalOrgID | Organization ID of the caller | Org-wide grants without listing accounts |
aws:SourceArn / aws:SourceAccount | The resource or account a service is acting for | Confused-deputy protection on resource policies; aws:SourceAccount exists only for direct service-principal calls |
aws:SourceOrgID / aws:SourceOrgPaths | The organization or OU path a service is acting for | Same, at organization scope |
aws:SourceVpce | VPC endpoint ID | Present only on the endpoint path |
aws:SourceIp | Caller IP | Absent through VPC endpoints |
aws:SecureTransport | Whether TLS was used | Deny "false" to require TLS |
aws:MultiFactorAuthPresent | MFA on temporary credentials | Absent for long-term keys; use BoolIfExists |
aws:TokenIssueTime | When temporary credentials were issued | Absent for long-term keys; "Null": {"aws:TokenIssueTime": "false"} requires temporary credentials |
aws:userid | Caller's unique ID | Allow-lists keyed on it are a common explicit-deny cause |
Looking up exact names
- Service Authorization Reference: the page per service lists every action, the resource types it authorizes, and the service-specific condition keys.
- Machine-readable service reference:
https://servicereference.us-east-1.amazonaws.com/lists services with a JSON URL each (for example…/v1/s3/s3.json), giving actions with their condition keys and resource types, condition key types, resource ARN formats, and operation-to-action mappings with SDK method names.…/v1/mapping.jsonmaps SDK service names to entries. Updates can take up to 24 hours to appear. Each action carriesIsList,IsWrite,IsPermissionManagementandIsTaggingOnlyflags; filtering onIsPermissionManagementfinds the actions that can change permissions.
An operation may need more than one action (S3 GetObject can authorize several); the operations section of the service reference lists them where the service supports that mapping.