Use the Conformity Knowledge Base AI to help improve your Cloud Posture

Amazon EC2 Purchase Restriction

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: High (not acceptable risk)

Ensure that only dedicated IAM users have the capability to purchase Amazon EC2 Reserved Instances and/or Savings Plans within your AWS cloud account in order to address internal compliance requirements and prevent unexpected charges on your AWS bill. Prior to running this conformity rule, the name(s) of the IAM user(s) allowed to purchase EC2 Reserved Instances and/or Savings Plans, must be configured in the conformity rule settings, on the Trend Cloud One™ – Conformity console.

This rule can help you work with the AWS Well-Architected Framework.

Cost
optimisation

Purchasing Amazon EC2 Reserved Instances (RIs) and Savings Plans result in bigger financial commitments. Therefore, to keep compute costs under control, you might want to control who can make such purchases within your AWS cloud account.


Audit

To check for unintended IAM users that have permissions to purchase Amazon EC2 Reserved Instances and/or Savings Plans, perform the following operations:

Using AWS Console

01 Sign in to your Trend Cloud One™ – Conformity account, access Amazon EC2 Purchase Restriction conformity rule settings and identify the name(s) of the IAM user(s) allowed to purchase Amazon EC2 Reserved Instances and/or Savings Plans in your AWS account.

02 Sign in to the AWS Management Console.

03 Navigate to Amazon IAM console at https://console.aws.amazon.com/iam/.

04 In the navigation panel, under Access management, choose Users.

05 Click on the name of the IAM user that you want to examine.

06 Select the Permissions tab and click on the Expand button (right arrow icon) available next to each IAM policy attached, to show the IAM policy document in JSON format.

07 Inside the policy document box, search for the "Action" policy element that contains "ec2:PurchaseReservedInstancesOffering" or "savingsplans:CreateSavingsPlan" or both, in combination with "Effect" set to "Allow", as shown in the example below:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"ec2:PurchaseReservedInstancesOffering",
				"savingsplans:CreateSavingsPlan"
			],
			"Resource": "*"
		}
	]
}

If the verified IAM user has permissions to purchase Amazon EC2 Reserved Instances and/or Savings Plans, and the user name is not listed in the conformity rule settings identified at step no. 1, the selected AWS IAM user should not be able to make purchases, therefore the associated identity-based policies are not compliant.

08 Repeat steps no. 5 – 7 for each Amazon IAM user created within your AWS cloud account.

Using AWS CLI

01 Sign in to your Trend Cloud One™ – Conformity account, access Amazon EC2 Purchase Restriction conformity rule settings and identify the name(s) of the IAM user(s) allowed to purchase Amazon EC2 Reserved Instances and/or Savings Plans in your AWS account.

02 Run list-users command (OSX/Linux/UNIX) using custom query filters to list the names of all IAM users available within your AWS account:

aws iam list-users
  --output table
  --query 'Users[*].UserName'

03 The command output should return a table with the requested IAM user identifiers:

-----------------------
|     ListUsers       |
+---------------------+
|  cc-project5-admin  |
|  cc-rds-db-manager  |
+---------------------+ 

04 Run list-attached-user-policies command (OSX/Linux/UNIX) using the name of the Amazon IAM user that you want to examine as identifier parameter and custom filtering to list the Amazon Resource Names (ARNs) of the IAM managed policies currently attached to the selected user:

aws iam list-attached-user-policies
  --user-name cc-project5-admin
  --query 'AttachedPolicies[*].PolicyArn'

05 The command output should return the ARNs of the managed policies attached to the specified IAM user:

[
	"arn:aws:iam::123456789012:policy/cc-ec2-compute-access",
	"arn:aws:iam::123456789012:policy/cc-rds-service-access"
]

06 Run get-policy-version command (OSX/Linux/UNIX) using the ARN of the IAM policy that you want to examine as identifier parameter and custom query filters to describe the policy document in JSON format. Repeat this step for each managed policy attached to the specified IAM user:

aws iam get-policy-version
  --policy-arn arn:aws:iam::123456789012:policy/cc-ec2-compute-access
  --version-id v1
  --query 'PolicyVersion.Document'

07 The command output should return the requested IAM policy document:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"ec2:Describe*",
				"elasticloadbalancing:Describe*",
				"autoscaling:Describe*",
				"cloudwatch:Describe*",
				"cloudwatch:ListMetrics",
				"cloudwatch:GetMetricStatistics",
				"ec2:PurchaseReservedInstancesOffering",
				"savingsplans:CreateSavingsPlan"
			],
			"Resource": "*"
		}
	]
}

08 Run list-user-policies command (OSX/Linux/UNIX) using the name of the Amazon IAM user that you want to examine as identifier parameter and custom filtering to list the names of the inline policies embedded within the selected IAM user:

aws iam list-user-policies
  --user-name cc-project5-admin
  --query 'PolicyNames'

09 The command output should return the names of the inline policies embedded in the specified IAM user:

[
	"cc-inline-ec2-policy",
	"cc-custom-api-access"
]

10 Run get-user-policy command (OSX/Linux/UNIX) using the name of the inline policy that you want to examine as identifier parameter, returned at the previous step, to describe the IAM policy document in JSON format. Repeat this step for each inline policy attached to the specified IAM user:

aws iam get-user-policy
  --user-name cc-project5-admin
  --policy-name cc-inline-ec2-policy
  --query 'PolicyDocument'

11 The command output should return the requested AWS IAM policy document:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"ec2:PurchaseReservedInstancesOffering",
				"savingsplans:CreateSavingsPlan"
			],
			"Resource": "*"
		}
	]
}

Search the policy documents returned by the get-policy-version command output at step no. 6 and the get-user-policy command output at step no. 10 for the "Action" policy element that contains "ec2:PurchaseReservedInstancesOffering" or "savingsplans:CreateSavingsPlan" or both, in combination with "Effect": "Allow". If the verified IAM user has permissions to purchase Amazon EC2 Reserved Instances and/or Savings Plans, and the user name is not listed in the conformity rule settings identified at step no. 1, the selected AWS IAM user should not be able to make purchases, therefore the associated identity-based policies are not compliant.

12 Repeat steps no. 3 – 10 for each unintended AWS IAM user available within your AWS cloud account.

Remediation / Resolution

To prevent unintended AWS IAM users from purchasing Amazon EC2 Reserved Instances and/or Savings Plans within your AWS cloud account, perform the following operations:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Resources": {
		"IAMUser": {
			"Type": "AWS::IAM::User",
			"Properties": {
				"UserName": "cc-ec2-instance-developer"
			}
		},
		"IAMUserPolicy": {
			"Type": "AWS::IAM::Policy",
			"Properties": {
				"PolicyName": "full-access-policy",
				"PolicyDocument": {
					"Version": "2012-10-17",
					"Statement": [
						{
							"Effect": "Allow",
							"Action": [
								"ec2:Describe*",
								"elasticloadbalancing:Describe*",
								"autoscaling:Describe*",
								"cloudwatch:Describe*",
								"cloudwatch:ListMetrics",
								"cloudwatch:GetMetricStatistics",
								"ec2:PurchaseReservedInstancesOffering",
								"savingsplans:CreateSavingsPlan"
							],
							"Resource": "*"
						}
					]
				},
				"Users": [
					{
						"Ref": "IAMUser"
					}
				]
			}
		}
	}
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
	Resources:
	IAMUser:
		Type: AWS::IAM::User
		Properties:
		UserName: cc-ec2-instance-developer
	IAMUserPolicy:
		Type: AWS::IAM::Policy
		Properties:
		PolicyName: full-access-policy
		PolicyDocument:
			Version: '2012-10-17'
			Statement:
			- Effect: Allow
				Action:
				- ec2:Describe*
				- elasticloadbalancing:Describe*
				- autoscaling:Describe*
				- cloudwatch:Describe*
				- cloudwatch:ListMetrics
				- cloudwatch:GetMetricStatistics
					- ec2:PurchaseReservedInstancesOffering
					- savingsplans:CreateSavingsPlan
				Resource: '*'
		Users:
			- !Ref 'IAMUser'

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf):

terraform {
	required_providers {
		aws = {
			source  = "hashicorp/aws"
			version = "~> 4.0"
		}
	}
	required_version = ">= 0.14.9"
}

provider "aws" {
	profile = "default"
	region  = "us-east-1"
}

resource "aws_iam_user" "iam-user" {
	name = "cc-ec2-instance-developer"
}

resource "aws_iam_policy" "iam-policy" {
	name   = "ec2-access-policy"
	policy = <<EOF
	{
		"Version": "2012-10-17",
		"Statement": [
			{
				"Effect": "Allow",
				"Action": [
					"ec2:Describe*",
					"elasticloadbalancing:Describe*",
					"autoscaling:Describe*",
					"cloudwatch:Describe*",
					"cloudwatch:ListMetrics",
					"cloudwatch:GetMetricStatistics",
					"ec2:PurchaseReservedInstancesOffering",
					"savingsplans:CreateSavingsPlan"
				],
				"Resource": "*"
			}
		]
	}
	EOF
}

resource "aws_iam_policy_attachment" "iam-user-attachment" {
	name       = "iam-user-attachment"
	users      = [aws_iam_user.iam-user.name]
	policy_arn = aws_iam_policy.iam-policy.arn
}

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon IAM console at https://console.aws.amazon.com/iam/.

03 In the navigation panel, under Access management, choose Users.

04 Click on the name of the unintended IAM user that you want to reconfigure (see Audit section part I to identify the non-compliant user).

05 Select the Permissions tab, expand the panel with the policy that you want to update, then choose Edit policy.

06 On the Edit <policy-name> configuration page, perform the following actions:

  1. Select the JSON tab and remove the following lines: "ec2:PurchaseReservedInstancesOffering" and "savingsplans:CreateSavingsPlan" from the "Action" element value. This will remove the user capability to purchase Amazon EC2 Reserved Instances and Savings Plans.
  2. Choose Review policy to review the modified policy.
  3. Choose Save changes to apply the permission changes.

07 Repeat steps no. 5 and 6 for each non-compliant identity-based policy attached to the selected IAM user.

08 Repeat steps no. 4 – 7 for each unintended AWS IAM user available within your AWS cloud account.

Using AWS CLI

01 Modify the non-compliant identity-based policy (see Audit section part II to identify the right policy) and remove the following lines: "ec2:PurchaseReservedInstancesOffering" and "savingsplans:CreateSavingsPlan" from the "Action" element value (highlighted). This will remove the user capability to purchase Amazon EC2 Reserved Instances and Savings Plans. Save the modified IAM policy document to a JSON file named compliant-user-policy.json:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"ec2:Describe*",
				"elasticloadbalancing:Describe*",
				"autoscaling:Describe*",
				"cloudwatch:Describe*",
				"cloudwatch:ListMetrics",
				"cloudwatch:GetMetricStatistics",
				"ec2:PurchaseReservedInstancesOffering",
				"savingsplans:CreateSavingsPlan"
			],
			"Resource": "*"
		}
	]
}

02 Run create-policy-version command (OSX/Linux/UNIX) to update the non-compliant customer-managed policy attached to the specified AWS IAM user using the policy document modified at the previous step:

aws iam create-policy-version
  --policy-arn arn:aws:iam::123456789012:policy/cc-ec2-compute-access
  --set-as-default
  --policy-document file://compliant-user-policy.json

03 The command output should return the metadata for the new policy version:

{
	"PolicyVersion": {
		"VersionId": "v2",
		"IsDefaultVersion": true,
		"CreateDate": "2021-02-04T16:00:00+00:00"
	}
}

04 Run put-user-policy command (OSX/Linux/UNIX) to update the non-compliant inline policy embedded in the specified AWS IAM user using the policy document modified at step no. 1 (the command does not produce an output):

aws iam put-user-policy
  --user-name cc-project5-admin
  --policy-name cc-inline-ec2-policy
  --policy-document file://compliant-user-policy.json

05 Repeat steps no. 1 – 4 for each unintended AWS IAM user available in your AWS cloud account.

References

Publication date Sep 7, 2023