AWS Resource Control Policies (RCPs) Explained: A Practical Guide to Resource-Level Security

Published: (January 14, 2026 at 03:54 AM EST)
5 min read
Source: Dev.to

Source: Dev.to

Modern AWS Governance with Resource Control Policies (RCPs)

Modern AWS environments are built for scale — multiple accounts, shared teams, and resources that need to operate across boundaries. While this flexibility enables agility, it also introduces a critical governance challenge: even when IAM policies and SCPs are correctly configured, resource policies can still be mis‑configured, resulting in overly broad access or unintended exposure.

That gap is exactly what Resource Control Policies (RCPs) were created to address.

What RCPs Do

RCPs let you enforce non‑negotiable rules directly on resources, such as:

  • This resource can never be shared outside the organization.
  • Only approved identities can assume roles here.
  • Even admins can’t break these rules.

Note: RCPs don’t replace IAM or SCPs — they fill the last missing governance layer.

LayerWhat it controls
IAMWhich principals can perform which actions on which resources, within organizational guardrails.
SCPThe maximum permissions IAM principals in an account or OU can ever have; they restrict but do not grant access.
RCPThe maximum permissions that can ever apply to specific resources in accounts or OUs, regardless of which principal calls them.

Hands‑On Demo

⚠️ It is highly advisable to test RCPs in a dev/test account before applying them in production. Do not apply directly at the root level.

In this demo we cover two scenarios:

  1. Enforce HTTPS‑only access across all S3 buckets
  2. Prevent external accounts from decrypting KMS keys (or disable cross‑account use of KMS keys)

Scenario #1 – Enforce HTTPS‑only on S3 Buckets

1. Create an over‑permissive bucket policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "S3rcppolicy",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::XXXX-XXXXX-demo-XXXXXXX/*"
    }
  ]
}

The bucket contains a simple file with the text RCP HTTPS test.

2. Verify HTTP and HTTPS both work

  • HTTP test

    HTTP access

  • HTTPS test

    HTTPS access

3. Apply an RCP at the account level to allow only HTTPS

RCP attached to S3

4. Observe the result

  • HTTP request → AccessDenied (highlighted in the screenshot)

    HTTP error after RCP

  • HTTPS request → succeeds

Takeaway: Once an RCP is applied, it governs both existing and newly created resource policies. Ensure you review which resources are intentionally shared across the organization before enforcing an RCP.

Scenario #2 – Prevent External Accounts from Decrypting KMS Keys

This example blocks decryption of AWS KMS keys for any principal except a whitelisted principal defined in the key policy.

1. Sample KMS key policy (granting cross‑account access)

{
  "Sid": "Enable IAM User Permissions",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::714XXXXXXXXX:root"
  },
  "Action": "kms:*",
  "Resource": "*"
},
{
  "Sid": "Allow use of the key",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::599XXXXXXXXX:root"
  },
  "Action": [
    "kms:Encrypt",
    "kms:Decrypt",
    "kms:ReEncrypt*",
    "kms:GenerateDataKey*",
    "kms:DescribeKey"
  ],
  "Resource": "*"
}

2. Test decryption without RCP

  • Encrypt a file using the KMS key in Account A (714XXXXXXXXX).

  • Decrypt the file from both:

    • Account A (same account) – succeeds.
    • Account B (599XXXXXXXXX) – also succeeds because of the cross‑account permission.

Account A decryption result

KMS decryption – Account A

Account B decryption result (truncated for brevity)

KMS decryption – Account B

3. Apply an RCP that disallows cross‑account decryption

After attaching the appropriate RCP at the account or OU level, attempts from Account B to decrypt the key are denied, while Account A retains its ability to use the key.

Result: The RCP enforces the “maximum permissions” rule on the KMS resource, overriding the permissive key policy for any external principal.

Summary

  • IAM controls who can do what on which resources.
  • SCPs set the maximum permissions an IAM principal can ever have in an account/OU.
  • RCPs set the maximum permissions that can ever be applied to specific resources, regardless of the caller.

By adding RCPs you close the final governance gap, ensuring that even a perfectly‑written IAM policy or SCP cannot be bypassed by a mis‑configured resource policy. Test thoroughly in non‑production accounts, then roll out strategically to protect your most critical resources.

kms-policy

Applying the RCP to Account A

{
  "Effect": "Deny",
  "Principal": "*",
  "Action": [
    "kms:Decrypt",
    "kms:Encrypt",
    "kms:GenerateDataKey"
  ],
  "Resource": "*",
  "Condition": {
    "StringNotEquals": {
      "aws:PrincipalAccount": [
        "714XXXXXXXXX"
      ]
    }
  }
}

kms-deny

Before Implementing Resource Control Policies (RCPs)

RCPs are a powerful AWS feature for designing data perimeters. They protect data, block breaches, and enforce real cloud perimeters—but if deployed carelessly, they can also break production workloads.

We must create and test RCPs before applying them to critical workloads.

Before you deploy any RCP, make sure it passes through a formal test cycle.

What to Test

Use AWS IAM Access Analyzer to understand:

  • Which resources are currently public
  • Which resources are shared externally
  • Which identities depend on cross‑account access

This helps you avoid breaking legitimate access paths.

Then validate policy logic using:

  • IAM Policy Simulator
  • Controlled sandbox accounts
  • Development OUs before production

Also test interactions between Service Control Policies (SCPs) and RCPs.

Remember: a deny from either one will block access.

Other High‑Impact RCP Use Cases to Explore

AWS maintains a fantastic repository of real‑world RCP patterns:

  • 🔐 Enforce Org‑Only STS Access
  • 🔑 Lock Down OIDC Providers (GitHub Actions, etc.)
  • 🗄️ Block External Sharing of Data Stores

When used thoughtfully, RCPs close the last remaining gaps around data access, cross‑account trust, and misconfigurations.

Good security isn’t about trusting people—it’s about designing systems that remain safe even when mistakes happen.

Thanks for reading — hope this helps you build safer, more resilient AWS environments.

Back to Blog

Related posts

Read more »

𝗗𝗲𝘀𝗶𝗴𝗻𝗲𝗱 𝗮 𝗣𝗿𝗼𝗱𝘂𝗰𝘁𝗶𝗼𝗻‑𝗥𝗲𝗮𝗱𝘆 𝗠𝘂𝗹𝘁𝗶‑𝗥𝗲𝗴𝗶𝗼𝗻 𝗔𝗪𝗦 𝗔𝗿𝗰𝗵𝗶𝘁𝗲𝗰𝘁𝘂𝗿𝗲 𝗘𝗞𝗦 | 𝗖𝗜/𝗖𝗗 | 𝗖𝗮𝗻𝗮𝗿𝘆 𝗗𝗲𝗽𝗹𝗼𝘆𝗺𝗲𝗻𝘁𝘀 | 𝗗𝗥 𝗙𝗮𝗶𝗹𝗼𝘃𝗲𝗿

!Architecture Diagramhttps://dev-to-uploads.s3.amazonaws.com/uploads/articles/p20jqk5gukphtqbsnftb.gif I designed a production‑grade multi‑region AWS architectu...