Skip to content

Instantly share code, notes, and snippets.

@jstewmon
Last active August 8, 2024 04:23
Show Gist options
  • Save jstewmon/ee5d4b7ec0d8d60cbc303cb515272f8a to your computer and use it in GitHub Desktop.
Save jstewmon/ee5d4b7ec0d8d60cbc303cb515272f8a to your computer and use it in GitHub Desktop.
AWS IAM Policy JSON Schema
{
"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"
}
}
}
}
}
@jstewmon
Copy link
Author

jstewmon commented Sep 9, 2021

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.

@LeePorte
Copy link

LeePorte commented Jun 9, 2022

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

@rrrix
Copy link

rrrix commented Sep 14, 2022

This is why I love open source :) :)

@Edgar-P-yan
Copy link

Hi! The schema is awesome. Wanted to mention this:

  1. Principal and NotPrincipal are also mutually exclusive, so i would add:
"oneOf": [
  { "required": ["Principal"] },
  { "required": ["NotPrincipal"] }
]
  1. 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

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