AWS SCP Policy Rule Sets for Popular AWS Services

Practical Service Control Policy guardrails for AWS Regions, S3, EC2, IAM, KMS, CloudTrail, GuardDuty, AWS Config, RDS, Lambda, VPC, DynamoDB, and EKS.

AWS Service Control Policies (SCPs) establish the maximum permissions available to accounts in an AWS Organization. They do not grant permissions; IAM policies and resource policies must still allow an operation.

Before deployment: Replace placeholder Regions, account IDs, role names, resources, and other organization-specific values. Test every policy in a sandbox organizational unit (OU).

1. Restrict operations to approved AWS Regions

This organization-wide guardrail denies most activity outside approved Regions while exempting selected global services.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyUnapprovedRegions",
    "Effect": "Deny",
    "NotAction": [
      "account:*", "aws-portal:*", "billing:*", "budgets:*",
      "cloudfront:*", "iam:*", "organizations:*", "route53:*",
      "route53domains:*", "support:*", "waf:*"
    ],
    "Resource": "*",
    "Condition": {
      "StringNotEquals": {
        "aws:RequestedRegion": ["us-east-1", "us-west-2"]
      }
    }
  }]
}

Use case: Data residency, cost control, and attack-surface reduction.

2. Amazon S3 guardrails

Prevent public-access protection from being disabled

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyDisablingAccountPublicAccessBlock",
      "Effect": "Deny",
      "Action": "s3:PutAccountPublicAccessBlock",
      "Resource": "*"
    },
    {
      "Sid": "DenyChangingBucketPublicAccessBlock",
      "Effect": "Deny",
      "Action": ["s3:DeleteBucketPublicAccessBlock", "s3:PutBucketPublicAccessBlock"],
      "Resource": "*"
    }
  ]
}

The second statement is deliberately restrictive. A practical deployment can exempt a centrally controlled security role:

"Condition": {
  "ArnNotLike": {
    "aws:PrincipalArn": "arn:aws:iam::*:role/SecurityAdministrationRole"
  }
}

Require encrypted object uploads

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnencryptedS3Uploads",
      "Effect": "Deny",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::*/*",
      "Condition": {"Null": {"s3:x-amz-server-side-encryption": "true"}}
    },
    {
      "Sid": "DenyUnsupportedS3Encryption",
      "Effect": "Deny",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::*/*",
      "Condition": {
        "StringNotEquals": {
          "s3:x-amz-server-side-encryption": ["AES256", "aws:kms"]
        }
      }
    }
  ]
}

Caution: Some AWS services write to S3 through service-specific mechanisms and may require carefully scoped exemptions.

3. Amazon EC2 guardrails

Permit only approved instance types

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyUnapprovedEC2InstanceTypes",
    "Effect": "Deny",
    "Action": "ec2:RunInstances",
    "Resource": "arn:aws:ec2:*:*:instance/*",
    "Condition": {
      "StringNotEquals": {
        "ec2:InstanceType": ["t3.micro", "t3.small", "t3.medium", "m6i.large"]
      }
    }
  }]
}

Use case: Prevent expensive GPU or high-capacity instances from being launched.

Prevent disabling EBS encryption by default

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyDisablingDefaultEBSEncryption",
    "Effect": "Deny",
    "Action": "ec2:DisableEbsEncryptionByDefault",
    "Resource": "*"
  }]
}

Prevent creation of unencrypted EBS volumes

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyUnencryptedEBSVolumes",
    "Effect": "Deny",
    "Action": "ec2:CreateVolume",
    "Resource": "*",
    "Condition": {"Bool": {"ec2:Encrypted": "false"}}
  }]
}

4. IAM guardrails

Prevent member accounts from creating IAM users

This encourages workforce access through IAM Identity Center and temporary roles.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyIAMUserManagement",
    "Effect": "Deny",
    "Action": ["iam:CreateUser", "iam:CreateAccessKey", "iam:CreateLoginProfile"],
    "Resource": "*"
  }]
}

Protect designated administrative and security roles

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "ProtectSecurityRoles",
    "Effect": "Deny",
    "Action": [
      "iam:DeleteRole", "iam:DeleteRolePolicy", "iam:DetachRolePolicy",
      "iam:PutRolePolicy", "iam:UpdateAssumeRolePolicy"
    ],
    "Resource": [
      "arn:aws:iam::*:role/SecurityAdministrationRole",
      "arn:aws:iam::*:role/IncidentResponseRole",
      "arn:aws:iam::*:role/OrganizationAccountAccessRole"
    ],
    "Condition": {
      "ArnNotLike": {
        "aws:PrincipalArn": "arn:aws:iam::*:role/SecurityAdministrationRole"
      }
    }
  }]
}

Restrict role passing

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyPassingPrivilegedRoles",
    "Effect": "Deny",
    "Action": "iam:PassRole",
    "Resource": [
      "arn:aws:iam::*:role/SecurityAdministrationRole",
      "arn:aws:iam::*:role/OrganizationAccountAccessRole"
    ]
  }]
}

This prevents users from indirectly gaining privilege by attaching a powerful role to Lambda, EC2, Glue, or another AWS service.

5. AWS KMS guardrails

Prevent deletion of KMS keys

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyKMSKeyDeletion",
    "Effect": "Deny",
    "Action": ["kms:ScheduleKeyDeletion", "kms:DeleteImportedKeyMaterial"],
    "Resource": "*",
    "Condition": {
      "ArnNotLike": {"aws:PrincipalArn": "arn:aws:iam::*:role/KMSAdministrationRole"}
    }
  }]
}

Prevent key rotation from being disabled

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyDisablingKMSKeyRotation",
    "Effect": "Deny",
    "Action": "kms:DisableKeyRotation",
    "Resource": "*"
  }]
}

6. AWS CloudTrail guardrails

Prevent users in member accounts from disabling or deleting audit trails.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "ProtectCloudTrail",
    "Effect": "Deny",
    "Action": [
      "cloudtrail:DeleteTrail", "cloudtrail:StopLogging", "cloudtrail:UpdateTrail",
      "cloudtrail:PutEventSelectors", "cloudtrail:PutInsightSelectors"
    ],
    "Resource": "*",
    "Condition": {
      "ArnNotLike": {"aws:PrincipalArn": "arn:aws:iam::*:role/SecurityAdministrationRole"}
    }
  }]
}

7. Amazon GuardDuty guardrails

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "ProtectGuardDuty",
    "Effect": "Deny",
    "Action": [
      "guardduty:DeleteDetector", "guardduty:DisassociateFromAdministratorAccount",
      "guardduty:DisassociateMembers", "guardduty:StopMonitoringMembers",
      "guardduty:UpdateDetector"
    ],
    "Resource": "*",
    "Condition": {
      "ArnNotLike": {"aws:PrincipalArn": "arn:aws:iam::*:role/SecurityAdministrationRole"}
    }
  }]
}

8. AWS Config guardrails

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "ProtectAWSConfig",
    "Effect": "Deny",
    "Action": [
      "config:DeleteConfigurationRecorder", "config:DeleteDeliveryChannel",
      "config:StopConfigurationRecorder"
    ],
    "Resource": "*",
    "Condition": {
      "ArnNotLike": {"aws:PrincipalArn": "arn:aws:iam::*:role/SecurityAdministrationRole"}
    }
  }]
}

9. Amazon RDS guardrails

Require storage encryption

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnencryptedRDSInstances",
      "Effect": "Deny",
      "Action": "rds:CreateDBInstance",
      "Resource": "*",
      "Condition": {"Bool": {"rds:StorageEncrypted": "false"}}
    },
    {
      "Sid": "DenyUnencryptedRDSClusters",
      "Effect": "Deny",
      "Action": "rds:CreateDBCluster",
      "Resource": "*",
      "Condition": {"Bool": {"rds:StorageEncrypted": "false"}}
    }
  ]
}

Prevent public RDS databases

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyPublicRDSInstances",
    "Effect": "Deny",
    "Action": ["rds:CreateDBInstance", "rds:ModifyDBInstance"],
    "Resource": "*",
    "Condition": {"Bool": {"rds:PubliclyAccessible": "true"}}
  }]
}

10. AWS Lambda guardrails

Restrict approved Lambda runtimes

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyUnapprovedLambdaRuntimes",
    "Effect": "Deny",
    "Action": ["lambda:CreateFunction", "lambda:UpdateFunctionConfiguration"],
    "Resource": "*",
    "Condition": {
      "StringNotEqualsIfExists": {
        "lambda:Runtime": ["python3.13", "nodejs22.x", "java21"]
      }
    }
  }]
}

Container-image Lambda functions do not use the standard runtime parameter, so this policy requires careful testing.

Prevent public Lambda function URLs

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyPublicLambdaURLs",
    "Effect": "Deny",
    "Action": ["lambda:CreateFunctionUrlConfig", "lambda:UpdateFunctionUrlConfig"],
    "Resource": "*",
    "Condition": {"StringEquals": {"lambda:FunctionUrlAuthType": "NONE"}}
  }]
}

11. Amazon VPC guardrails

Prevent unmanaged internet gateways

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyInternetGatewayChanges",
    "Effect": "Deny",
    "Action": [
      "ec2:CreateInternetGateway", "ec2:AttachInternetGateway",
      "ec2:DetachInternetGateway", "ec2:DeleteInternetGateway"
    ],
    "Resource": "*",
    "Condition": {
      "ArnNotLike": {"aws:PrincipalArn": "arn:aws:iam::*:role/NetworkAdministrationRole"}
    }
  }]
}

Prevent VPC Flow Logs from being deleted

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "ProtectVPCFlowLogs",
    "Effect": "Deny",
    "Action": "ec2:DeleteFlowLogs",
    "Resource": "*",
    "Condition": {
      "ArnNotLike": {"aws:PrincipalArn": "arn:aws:iam::*:role/NetworkAdministrationRole"}
    }
  }]
}

12. Amazon DynamoDB guardrails

Prevent point-in-time recovery from being disabled

An SCP cannot force every new table to have point-in-time recovery enabled as part of a single table-creation operation because recovery is normally enabled through a separate API call. It can, however, prevent recovery from being disabled.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyDisablingDynamoDBRecovery",
    "Effect": "Deny",
    "Action": "dynamodb:UpdateContinuousBackups",
    "Resource": "*",
    "Condition": {"Bool": {"dynamodb:PointInTimeRecoveryEnabled": "false"}}
  }]
}

Use AWS Config or CloudFormation hooks to identify or prevent tables that never enable recovery.

13. Amazon EKS guardrails

Prevent public Kubernetes API endpoints

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyPublicEKSEndpoint",
    "Effect": "Deny",
    "Action": ["eks:CreateCluster", "eks:UpdateClusterConfig"],
    "Resource": "*",
    "Condition": {"Bool": {"eks:EndpointPublicAccess": "true"}}
  }]
}

This is appropriate where administrative access is available through private connectivity. Confirm relevant condition-key support before production deployment.

14. Consolidated security-service protection

This example protects CloudTrail, AWS Config, GuardDuty, Security Hub, and IAM Access Analyzer against tampering.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenySecurityServiceTampering",
    "Effect": "Deny",
    "Action": [
      "access-analyzer:DeleteAnalyzer", "cloudtrail:DeleteTrail",
      "cloudtrail:StopLogging", "config:DeleteConfigurationRecorder",
      "config:DeleteDeliveryChannel", "config:StopConfigurationRecorder",
      "guardduty:DeleteDetector", "securityhub:DisableSecurityHub"
    ],
    "Resource": "*",
    "Condition": {
      "ArnNotLike": {
        "aws:PrincipalArn": [
          "arn:aws:iam::*:role/SecurityAdministrationRole",
          "arn:aws:iam::*:role/AWSControlTowerExecution"
        ]
      }
    }
  }]
}

Recommended SCP rule-set structure

Rule set Typical controls
Organization baseline Approved Regions, prohibited services, and root-user restrictions
Security protection Protect CloudTrail, AWS Config, GuardDuty, and Security Hub
Identity protection Protect security roles; restrict IAM users and role passing
Data protection Require encryption for S3, EBS, and RDS
Network protection Restrict internet gateways, public endpoints, and VPC changes
Cost protection Approved EC2 instance types, GPU restrictions, and expensive Regions
Workload-specific Separate controls for production, development, and sandbox OUs

Implementation cautions

  • Test each SCP against a sandbox OU before attaching it to production.
  • An explicit SCP denial overrides IAM permissions, including administrator permissions.
  • SCPs restrict the permissions available to principals; they do not grant permissions.
  • Service-linked roles have special behavior and may not be restricted by SCPs in the same way as ordinary IAM principals.
  • Use ArnNotLike with aws:PrincipalArn for carefully controlled break-glass exemptions.
  • Avoid one enormous policy. Smaller policies are easier to test, version, and attach by OU.
  • Combine SCPs with AWS Config, AWS Control Tower controls, CloudFormation hooks, and detective controls. Not every configuration requirement can be enforced reliably through an SCP alone.

These examples are starting points, not drop-in production policies. Validate action names, condition-key support, service dependencies, and exemption paths against your organization’s current AWS architecture.