AWS
Security
Outdated Default AWS IAM Policy Language Versions
Overview #
The AWS Identity and Access Management (IAM) service is used to securely control access to AWS resources and can be expressed in JSON as IAM policies. The
Version
element of the JSON policy specifies which language syntax rules are used when processing the policy.There are 2 possible
Version
element values: 2012-10-17
and 2008-10-17
. The 2008-10-17
version is an earlier version that does not support newer features such as policy variables and AWS recommends not to use this version for any new policies or when updating existing policies. After going through all services that support IAM resource-based policies and identity-based policies, we found multiple AWS services that used the legacy 2008-10-17
policy version, including Gateway VPC Endpoint Policies, SNS Topic Policies, and SQS Queue Policies.We sent details on our research and our thoughts regarding developer experience on outdated policy versions and default behavior to the AWS Security team on February 8th, 2023. This came up as a discussion point in an AWS Security online community regarding SNS Topic policies and we did further research on other default and example policies across all AWS services.
In this post, we will cover the IAM Policy Language Version and what that means, our research on which services have default legacy versions, the user experience in AWS when specifying the policy version, how to find default legacy versions in your AWS environment, and recommendations.
IAM Policy Language Version #
A lesser known detail about IAM policy grammar is the policy
Version element
. This is not the different versions of IAM policies that can be created for managed policies via CreatePolicyVersion
. We're referring to the snippet of "Version": "2008-10-17"
or "Version": "2012-10-17"
that may be included in an IAM policy. This Version
specifies which language syntax rules are used when processing the IAM policy.In AWS console and even in the CLI/API, there are default and example policies that leverage the legacy interpretation of the IAM policy language which can create issues for developers. IAM is one of the building blocks in AWS and often can be a source of headaches for developers to properly configure permissions and access for applications, let alone focus on least privilege and properly defined IAM permissions. By using the legacy
2008-10-17
version of the policy language, this can lead to misconfiguration and development time spent troubleshooting differences in language syntax rules such as policy variables being treated as literal strings in the policy.There are 3 different implicit and explicit settings for the
Version
element:- Explicit
2012-10-17
- Explicit
2008-10-17
- Implicit
2008-10-17
: NoVersion
specified.
The
Version
element can be present in both identity-based policies and resource-based policies among other policy types."Version": "2008-10-17",
"Id": "OutdatedVersionElement",
"Statement": [
{
"Sid": "ExampleStatement",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"SQS:ReceiveMessage"]
}
...
Identity-Based Policies and Their Versions #
There are 4 types of identity-based policies that we will take a look at:
AWS has controls that block the creation of IAM managed policies with legacy policy versions. The following screenshots show the mechanisms for blocking a policy created without
2012-10-17
specified in the policy version. In console, an error message pops up about the version string.With the AWS CLI, we get a `MalformedPolicyDocument`` error:
However, these controls are inconsistent and do not apply to inline policies. Inline policies still can be created with legacy policy versions of
2008-10-17
or with no Version
specified.We used the following JSON as our policy:
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "ListPolicies",
"Effect": "Allow",
"Action": ["iam:ListPolicies"],
"Resource": "*"
}
]
}
The following command to put an inline policy on our
cloudquery-user
user succeeded:aws iam put-user-policy \
--user-name cloudquery-user \
--policy-name test-cq-policy \
--policy-document file://2008policyversion.json
Finding Identity-Based Policies with CloudQuery #
The below queries have a prerequisite to use CloudQuery to sync AWS data to PostgreSQL. For a guide, see our quickstart guide.
We will use CloudQuery to check for identity-based with
2008-10-17
explicitly set as the version or for identity-based policies without an explicit version set.Finding IAM User Inline Policies
SELECT * FROM
(
SELECT policy_document ->> 'Version' as version, *
FROM aws_iam_user_policies
) as user_policies
WHERE version = '2008-10-17'
OR version is NULL;
Finding IAM Group Inline Policies
SELECT * FROM
(
SELECT policy_document ->> 'Version' as version, *
FROM aws_iam_group_policies
) as group_policies
WHERE version = '2008-10-17'
OR version is NULL;
Finding IAM Role Inline Policies
SELECT * FROM
(
SELECT policy_document ->> 'Version' as version, *
FROM aws_iam_role_policies
) as role_policies
WHERE version = '2008-10-17'
OR version is NULL;
Resource-Based Policies and Their Versions #
In our research, we found 3 types of resource-based policies with default versions set to
2008-10-17
:The below table shows the AWS services we tested based on AWS Services that work with IAM. From our research, we found some services default to
2012-10-17
, some services default to 2008-10-17
, some services default to empty policies (Empty), and some services did not support writing full IAM policy JSON.AWS Service | Default Policy Version Element | Comments |
---|---|---|
AWS SQS | 2008 | Both Console and API/CLI |
AWS SNS | 2008 | Both Console and API/CLI |
AWS VPC Endpoints | 2008 | Gateway Endpoints Only |
AWS VPC Endpoints | 2012 | Interface Endpoints (Did not test all Interface Endpoints) |
AWS Lambda | 2012 | Console |
AWS SES | 2012 | Console |
AWS Glue | Empty | Console |
AWS EFS | Empty | Console |
AWS KMS | 2012 | Console |
AWS Secrets Manager | 2012 | Console |
AWS ECR (Repository) | 2012 | Console |
AWS CloudWatch Logs | 2012 | API/CLI Only |
AWS S3 | 2012 | Console |
AWS IAM | 2012 | Console |
AWS Private CA | Unknown | API/CLI Only |
AWS API Gateway | 2012 | Console |
AWS Cloud9 | NA | Does not support full IAM Policy Language |
AWS SAM | NA | Does not support full IAM Policy Language |
AWS Backup | 2012 | Console |
AWS S3 Glacier | Empty | Console |
AWS S3 Outposts | Unknown | Did Not Test |
AWS CodeArtifact | 2012 | Console |
AWS Lex v2 | Empty | Console |
AWS OpenSearch | 2012 | Console |
AWS EventBridge Schemas | 2012 | Console |
AWS EventBridge Event Buses | 2012 | Console |
AWS Elemental MediaStore | 2012 | Console |
AWS CloudTrail | 2012 | Console |
Finding Resource-Based Policies with CloudQuery #
We will use CloudQuery to check for resource-based policies with
2008-10-17
explicitly set as the version or for resource-based policies without an explicit version set. The following queries will be used to check for SQS queue policies, SNS topic policies, and VPC Endpoint policies. Additional queries can be written for other AWS resource-based policies.Finding SQS Queues and Their Resource-Based Policies
SELECT * FROM
(
SELECT policy ->> 'Version' as version, *
FROM aws_sqs_queues
) as sqs_queues
WHERE version = '2008-10-17'
OR version is NULL;
Finding SNS Topics and Their Resource-Based Policies
SELECT * FROM
(
SELECT policy ->> 'Version' as version, *
FROM aws_sns_topics
) as sns_topics
WHERE version = '2008-10-17'
OR version is NULL;
Finding VPC Endpoints and Their Resource-Based Policies
SELECT * FROM
(
SELECT policy_document ->> 'Version' as version, *
FROM aws_vpc_endpoints
) as vpc_endpoints
WHERE version = '2008-10-17'
OR version is NULL;
Conclusion #
The legacy policy version
2008-10-17
can be problematic for developers and application teams given the difference in interpretation by AWS.We would like to see the following from AWS:
- Example and default policies should have default policy versions set to
2012-10-17
. - Not specifying a policy version should also default to
2012-10-17
once enough warning has been given to AWS customers. - In the interim, more controls similar to the IAM Managed Policy creation experience that block creation of new policies without
2012-10-17
specified.
In the interim, we have the following recommendations for AWS end users:
- Scan AWS environments for any legacy usage of the
2008-10-17
policy language version. - If possible, update legacy policies to use the
2012-10-17
policy language version. - Ensure all new policies leverage the newer
2012-10-17
policy language version.
Stay tuned for more use cases we can build with CloudQuery on top of the infrastructure data we loaded from AWS!
Summary #
Ready to get started with CloudQuery? You can try out CloudQuery locally with our quick start guide or explore the CloudQuery Platform (currently in beta) for a more scalable solution.
Want help getting started? Join the CloudQuery community to connect with other users and experts, or message our team directly here if you have any questions.
References and Useful Links #
Written by Jason Kao
Jason worked as Head of Security Research and Solutions at CloudQuery and was a Senior Data Engineer prior to taking on that role. He focused on multi-cloud environments and has particular expertise on AWS.