AWS Resource Control Policies: Practical RCP Rule Sets for 11 AWS Services

AWS Resource Control Policies provide a centrally managed resource-side security boundary. This guide presents practical RCP rule sets for eleven widely used AWS services and explains where RCPs complement—rather than replace—SCPs, IAM policies, key policies, and resource policies.

What is an AWS Resource Control Policy?

A Resource Control Policy, or RCP, is an AWS Organizations policy that defines the maximum permissions available on resources in member accounts. An RCP can prevent an external or unintended principal from accessing an organizational resource even when a resource policy mistakenly permits that access.

RCPs do not grant permissions. Actual access must still be granted through an identity-based or resource-based policy. Effective access is the intersection of the applicable RCPs, SCPs, IAM policies, and resource policies.

SCP versus RCP: an SCP limits what identities in member accounts can do. An RCP limits what principals—inside or outside the organization—can do to resources in member accounts.

Recommended controls by service

Service RCP prefix Recommended guardrails
Amazon S3 s3 Block external principals; require TLS; require SSE-KMS; control service-originated access.
AWS KMS kms Block external principals from customer-managed keys; protect against confused-deputy access.
CloudWatch Logs logs Protect log groups, destinations, and service-delivery paths.
DynamoDB dynamodb Prevent unintended cross-organization table access.
EC2 Auto Scaling autoscaling Prevent external access to supported Auto Scaling resources.
Amazon Inspector Scan inspector2 Prevent external access to supported Inspector Scan resources.
Kinesis Video Streams kinesisvideo Protect video streams from external access.
Amazon SQS sqs Protect queues and restrict service-originated message delivery.
AWS CodeBuild codebuild Prevent external access to supported build resources.
AWS CodePipeline codepipeline Prevent external access to supported pipeline resources.
AWS Secrets Manager secretsmanager Prevent external secret access and unintended resource-policy sharing.
Important Kinesis limitation: AWS currently lists Kinesis Video Streams—not standard Kinesis Data Streams—as supporting RCPs. Use SCPs, IAM policies, and stream resource policies for Kinesis Data Streams. Amazon Data Firehose has separate RCP support under firehose.

Rule set 1: Establish an organizational resource perimeter

This consolidated policy denies access from IAM principals outside the organization while allowing AWS service principals. Replace o-xxxxxxxxxx with the actual AWS Organization ID.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyExternalPrincipalAccessToProtectedResources",
      "Effect": "Deny",
      "Principal": "*",
      "Action": [
        "s3:*",
        "kms:*",
        "logs:*",
        "dynamodb:*",
        "autoscaling:*",
        "inspector2:*",
        "kinesisvideo:*",
        "sqs:*",
        "codebuild:*",
        "codepipeline:*",
        "secretsmanager:*"
      ],
      "Resource": "*",
      "Condition": {
        "BoolIfExists": {
          "aws:PrincipalIsAWSService": "false"
        },
        "StringNotEqualsIfExists": {
          "aws:PrincipalOrgID": "o-xxxxxxxxxx"
        }
      }
    }
  ]
}

Exempt approved external roles

If a partner or controlled break-glass role requires access, add a narrow ArnNotLike exception. Avoid broad account-wide exceptions.

"Condition": {
  "BoolIfExists": {
    "aws:PrincipalIsAWSService": "false"
  },
  "StringNotEqualsIfExists": {
    "aws:PrincipalOrgID": "o-xxxxxxxxxx"
  },
  "ArnNotLike": {
    "aws:PrincipalArn": [
      "arn:aws:iam::111122223333:role/ApprovedPartnerRole",
      "arn:aws:iam::*:role/OrganizationBreakGlassRole"
    ]
  }
}

Rule set 2: Reduce cross-service confused-deputy risk

AWS service principals frequently need legitimate resource access—for example, CloudTrail writing to S3 or EventBridge sending to SQS. Where the integration supplies the relevant source context, require the calling service to act for a resource associated with your organization.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyServiceAccessFromOutsideOrganization",
      "Effect": "Deny",
      "Principal": "*",
      "Action": [
        "s3:*", "kms:*", "logs:*", "dynamodb:*",
        "autoscaling:*", "inspector2:*", "kinesisvideo:*",
        "sqs:*", "codebuild:*", "codepipeline:*",
        "secretsmanager:*"
      ],
      "Resource": "*",
      "Condition": {
        "Bool": {
          "aws:PrincipalIsAWSService": "true"
        },
        "Null": {
          "aws:SourceAccount": "false"
        },
        "StringNotEqualsIfExists": {
          "aws:SourceOrgID": "o-xxxxxxxxxx"
        }
      }
    }
  ]
}

Test this rule carefully because AWS integrations do not all populate source context keys identically. Where appropriate, use aws:SourceAccountaws:SourceArnaws:SourceOrgID, or aws:SourceOrgPaths based on the integration.

Rule set 3: Enforce S3 transport security

Require HTTPS

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyUnencryptedS3Transport",
    "Effect": "Deny",
    "Principal": "*",
    "Action": "s3:*",
    "Resource": "*",
    "Condition": {
      "Bool": { "aws:SecureTransport": "false" }
    }
  }]
}

Require TLS 1.2 or later

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyS3RequestsBelowTLS12",
    "Effect": "Deny",
    "Principal": "*",
    "Action": "s3:*",
    "Resource": "*",
    "Condition": {
      "NumericLessThan": { "s3:TlsVersion": "1.2" }
    }
  }]
}

TLS 1.2 is a broadly compatible enterprise baseline. AWS Control Tower also provides a stricter preventive control that requires TLS 1.3.

Rule set 4: Require SSE-KMS for S3 object uploads

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyS3UploadsWithoutSSEKMSKey",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::*/*",
      "Condition": {
        "Null": {
          "s3:x-amz-server-side-encryption-aws-kms-key-id": "true"
        }
      }
    },
    {
      "Sid": "DenyIncorrectS3EncryptionAlgorithm",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::*/*",
      "Condition": {
        "StringNotEqualsIfExists": {
          "s3:x-amz-server-side-encryption": "aws:kms"
        }
      }
    }
  ]
}
Deployment consideration: the explicit key-header check may reject clients that depend only on bucket default encryption. Inventory those upload paths before enforcement.

Rule set 5: Protect customer-managed KMS keys

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyExternalAccessToCustomerManagedKeys",
    "Effect": "Deny",
    "Principal": "*",
    "Action": "kms:*",
    "Resource": "*",
    "Condition": {
      "BoolIfExists": {
        "aws:PrincipalIsAWSService": "false"
      },
      "StringNotEqualsIfExists": {
        "aws:PrincipalOrgID": "o-xxxxxxxxxx"
      },
      "ArnNotLike": {
        "aws:PrincipalArn": "arn:aws:iam::111122223333:role/ApprovedExternalKMSRole"
      }
    }
  }]
}

RCPs do not apply to AWS-managed KMS keys or to kms:RetireGrant. Key policies and IAM policies remain necessary to grant access.

Service-specific organizational perimeter policies

The same tested perimeter pattern can be applied separately when different OUs, exemptions, or rollout schedules are required. Change the Sid, action prefix, and—in the SQS example—the resource ARN as shown below.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyExternalAccessToSERVICE",
    "Effect": "Deny",
    "Principal": "*",
    "Action": "SERVICE_PREFIX:*",
    "Resource": "*",
    "Condition": {
      "BoolIfExists": {
        "aws:PrincipalIsAWSService": "false"
      },
      "StringNotEqualsIfExists": {
        "aws:PrincipalOrgID": "o-xxxxxxxxxx"
      }
    }
  }]
}
Service-specific policy Sid Action Resource
CloudWatch Logs DenyExternalAccessToCloudWatchLogs logs:* *
DynamoDB DenyExternalAccessToDynamoDB dynamodb:* *
EC2 Auto Scaling DenyExternalAccessToAutoScaling autoscaling:* *
Inspector Scan DenyExternalAccessToInspectorScan inspector2:* *
Kinesis Video Streams DenyExternalAccessToKinesisVideo kinesisvideo:* *
SQS DenyExternalAccessToSQSQueues sqs:* arn:aws:sqs:*:*:*
CodeBuild DenyExternalAccessToCodeBuild codebuild:* *
CodePipeline DenyExternalAccessToCodePipeline codepipeline:* *
Secrets Manager DenyExternalAccessToSecrets secretsmanager:* *

What these RCPs do not control

  • CodeBuild and CodePipeline execution roles: use IAM policies and SCPs to control what build and pipeline roles can access.
  • Kinesis Data Streams: use SCPs, IAM, and stream resource policies because the kinesis prefix is not currently listed for RCP support.
  • Management-account resources: RCPs apply to member-account resources, not resources in the AWS Organizations management account.
  • Service-linked roles: RCPs do not restrict calls made by service-linked roles.
  • Permission grants: an RCP establishes a ceiling; it never grants access by itself.

Safe deployment sequence

  1. Inventory existing public and cross-account access with IAM Access Analyzer.
  2. Identify partner roles and required AWS service integrations.
  3. Add narrow, documented exceptions.
  4. Attach the RCP to a dedicated test account.
  5. Review CloudTrail for unexpected AccessDenied events.
  6. Expand to a nonproduction OU.
  7. Progressively deploy to production OUs.
  8. Attach at the organization root only after broad validation.

RCP syntax reminders

  • Customer-created RCPs use explicit Deny statements.
  • The Principal in an RCP must be "*"; use conditions to distinguish principals.
  • A customer-managed RCP cannot use a bare "Action": "*"; specify one or more supported service prefixes.
  • The AWS-managed RCPFullAWSAccess policy remains attached automatically and does not grant permissions.
  • Narrow resources and exceptions where service authorization semantics allow it.

Conclusion

The strongest RCP design begins with a common organizational resource perimeter, adds confused-deputy protection for AWS service access, and then layers service-specific controls such as S3 transport encryption and SSE-KMS requirements. SCPs constrain identities; RCPs protect resources. Used together, they create a stronger preventive boundary for a multi-account AWS environment.

References

Disclaimer: These policies are reference patterns, not drop-in production controls. Validate supported actions, service integrations, resource ARNs, and exceptions in a test OU before enforcement.