What Are AWS Resource Control Policies (RCPs)? The Complete Guide Resource Control Policies (RCPs) are organization-wide guardrails designed to enforce security and governance across AWS resources.

Resource Control Policies (RCPs) are organization-wide guardrails designed to enforce security and governance across AWS resources. These deny-only policies establish permission boundaries for specific resource types within AWS organizations.
Amazon introduced RCPs and an added layer of security to better protect AWS resources, especially those that contain sensitive information.
Additionally, RCPs are the last to be evaluated, which means they have the final say about whether an action can proceed. If an RCP denies the action, the request is blocked, regardless of what the IAM or resource policies allow.
What exactly are RCPs, and how can you use them to bolster your own cloud security? Keep reading to learn more about this purpose-built security mechanism so you can better secure your AWS resources.
RCPs are policies that set permission boundaries for resources or resource types throughout your AWS organization’s OUs and accounts.
Ultimately, RCPS are “guardrails”, working to prevent access that otherwise might be allowed by the access policies of the individual resources and/or the individual principals that are requesting access to those resources.
RCPs are available today for the following services:
It’s important to underscore that RCPs work as enforcement and are later evaluated after IAM policies, other resource-based policies, and other service-specific controls. Cloud security still requires comprehensive IAM policies that work with RCPs.
One valuable use case of RCPs is secrets management. They can help enforce access policies for secrets and other sensitive data.
Administrators can use them to prevent access that does not comply with the organization’s overall policy, even if other policies may have allowed it.
What makes an RCP tick? At its heart, RCP is a JSON file that specifies the policies that affect specific resources. For example, here’s an example of a JSON config file restricting access to a specific AWS organization:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RestrictExternalAccess",
"Effect": "Deny",
"Principal": "*",
"Action": "*",
"Resource": "*",
"Condition": {
"StringNotEquals": { "aws:PrincipalOrgID": "o-abcdefghij" }
}
}
]
}
Let’s break down the above RCP example to better understand how it works under the hood.
| Element | Purpose | Example Snippet |
| Version | Specifies policy language version | "Version": "2012-10-17" |
| Statement | Defines policy rules | "Statement": {... } or "Statement": [ {... }, {... } ] |
| Sid | Optional statement identifier | "Sid": "RestrictExternalAccess" |
| Effect | Specifies action outcome (only “Deny” allowed) | "Effect": "Deny" |
| Principal | Always set to “*” (restrictions set via Condition) | "Principal": "*" |
| Action | Defines AWS actions being controlled | "Action": "*" |
| Resource / NotResource | Specifies targeted or exempted resources | "Resource": "*" |
| Condition | Applies additional constraints | "Condition": {
"StringNotEquals": { "aws:PrincipalOrgID": "o-abcdefghij" }
} |
The version field specifies the policy language version, which ensures compatibility with the AWS policy evaluation mechanism. The only valid value is “2012-10-17,” and this is a mandatory field.
Example:
"Version": "2012-10-17"
This parameter defines the core policy rules that dictate access control for AWS resources. A policy must contain at least one statement, but it can have multiple statements to enforce different restrictions.
Each statement consists of elements such as Effect, Action, Resource, and Condition.
Single statement: "Statement": {... }
Multiple statements: Statement": [ {... }, {... } ]
The Statement ID is an optional identifier that helps improve human readability to help with overall policy management. AWS does not enforce any specific behaviors based on Sid, but administrators can use it to track and reference individual policy statements for debugging and auditing.
Example:
"Sid": "RestrictExternalAccess"
The effect determines the enforcement outcome of the policy. RCPs only support “Deny,” which means they can only restrict access, never grant access. If a request meets the conditions defined in the policy, it will be explicitly denied, regardless of other permissions granted by IAM.
Example:
"Effect": "Deny",
The principal defines the entity to which the policy applies, such as role or user. However, for RCPs, this field must always be set to “*” as the actual restrictions are implemented through the Condition element.
Unlike resource-based policies, RCPs do not allow specifying individual AWS accounts or ARNs in this field.
Example:
"Principal": "*",
This field specifies which AWS service actions are affected by the policy. Actions are defined in a specific service:operation format, such as “s3:PutObject” to restrict object uploads to s3.
Wildcards can be used to cover multiple actions at once, but be careful not to apply overly broad restrictions.
Example:
"Action": "s3:PutObject",
The Resource or NotResource field specifies which actions are affected by or exempt from the policy. The following two options for this field are:
"arn:aws:s3:::prod-*" will restrict all S3 buckets with a prod- prefix."arn:aws:ec2:::instance/*" would apply to all EC2 instances in any region.“NotResource”: “arn:aws:s3:::public-bucket” would apply the policy to all resources except for the public-bucket."NotResource": "arn:aws:s3:::internal-" would exclude all buckets with the internal- prefix. Note that:
Example:
"Resource": "arn:aws:s3:::prod-*"
The Condition field contains AND-based logic gates to refine policy enforcement. Conditions operate using logical operators to provide granular control over access restrictions. Common operators include StringNotEquals and Bool.
By leveraging conditions, organizations can create flexible yet strict access control policies that enforce governance without any unnecessary disruptions.
Example:"Condition": {
"StringNotEquals": {"aws:PrincipalOrgID": "o-orgid"},
"Bool": {"aws:SecureTransport": "true"}
}
In general, the two types of policies that determine access are identity-based policies and resource-based policies.
AWS Resource Control Policies (RCPs) are the resource-policy counterpart to AWS Service Control Policies (SCPs). RCPs enable you to enforce organization-wide restrictions on who can access your AWS resources, and how, even for principals outside your AWS Organization.
If you’ve worked with SCPs, RCPs will feel and look familiar. Like SCPs, they:
Understanding these similarities and nuances will allow you to leverage RCPs alongside SCPs to enhance security and governance across your AWS environment.
With this in mind, RCPs are guardrails meant to override resource-based policies, while SCPs are guardrails meant to override identity-based policies.
| Feature | RCPs (Resource Context Policies) | SCPs (Service Control Policies) |
| Policy Target | Guardrail on the access policies that resources might have | Guardrails on the permissions users and roles might have |
| Inheritance | Organizational hierarchy | Organizational hierarchy |
| External Account Access | Applies to external users accessing org resources | Doesn’t affect external accounts accessing org resources |
| Policy Evaluation | Final gate before resource access | Filters available permissions before IAM policies apply |
RCPs are intended to replace your existing access controls but serve as an additional safeguard against unauthorized access of AWS resources. As a result, they have several constraints that must be understood before you start setting them up, let’s break them down.
Unlike other IAM policies that include “Allow” and “Deny” effects, RCPs are strictly limited to “Deny”. As such, they can only be used to explicitly block access to AWS resources but not grant or modify permissions.
This singular use further highlights the “safeguard” nature of RCPs, they’re not intended to replace more robust access control methods.
An RCP can contain up to five individual statements, each defining specific restrictions. This limit requires careful policy design to ensure that all necessary constraints are included without exceeding the maximum of five.
They can be spread across multiple RCPs but applied to the same resource if you need more.
The total size of an RCP cannot exceed 5,120 characters, including all JSON elements like Version, Statement, and Condition. This character limit means that policies must be written efficiently while avoiding unnecessary whitespace and complexities.
Administrators might need to optimize by using wildcards, consolidating their conditions, or restructuring statements if a policy approaches this limit.
Unlike other IAM policies, RCPs do not allow for specifying individual AWS accounts, IAM roles, or ARNs in the Principal field. Instead, the Principal must always be set to an asterisk, meaning all identities, with access restrictions enforced through the conditions field.
This restriction ensures that RCPs function as broad, overarching access control mechanisms that apply across an entire AWS environment, not a specific user or role.
AWS already has other security and access control layers, so where do RCPs fit in? Let’s examine their inner workings so you can better understand how to use them in your organization.
When an AWS request is made, AWS evaluates permissions in a specific order. RCPs’ guardrails are applied after all other access has been evaluated, so even if all other policies allow an action, RCPs can still deny it.
Let’s run through the policy evaluation order to underscore the guardrail nature of RCPs and help remediate any errors:
You can see how RCPs act as an overarching constraint on resource access. They are evaluated after all other security permissions, giving RCPs the final opportunity to deny an action before it proceeds.
RPCs are applied at the AWS organization level, allowing administrators to enforce security controls across all member accounts.
Inheritance works downwards, meaning that policies applied at the root level of an AWS organization automatically extend to all underlying organizational units (OUs) and accounts:
How are RCPs used in practice to secure cloud resources? We’ll break down a few common use cases and how they work so you can start brainstorming how to put RCPs to work.
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:SecureTransport": "false"
}
}
}
Use case: Enforce HTTPS-only access across all S3 buckets.
This RCP enforces that all S3 requests must use secure transport (HTTPS/TLS). The RCP enforces encryption in transit across all S3 operations, preventing data from being transmitted over HTTP.
While you can configure individual S3 bucket policies to enforce “aws:SecureTransport”, you don’t have to enforce HTTPS-only for every bucket. RCPs provide a stronger, organization-wide enforcement mechanism that avoids the possibility of misconfigurations, even if someone tries to override it with a bucket policy
{
"Effect": "Deny",
"Principal": {"AWS": "*"},
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"StringNotEqualsIfExists": {"aws:PrincipalOrgID": "o-yourorgid"}
}
}
Use case: Prevent external accounts from decrypting KMS keys.
This example blocks the decryption of AWS KMS (Key Management Service) keys for any principal outside your AWS Organization.
Once implemented, the RCP enhances data security and access control by preventing any entity outside your AWS Organization from decrypting your KMS-encrypted data, even if they somehow gain access to encrypted resources.
RCPs are powerful tools for managing access and improving security. However, their benefits depend on correctly implementing them. Improper configuration and deployment can lead to a range of issues, from operational disruptions to failure to prevent a data breach.
We’ve compiled a breakdown of some of the common RCP traps to ensure you correctly utilize and benefit from RCPs.
Why It Burns:
RCPs lack dry-run modes, which means any misconfiguration can quickly cause disruptions and outages. An untested RCP can also create access restrictions that block critical workflows and require time-consuming rollbacks and emergency fixes.
Example failure:
Let’s say an organization enforces an RCP that blocks all cross-account KMS access. This change unexpectedly breaks CI/CD pipelines that rely on shared encryption keys across accounts.
The immediate impact is that developers are unable to deploy updates, resulting in downtime and delays.
Disarm Tactics:
Opaque AccessDenied errors masking RCP conflicts.
Why It Burns:AccessDenied errors are vague and can have many possible causes. These errors can result in engineers wasting hours debugging IAM policies when RCPs are the real culprit.
RCPs operate at the organizational level, overriding other tiers of permissions, which can make AccessDenied failures difficult to identify.
The overall pattern that may be indicative of this error is:
Implement forensic logging by using AWS CloudTrail to trace Deny events with the following:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=Deny
--region us-east-1 --max-items 1000
From there, create granular CloudWatch alarms to filter out “errorCode=”AccessDenied” + userAgent=”AWS Organizations” to pinpoint RCP-related denials quickly.
It’s also advised to use resource tagging for exception visibility:
"Condition": {
"StringEquals": {"aws:ResourceTag/RCP-Exempt": "true"}
}
The Trap: Overly restrictive RCPs breaking vendor integrations
Why It Burns:
Enforcing rigid RCPs can unintentionally lead to disruptions in operations. A common mistake for giving vendors access is hardcoded exceptions, introducing long-term security gaps, such as:
// Risky hardcoded exception
"ArnLike": {"aws:PrincipalArn": "arn:aws:iam::666777888999:role/vendor-prod"}This type of exception grants permanent access and remains in effect even if vendor requirements change, ultimately increasing risk exposure.
Disarm Tactics:
Implement just-in-time access workflows rather than static exceptions. Vendors can request temporary access via a Security Token Service (STS):
# Temporary role assumption for vendors
aws sts assume-role --role-arn arn:aws:iam::123456789012:role/vendor-access \
--role-session-name "TempVendorSession"Additionally, use session tagging with dynamic conditions to restrict access and reduce unnecessary exposure:"Condition": {
"StringEquals": {"aws:PrincipalTag/AccessPurpose": "vendor-audit"}
}
Schedule periodic exception reviews using the AWS Config aggregator to audit and review exceptions regularly and ensure that only necessary access remains active.
RCPs can strengthen your overall security posture but can also introduce new issues if not handled correctly. Successfully implementing Restrictive Control Policies (RCPs) requires a structured approach to testing, governance, and monitoring.
We’ve compiled the following checklist, outlining key focus areas to ensure your organization can seamlessly deploy and maintain RCPs without unintended disruptions.
Unverified, implemented RCPs can introduce access conflicts and break essential services, causing major operational downtime. Rigorous testing helps identify any possible issues before the policy is enforced.
Develop a testing protocol that every RCP must pass before they are implemented. A few options to explore are:
RCPs should be structured for adaptability, which means allowing well-governed exceptions without compromising security. You can use AWS CloudFormation Guard for policy validation with the following:
cfn-guard validate --data rcp-policy.json --rules guard-ruleset
When put to use, this utility helps enforce compliance by preventing misconfigured RCPs from being deployed. Remember, since RCPs can only Deny, properly managing exceptions to these denials is crucial to security.
Additionally, it’s valuable to maintain versioned policy artifacts in AWS CodeCommit, store RCPs in a version-controlled repository to track changes over time. You may also wish to use automated CI/CD pipelines to validate and securely deploy RCP updates.
Develop a monitoring framework that grants ongoing visibility into RCPs. Any misconfigurations or security violations should be identified and quickly remediated.
One key strategy is to leverage critical CloudWatch metrics to track policy effectiveness and detect anomalies. Metrics to track are:
You can also aggregate CloudTrail logs to analyze RCP-related access denials with the following:
SELECT * FROM cloudtrail_logsWHERE eventName = 'Deny' AND eventSource = 'organizations.amazonaws.com'
The returned data provides forensic visibility into policy enforcement and troubleshooting capabilities.
RCPs are a relatively new way to secure AWS resources directly. Failing to restrict AWS can lead to data breaches, higher costs, and non-compliance with data protection regulations.
All it takes is one unprotected or misconfigured resource to enable a devastating cyber attack. It’s well worth leveraging resource-level security to create another layer of protection for your enterprise.
RCPs help, but they’re simply one added safeguard in the complex goal of protecting your cloud environments. To stay protected, you’ll need a series of platforms and experts, that’s where Tamnoon comes in.
We offer managed cloud security remediation that blends AI capabilities with human expertise to ensure your security aligns with your business objectives. Our teams are well-equipped to write RCPs and manage overall security so you don’t have to.
Make remediation the easiest part of your day. Book a demo today to learn more about how we can better secure your cloud environments.