-
-
Save jstewmon/ee5d4b7ec0d8d60cbc303cb515272f8a to your computer and use it in GitHub Desktop.
{ | |
"type": "object", | |
"required": ["Statement"], | |
"additionalProperties": false, | |
"properties": { | |
"Version": { | |
"type": "string", | |
"enum": ["2008-10-17", "2012-10-17"] | |
}, | |
"Id": { | |
"type": "string" | |
}, | |
"Statement": { | |
"oneOf": [ | |
{ | |
"$ref": "#/definitions/Statement" | |
}, | |
{ | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/Statement" | |
} | |
} | |
] | |
} | |
}, | |
"definitions": { | |
"aws-arn": { | |
"type": "string", | |
"pattern": "^arn:aws:[^:]+:[^:]*:(?:\\d{12}|\\*)?:.+$" | |
}, | |
"aws-principal-arn": { | |
"type": "string", | |
"pattern": "^arn:aws:iam::\\d{12}:(?:root|user|group|role)" | |
}, | |
"string-array": { | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
}, | |
"string-or-string-array": { | |
"anyOf": [ | |
{ | |
"type": "string" | |
}, | |
{ | |
"$ref": "#/definitions/string-array" | |
} | |
] | |
}, | |
"wildcard": { | |
"const": "*" | |
}, | |
"condition-set-value": { | |
"type": "object", | |
"additionalProperties": { | |
"$ref": "#/definitions/string-array" | |
} | |
}, | |
"condition-value": { | |
"type": "object", | |
"additionalProperties": { | |
"anyOf": [ | |
{ "$ref": "#/definitions/string-or-string-array" }, | |
{ "type": "boolean" }, | |
{ "type": "number" } | |
] | |
} | |
}, | |
"Statement": { | |
"allOf": [ | |
{ | |
"oneOf": [{ "required": ["Action"] }, { "required": ["NotAction"] }] | |
}, | |
{ | |
"oneOf": [ | |
{ "required": ["Resource"] }, | |
{ "required": ["NotResource"] } | |
] | |
}, | |
{ | |
"type": "object", | |
"required": ["Effect"], | |
"additionalProperties": false, | |
"properties": { | |
"Sid": { | |
"type": "string" | |
}, | |
"Effect": { | |
"type": "string", | |
"enum": ["Allow", "Deny"] | |
}, | |
"Action": { | |
"$ref": "#/definitions/Action" | |
}, | |
"NotAction": { | |
"$ref": "#/definitions/Action" | |
}, | |
"Principal": { | |
"$ref": "#/definitions/Principal" | |
}, | |
"NotPrincipal": { | |
"$ref": "#/definitions/Principal" | |
}, | |
"Resource": { | |
"$ref": "#/definitions/Resource" | |
}, | |
"NotResource": { | |
"$ref": "#/definitions/Resource" | |
}, | |
"Condition": { | |
"$ref": "#/definitions/Condition" | |
} | |
} | |
} | |
] | |
}, | |
"Action": { | |
"anyOf": [ | |
{ | |
"$ref": "#/definitions/wildcard" | |
}, | |
{ | |
"$ref": "#/definitions/string-or-string-array" | |
} | |
] | |
}, | |
"Principal": { | |
"anyOf": [ | |
{ | |
"$ref": "#/definitions/wildcard" | |
}, | |
{ | |
"type": "object", | |
"properties": { | |
"AWS": { | |
"anyOf": [ | |
{ | |
"$ref": "#/definitions/wildcard" | |
}, | |
{ | |
"$ref": "#/definitions/aws-principal-arn" | |
}, | |
{ | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/aws-principal-arn" | |
} | |
} | |
] | |
}, | |
"Federated": { | |
"$ref": "#/definitions/string-or-string-array" | |
}, | |
"CanonicalUser": { | |
"$ref": "#/definitions/string-or-string-array" | |
} | |
} | |
} | |
] | |
}, | |
"Resource": { | |
"anyOf": [ | |
{ | |
"$ref": "#/definitions/wildcard" | |
}, | |
{ | |
"$ref": "#/definitions/aws-arn" | |
}, | |
{ | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/aws-arn" | |
} | |
} | |
] | |
}, | |
"Condition": { | |
"type": "object", | |
"properties": { | |
"Null": { | |
"type": "object", | |
"additionalProperties": { | |
"enum": ["true", "false", true, false] | |
} | |
}, | |
"StringEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringNotEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringEqualsIgnoreCase": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringNotEqualsIgnoreCase": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringLike": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringNotLike": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericNotEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericLessThan": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericLessThanEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericGreaterThan": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericGreaterThanEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateNotEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateLessThan": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateLessThanEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateGreaterThan": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateGreaterThanEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"Bool": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"BinaryEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"IpAddress": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NotIpAddress": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"ArnEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"ArnNotEquals": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"ArnLike": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"ArnNotLike": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringNotEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringEqualsIgnoreCaseIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringNotEqualsIgnoreCaseIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringLikeIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"StringNotLikeIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericNotEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericLessThanIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericLessThanEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericGreaterThanIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NumericGreaterThanEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateNotEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateLessThanIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateLessThanEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateGreaterThanIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"DateGreaterThanEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"BoolIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"BinaryEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"IpAddressIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"NotIpAddressIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"ArnEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"ArnNotEqualsIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"ArnLikeIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"ArnNotLikeIfExists": { | |
"$ref": "#/definitions/condition-value" | |
}, | |
"ForAllValues:StringEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:StringNotEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:StringEqualsIgnoreCase": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:StringNotEqualsIgnoreCase": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:StringLike": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:StringNotLike": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:NumericEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:NumericNotEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:NumericLessThan": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:NumericLessThanEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:NumericGreaterThan": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:NumericGreaterThanEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:DateEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:DateNotEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:DateLessThan": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:DateLessThanEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:DateGreaterThan": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:DateGreaterThanEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:Bool": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:BinaryEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:IpAddress": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:NotIpAddress": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:ArnEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:ArnNotEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:ArnLike": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAllValues:ArnNotLike": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:StringEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:StringNotEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:StringEqualsIgnoreCase": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:StringNotEqualsIgnoreCase": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:StringLike": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:StringNotLike": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:NumericEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:NumericNotEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:NumericLessThan": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:NumericLessThanEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:NumericGreaterThan": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:NumericGreaterThanEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:DateEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:DateNotEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:DateLessThan": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:DateLessThanEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:DateGreaterThan": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:DateGreaterThanEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:Bool": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:BinaryEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:IpAddress": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:NotIpAddress": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:ArnEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:ArnNotEquals": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:ArnLike": { | |
"$ref": "#/definitions/condition-set-value" | |
}, | |
"ForAnyValues:ArnNotLike": { | |
"$ref": "#/definitions/condition-set-value" | |
} | |
} | |
} | |
} | |
} |
Hmm... according to the grammar, number is allowed as a condition value. Did you check whether the AWS service accepts your policy with a JSON number as the condition value?
Yeh - nice link! - thats what I mean number is not in the Schema : you have
"$ref": "#/definitions/string-or-string-array" or enum for condition value
Good idea to try it - we are using the schema for SCP validation but it seems the SCP console is pretty "accpeting"- I will try it in the IAM policy to see whats allowed
Definitely an awesome start!
Just looking at the required section for the 'Statement' you have 'Action' and 'Resource' in there but they are mutually exclusive with their 'NotAction' and 'NotResource' counterparts. IE you could have a valid statement with a 'NotAction' and no 'Action' but the schema validation would fail. I'm trying to resolve these requirements at the moment with the following...
"allOf": [
{
"required": [
"Effect"
]
},
{
"oneOf": [
{
"required": [
"Action"
]
},
{
"required": [
"NotAction"
]
}
]
},
{
"oneOf": [
{
"required": [
"Resource"
]
},
{
"required": [
"NotResource"
]
}
]
}
]
Also, looking at the grammer (and something which tripped me up), the statement can be both an 'array' and an 'object' (single statement).
Thanks for the feedback! I updated the gist accordingly.
n.b. I did some cursory testing, but I'm not using this schema myself, so no warranties, etc.
I have come up against an issue in that if you use the Action of sts:AssumeRole
the schema causes failure due there being no Resource present.
e.g. from https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_policy-examples.html
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"elasticmapreduce.amazonaws.com",
"datapipeline.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
I've posted a gist which fixes this over at https://gist.github.com/LeePorte/16825880f7eac126555b9aa3bda1cf22
It adds in the ability to have a Service
as a principal which validates against the pattern of .+.amazonaws.com$
and has some if else logic as to weather to apply
"oneOf": [
{ "required": ["Resource"] },
{ "required": ["NotResource"] }
]
based on if the Action is sts:AssumeRole
This is why I love open source :) :)
Hi! The schema is awesome. Wanted to mention this:
Principal
andNotPrincipal
are also mutually exclusive, so i would add:
"oneOf": [
{ "required": ["Principal"] },
{ "required": ["NotPrincipal"] }
]
- Seems like the array of statements cant be empty, so i'd add
"minLength": 1
"Statement": {
"oneOf": [
{
"$ref": "#/definitions/Statement"
},
{
"type": "array",
"minLength": 1,
"items": {
"$ref": "#/definitions/Statement"
}
}
]
}
Thanks a lot for the schema, it saved me some time :D
Super Schema!
Out of interest would numeric be allowed here https://gist.github.com/jstewmon/ee5d4b7ec0d8d60cbc303cb515272f8a#file-aws-iam-poilcy-schema-json-L198
We had 0 as a value but the schema wants it to be a string "0"