Post

AWS Trivia: Why Do IAM Policies Almost Always Use Version 2012-10-17?

Why do AWS IAM policies almost always use Version 2012-10-17? This post explains what that version actually means, how it differs from service API versions, and what happens if you leave it out.

AWS Trivia: Why Do IAM Policies Almost Always Use Version 2012-10-17?

If you work with AWS, you have probably seen IAM policies with Version set to 2012-10-17 over and over again.

1
2
3
4
5
6
7
8
9
10
{
  "Version":"2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    }
  ]
}

If you are seeing it for the first time, you probably have the same questions most people do:

  • Why is it always this date?
  • AWS keeps evolving, so why does the version not change?

In this post, I will break down what that date actually means and why it shows up so often.

Why Do IAM Policies Use Version 2012-10-17

Short answer: 2012-10-17 is the version of the IAM policy language. It is not a single API version shared across all AWS services.

Each AWS service has its own API version. For example:

So the accurate way to put it is this: IAM policies commonly use 2012-10-17, but that does not mean every AWS API uses the same version.

Why 2012-10-17 Specifically

The most widely accepted explanation is that 2012-10-17 marks a major update to the IAM policy language.

That version introduced policy variables such as ${aws:username} and ${aws:PrincipalTag}, making it possible to write policies that scale much more cleanly across users and roles.

That is why 2012-10-17 became the de facto standard you see in most IAM policies today.

What Happens If You Leave Out Version

If you leave out Version, AWS falls back to the older 2008-10-17 behavior.

In that case, strings like ${aws:username} may be treated as literal text instead of policy variables.

Where You Still See 2008-10-17

If you look through AWS accounts that were created before 2012 and never fully cleaned up, you will often find inline policies with no Version field at all.

Officially, if Version is completely omitted from a JSON policy document, IAM defaults to the 2008-10-17 policy language behavior.

That means plenty of “hidden” 2008-era policies are still hanging around in older environments.

You can also still run into 2008-10-17 when the AWS Console generates policy JSON for certain resources. In most cases, this is there for backward compatibility with older systems and APIs, not because 2012-10-17 is unsupported.

  • SQS queue policies: when you click “Edit policy” in the SQS console, the generated template is often still 2008-10-17.
  • SNS topic policies: similar to SQS, the default access policy JSON often still uses the 2008 format.
  • VPC endpoint policies (gateway type only): for example, gateway endpoints for S3 or DynamoDB often still show policy language marked as 2008.

Why These Older Versions Are Not Automatically Upgraded

This mostly comes down to how the underlying service APIs were designed, such as SQS SetQueueAttributes.

  • API compatibility: many resource policies are managed through service-specific APIs rather than the IAM API. Those APIs were defined years ago, so AWS keeps the defaults stable to avoid breaking existing automation.
  • Simpler policy needs: in many SQS and SNS use cases, a basic allow or deny on a specific ARN is enough, so the newer policy variable features are often unnecessary.

Will There Ever Be a New Version

A new version is certainly possible, but there is no official announcement right now.

If AWS ever introduces a new version, it will likely keep the older one around for compatibility so existing policies do not break overnight. In practice, though, you should usually use the newer version whenever possible.

References

This post is licensed under CC BY 4.0 by the author.