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. 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.
The Basics: What are RCPs?
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:
- KMS
- S3
- SQS
- STS
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.
Secrets Manager
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.
Understanding the Core Components of an RCP
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" }
} |
1. Version
"Version": "2012-10-17" 2. Statement
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": [ { ... }, { ... } ]
3. Sid (Statement ID)
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"
4. Effect
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",
5. Principal
"Principal": "*", 6. Action
"Action": "s3:PutObject", 7. Resource/NotResource
- Resource specifies the exact AWS resource the policy applies to with ARNs.
-
- For example,
"arn:aws:s3:::prod-*"will restrict all S3 buckets with a prod- prefix. - On the other hand,
"arn:aws:ec2:::instance/*"would apply to all EC2 instances in any region.
- For example,
-
- NotResource excludes certain resources from the policy’s effect, allowing all others to be affected.
- For example,
“NotResource”: “arn:aws:s3:::public-bucket”would apply the policy to all resources except for the public-bucket. - On the other hand,
"NotResource": "arn:aws:s3:::internal-"would exclude all buckets with the internal- prefix.
- For example,
- Resource and NotResource are mutually exclusive — you cannot use both Resource and NotResource in the same statement.
- Wildcards are allowed in both fields.
"Resource": "arn:aws:s3:::prod-*" 8. Condition
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"}
}
RCPs vs SCPs
In general, the two types of policies that determine access are identity-based policies and resource-based policies.
- Identity-based policies are policies attached to an identity (aka a principal) that determine what they can do.
- Resource-based policies are attached to a resource and determine who can access and interact with that resource.
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:
- Have length limits.
- Do not grant permissions.
- Support a restricted subset of IAM policy syntax.
- It can be applied at the organization, OU, or account level.
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 |
Understanding the Key Constraints of RCPs
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.
RCPs Only Support Deny Effects
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.
Maximum 5 Statements Per Policy
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.
Possibly Restrictive Character Limit
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.
Principal Field Cannot Specify Individual Accounts/ARNs
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.
How Do RCPs Work?
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.
Policy Evaluation Order
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:
- IAM policies evaluation: AWS’s first stop is checking an IAM user group, role, and policies. If an IAM policy explicitly allows the action, the evaluation proceeds. Otherwise, the action is denied.
- Permission boundaries evaluation: If a permission boundary is attached to the IAM entity (whether it’s a user or a role), AWS verifies that the requested action is allowed by the boundary. If the boundary doesn’t allow the action, it’s denied regardless of whether the identity-based policy permits it or not. In other words, permission boundaries do not grant permissions – they only limit them in case another policy explicitly grant them.
- Resource-based policies evaluation: These policies are attached to AWS resources, like an S3 bucket’s policies. Just like IAM, the request proceeds if resource-based policies allow it.
- AWS service-specific access controls: Some AWS services have built-in access controls.. These policies must also be evaluated before proceeding too RCP evaluation. If approved, the action proceeds.
- RCP evaluation: The final enforcement layer is RCPs. If RCPs dictate that an action is denied but approved at all previous layers, the action is still denied.
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.
How Inheritance Across AWS Organizations Works
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:
- Root-level RCPs: An RCP applied at the root of an AWS Organization will affect all accounts within the organization, including any new accounts added in the future.
- OU-level RCPs: If an RCP is applied to a specific OU, all accounts within the OU will also inherit the policy.
- Account-level RCPs: Individual accounts inherit RCPs from their parent OU, which means individual accounts cannot override these policies.
Real-World RCP Examples of Common Use Cases
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.
RCP Example #1: Block HTTP access to S3 Buckets
{
"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
RCP Example #2: Restrict Cross-Account KMS Access
{
"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.
RCP Traps to Avoid
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.
Trap #1: The “Set and Forget” Deployment Trap
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:
- Implement a phased rollout strategy throughout organizational units:
- Staging OU for initial testing in a controlled environment.
- Access Analyzer Validation to identify any unintended access denials before enforcement.
- Monitoring OU to enable logging and alerts for potential conflicts.
- Production OU applies policies only after validation and monitoring to confirm there are no disruptions.
- Detecting RCP policy drift with AWS Config rules and custom lambda functions ensures that policies do not unexpectedly change.
- Create CloudWatch dashboards that track RCPPolicyChanges and DeniedRequests, providing real-time insights into access failures.
Trap 2: The Phantom Access Denial
- A developer configures an S3 bucket with an IAM policy explicitly allowing access.
- Despite this, access requests fail due to an overriding RCP restriction that supersedes that IAM policy.
- The error message lacks details and simply says AccessDenied, leading engineers to spend hours debugging the wrong policies.
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"}
}
Trap 3: The Third-Party Access Time Bomb
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.
Survival Checklist for a Successful RCP Implementation
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.
1. Testing Protocol
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:
- Use AWS IAM Access Analyzer to identify any unintended access restrictions to prevent any service disruptions.
- Regularly audit findings to adjust policies as necessary before enforcement.
- Evaluate how RCPs and SCPs might interact to ensure the expected outcomes. You may wish to use an IAM policy simulator.
2. Exception Governance
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.
3. Monitoring Framework
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:
- “AWS/RCP DeniedRequests” which identifies spikes in denied access attempts
- “AWS/RCP PolicyChangeEvents” which detects unauthorized or unintended policy modifications.
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.
Go Further Than RCPs with Managed Cloud Security Remediation
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.