"Deny All" for Public Buckets: AWS Resource Control Policies (RCP) Extend Centralized Cloud Governance

5 mins to read

AWS’s release of Resource Controls Policies (RCP) when used in combination with existing Service Control Policies (SCP), enables Cloud Architects to create an identity perimeter controlling all undesired permissions and access to resources at scale. Their usage removes the need for cumbersome least privilege requirements for every workload, facilitating developer innovation.

Understanding RCP

A Resource Control Policy (RCP) denies access to a permission on a resource across any account that is below the OU where it is attached in an AWS Organization. They do not grant permissions, but define the maximum permissions and access that may occur. Developers can still create resource policies and trust that would appear to allow public or external access, but the RCP policy would override that and deny the access at the request time.

The Need for RCP

The most obvious use case prevents accidental public exposure of resources, including S3 Data, Queues, Roles, and Secrets that might be exposed through a misconfigured resource policy. Public S3 buckets are the most obvious of the obvious.

There are approximately 30 services in AWS that allow public exposure of resources like this, including snapshots, backups, tables, keys, gateways, etc. Any service in the following AWS reference list that has a green check in the “Resource-based policies” column would qualify. We look forward to future additions to supported services in the RCP roadmap.

To illustrate this is still an unsolved problem, a quick jump over to GrayHatWarfare will give you some visibility into the number of files that get exposed this way.  

Example Scenario

Consider an S3 bucket intended to be accessed from Cloudfront. However, the developer is troubleshooting and adding a principal of * as an alternative to see if that works after getting an error.

This policy accidentally exposes the bucket to the Internet unauthenticated. AWS has many ways to block public S3 buckets, but until now, most other resources could not be blocked.

Fix with Deny First Model

A central way to combat the risk of misconfigurations like the one described above is to implement a ‘deny-first’ model using RCPs. As the name suggests, this model starts by denying all public access across all accounts. However, it allows for specific, intentional exceptions for public-facing resources, such as a website hosted on an S3 bucket. By implementing this model, you can significantly reduce the risk of public resource exposure.

Example Policy:

Alternatively, this could be written using Conditions vs. NotResource; however, NotResource is simpler and uses fewer characters.

Example Policy with Conditions:

Valid Uses of a Principal of “*”

There are valid reasons for using a Principal of * in a resource policy that are not public and are best practices.

Examples from AWS Documentation:

In both cases, these DynamoDB resource policies are restrictive. However, what if “arn:aws:iam::123456789012:user/John” is a bad actor from outside your account who added that to maintain persistence after a breach clean up.

This is where RCPs can save you.  The condition key “aws:PrincipalOrgID” can check if the Identity making the request is part of an AWS Organization and “aws:SourceOrgID” can check if an AWS service making that call originates from inside your Organization. You can completely deny access to all external sources using these keys.

For example, RCP denies access to all identities and services outside your AWS organization.

If you implement this, you will discover you have a lot of access from outside your Organization. For example, you might use a third party for security visibility, log management, performance monitoring, cost savings, etc., and those will all immediately break. You also might have multiple orgs doing cross-organization logging or Marketplace subscriptions that require access.

Handling Exceptions

The RCP policies support putting in exceptions. I would argue the Cloud Operations/Infrastructure team should be aware of all third-party access to your Org. Admittedly, if you haven’t had much supervision over development teams, getting your arms around that might be a task, but a worthwhile one. Assuming you have the list of resources those parties need to access, it is pretty easy to flip the “Resource”: “*” part of the policy to “NotResource”: “<Allowed Resources>”.

Example Policy:

For example, RCP denies access to all identities and services outside your AWS organization.

This allows you to exempt any resource a third party must access from outside your org. This will scale up to a point, but per RCP policy, the limit is 5120 characters. If you are in a scenario where you need to scale beyond the limit of what will fit in the RCP, you will need to use ABAC controls such as “aws:ResourceTag” or “aws:PrincipalTag”.

Why You Need Both SCPs and RCPs

SCPs are controls for your users and roles that exist in your member accounts. They control which permissions, and under what circumstances you allow your principal to execute an API call. We use these heavily in the Sonrai Cloud Permissions Firewall.

RCPs control what identities can access your resource with what permissions under which conditions – like encryption. You can specify controls that apply to all resource types or controls that should only apply to resources of a specific type.

Additional Uses for RCP

RCPs can also be used to enforce encryption controls, such as requiring that all data stored in S3 buckets must be encrypted at rest or in transit:

Example Policy:

This policy ensures that all objects put into any S3 bucket or modifications to API Gateway must use AWS KMS for encryption.

Conclusion

AWS’s introduction of RCP adds a robust tool to the security arsenal of AWS Organizations, enabling finer control over resource access and ensuring that compliance and security do not stifle innovation. By understanding and implementing RCP correctly, organizations can protect their resources from unintended public exposure while maintaining the flexibility required for agile development.