← SCP Explorer

Tag enforcement

Requires specific tags on all EC2 instances and RDS databases, ensuring proper resource categorization and cost allocation.

Policy description

What this SCP does

This Service Control Policy (SCP) requires specific tags on all EC2 instances and RDS databases, ensuring proper resource categorization and cost allocation. For EC2 instances, it enforces the presence of the 'Environment' tag on the resource itself using resource-level tag conditions. For RDS databases, it enforces tagging at creation time using request-level tag conditions. This dual approach ensures effective tag enforcement while accommodating the different tagging capabilities of each service.

When users try to create EC2 instances without specifying the required 'Environment' tag in the resource tags, or RDS instances without the tag in the request, the operation will be denied. This enforces tagging discipline across all accounts in the organization while respecting service-specific tagging mechanisms.

Validation strategy

How to test this SCP works

To validate this SCP, try to create instances with and without the required 'Environment' tag. Note that EC2 and RDS use different tagging mechanisms in the API calls.

  • Invalid test: Launch an EC2 instance without specifying the 'Environment' tag in the resource tags (should be denied)
  • Valid test: Launch an EC2 instance with the 'Environment' tag specified in the resource tags via tag-specifications (should succeed)
  • Invalid test: Create an RDS instance without the 'Environment' tag in the request (should be denied)
  • Valid test: Create an RDS instance with the 'Environment' tag in the request tags (should succeed)

We expect resource creation without the required tag to be denied with an AccessDenied error, while creation with the proper tag should succeed. For EC2, tags must be specified using the tag-specifications parameter, while for RDS they are specified directly in the request tags.

SCP policy & validation scenarios

{ "Version": "2012-10-17", "Statement": [ { "Sid": "DenyEC2WithoutTags", "Effect": "Deny", "Action": "ec2:RunInstances", "Resource": "arn:aws:ec2:*:*:instance/*", "Condition": { "Null": { "ec2:ResourceTag/Environment": "true" } } }, { "Sid": "DenyRDSWithoutTags", "Effect": "Deny", "Action": "rds:CreateDBInstance", "Resource": "*", "Condition": { "Null": { "aws:RequestTag/Environment": "true" } } } ] }
#Users may need to create a VPC if they do not already have one aws ec2 create-default-vpc # Try to launch an EC2 instance without the required tag (this should be denied) aws ec2 run-instances \ --image-id ami-0e449927258d45bc4 \ --instance-type t2.micro \ --count 1 # Try to launch an EC2 instance with the required tag (this should be allowed) aws ec2 run-instances \ --image-id ami-0e449927258d45bc4 \ --instance-type t2.micro \ --count 1 \ --tag-specifications 'ResourceType=instance,Tags=[{Key=Environment,Value=dev}]' # Try to create an RDS instance without the required tag (this should be denied) aws rds create-db-instance \ --db-instance-identifier test-db \ --db-instance-class db.t3.micro \ --engine mysql \ --master-username admin \ --master-user-password Password123! \ --allocated-storage 20 # Try to create an RDS instance with the required tag (this should be allowed) aws rds create-db-instance \ --db-instance-identifier test-db \ --db-instance-class db.t3.micro \ --engine mysql \ --master-username admin \ --master-user-password Password123! \ --allocated-storage 20 \ --tags Key=Environment,Value=dev
import boto3 import time # Initialize clients ec2_client = boto3.client('ec2') rds_client = boto3.client('rds') # Test EC2 instance creation without required tag try: ec2_client.run_instances( ImageId='ami-0e449927258d45bc4', # Amazon Linux 2 AMI InstanceType='t2.micro', MinCount=1, MaxCount=1 ) print("WARNING: Successfully launched EC2 instance without required tag") print("This means the SCP is NOT restricting as expected") except Exception as e: print(f"Expected error for EC2 without tag if SCP is working: {e}") # Test EC2 instance creation with required tag try: response = ec2_client.run_instances( ImageId='ami-0e449927258d45bc4', # Amazon Linux 2 AMI InstanceType='t2.micro', MinCount=1, MaxCount=1, TagSpecifications=[ { 'ResourceType': 'instance', 'Tags': [ { 'Key': 'Environment', 'Value': 'dev' } ] } ] ) instance_id = response['Instances'][0]['InstanceId'] print(f"Successfully launched EC2 instance with required tag: {instance_id}") # Clean up ec2_client.terminate_instances(InstanceIds=[instance_id]) print(f"Cleaned up test instance: {instance_id}") except Exception as e: print(f"Error launching EC2 with required tag: {e}") # Test RDS instance creation without required tag try: rds_client.create_db_instance( DBInstanceIdentifier='test-db-' + str(int(time.time())), AllocatedStorage=20, DBInstanceClass='db.t3.micro', Engine='mysql', MasterUsername='admin', MasterUserPassword='Password123!' ) print("WARNING: Successfully created RDS instance without required tag") print("This means the SCP is NOT restricting as expected") except Exception as e: print(f"Expected error for RDS without tag if SCP is working: {e}") # Test RDS instance creation with required tag try: db_identifier = 'test-db-' + str(int(time.time())) rds_client.create_db_instance( DBInstanceIdentifier=db_identifier, AllocatedStorage=20, DBInstanceClass='db.t3.micro', Engine='mysql', MasterUsername='admin', MasterUserPassword='Password123!', Tags=[ { 'Key': 'Environment', 'Value': 'dev' } ] ) print(f"Successfully created RDS instance with required tag: {db_identifier}") print("Note: Created RDS instance will take time to be available and delete") except Exception as e: print(f"Error creating RDS with required tag: {e}")