AWS has released an important new feature that allows you to apply permission boundaries around resources at scale called Resource Control Policies (RCPs). Read on to learn what RCPs are all about and how to use them, as well as how Tenable Cloud Security already factors them into its analysis.
AWS just launched Resource Control Policies (RCPs), a new feature in AWS Organizations that lets you restrict the permissions granted to resources.
If you are familiar with service control policies (or SCPs), you may have an idea of what an RCP can do and what it’s good for.
We thought “unboxing” RCPs would be beneficial both for those of you seasoned in using guardrails as well as for novices. So after taking this shiny new feature out for a spin, here’s what we have to say about it.
What are RCPs?
Before we can explain RCPs, we need to cover the concept of guardrails and “data perimeters.” Where AWS really shines in its IAM features is in the multiple mechanisms it provides for managing entitlements to resources in AWS accounts. As practitioners who have been pioneers in helping organizations achieve least privilege and manage access in the most effective way possible, we at Tenable Cloud Security have a lot of appreciation for these features.
Access guardrails are a significant component of the arsenal of tools AWS provides its customers to properly control access to resources. They are robust and highly configurable controls that can be placed on accounts, resources and/or identities to limit the potential sum of permissions they can be assigned. Access-guardrail functions act as a boundary, so even when someone tries to assign unauthorized permissions to an entity – whether the attempt is accidental or malicious -- the access won’t be granted.
A guardrail could be, for example, a “permission boundary” placed on a specific principal, such as an IAM role or IAM user, to limit the potential permissions the principal can have. Or it can be, for example, a resource-based policy applied to a specific resource to limit the principals that can access the resource, the access conditions, the actions that can be performed, and so on. If you wanted to impose such a boundary at scale to all identities in an account or even in several accounts, you could do it using an SCP applied from AWS Organizations.
SCPs are known as very effective boundaries, although they don’t solve the issue of resource-based policies that grant access to principals from external accounts (more on that later).
This kind of boundary may also be known as a “data perimeter.” Several such boundary types exist. We’re going to touch on just a few so if you’re interested in getting more details, we recommend reading this article by AWS which reviews the different ways to create these data perimeters.
Simply put, the newly introduced RCPs are a boundary applied to all resources (of the supported resource types) in an account or accounts. As you can use an SCP to apply a boundary at scale to all principals in an account, instead of to each principal separately using a permission boundary, you can use an RCP to apply a boundary to all resources of an account, instead of to each resource separately using its resource-based policy.
From AWS Organizations, you can create and apply RCPs similarly to how you would an SCP; you can find RCPs under “Policies” in AWS Organizations:
The management interface of RCPs has the same “look and feel” as that of SCPs:
If you listen closely you may be able to hear slide decks about AWS IAM changing around the world, as the widely known policy evaluation logic diagram for AWS access has now been changed to include the RCP:
Why are RCPs important?
As mentioned earlier, SCPs have a well-known limitation: while very effective as a boundary, SCPs ironically don’t solve the issue of resource-based policies that grant access to principals from external accounts. That is, if the resource-based policy applied to a resource grants direct access to a principal from a different account, the SCP will not limit that access. This isn’t intuitive to understand, so many people may not realize this.
Granted, the best practice is to provide such access with an IAM role to be assumed by the principal in the external account, and that IAM role will in turn be granted the permissions required by that principal. However, best practices are often not implemented. Access granted by a resource-based policy is an issue security professionals can’t ignore.
So, RCPs allow you to apply such a boundary at scale, which is great. Until now, doing so was not an option. An added bonus: Having a separate instrument for applying this boundary to resources may improve practitioner awareness that SCPs are a boundary for identities in the account and do not limit external access - that’s the job of the resource oriented control, RCP.
But it’s important to also remember that these boundaries are not just around permissions. You can also use RCPs to enforce conditions on access to resources, which we will detail in the next section.
One last thing: When exploring RCPs, don’t stop using SCPs. They’re highly effective as a boundary and serve their intended purpose: applying a boundary for what identities in the account can perform in the account and outside of it -- meaning on other accounts as well. An RCP doesn’t do this. In short, SCPs and RCPs have different use cases, so keep that in mind.
Usage
So how do we use this boundary goodness? Let’s look at a few examples, and at several important points about RCPs.
Creating data perimeter for a resource
As mentioned, when it comes to scale, RCPs take the creation of a “perimeter” around resources to the next level.
The good news is that all global condition keys, as well as the condition keys of the services that RCPs support, are available in RCPs. This is pretty cool as it allows you to really hit the ground running with RCPs.
For example, if we use attribute-based access control (ABAC) to manage access to a resource, we can limit all access to principals labeled “Dev” to sensitive S3 resources based on their name pattern using an RCP, which will look like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::testing-rcp-pattern-sensitive-bucket-*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/Department": "Dev"
}
}
}
]
}
Unfortunately, “NotAction” is not supported. It would have been great to be able to deny any other action besides very specific ones which would be allowed as exempt. Hopefully, it will be supported some day.
In addition to setting the boundary for principals, you can also enforce that access has to be done from specific VPCs or IPs, as such:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource":"*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "<IP_ADDRESS>"
}
}
}
]
}
Enforce action-related policy
In addition to enforcing access to be done – or not be done – by certain principals or from certain locations, you can also use RCPs to enforce how the access will be granted. RCP functions as a kind of policy as code.
For example, you can enforce that access to S3 buckets will only be done over TLS, as such:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "*",
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}
Or, you can enforce the default SSE server-side encryption on items uploaded to S3 buckets, like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
}
}
]
}
Pretty cool, isn’t it?
Don't cause denial-of-service
Be mindful to avoid creating your own denial of service (DoS) on your infrastructure by denying legitimate access by mission-critical services, employees or customers. When controls are used incorrectly, this can happen.
Here’s an obvious tip: Always test in lower environments (development, testing, staging) every control you’ll apply to production.
That said, keep these things in mind to ease RCPs’ safe adoption :
- The “NotResource” element is supported. You can use it to exclude resources to which the RCPs won’t apply.
- The “NotPrincipal” element is not supported. You must specify “*” as the “Principal.” This isn’t problematic because you can apply the appropriate logic around principals by using condition keys such as “aws:PrincipalArn” and “aws:PrincipalAccount”.
- Third-party services that perform various business functions such as security (like Tenable Cloud Security), DevOps and FinOps on your cloud environment might be blocked by RCPs.You may have to exclude them from those RCPs if you want them to operate properly.
- Finally, since AWS service principals may also be restricted by RCPs, you should use appropriate condition keys (such as aws:PrincipalIsAWSService and aws:PrincipalServiceName) to exclude the relevant ones, as you would in a resource-based policy. (We’ve written about this issue in another blog post).
Services supported
It’s key to keep in mind that RCPs only support a handful of services:
- Amazon S3
- AWS Security Token Service (STS)
- Amazon SQS
- AWS KMS
- AWS Secrets Manager
This is a good start, of course, because SQS, S3 and Secrets Manager usually host sensitive and mission-critical resources, while STS is crucial for creating a boundary around assuming IAM roles. As mentioned, limiting IAM role assumption is important for preventing external identities from gaining access to resources within an account.
And of course, KMS is a sensitive service. Protecting KMS keys with a boundary, for example, for setting the key policy is an amazing use case for RCPs.
Quotas
Similarly to SCPs, there’s a quota for five RCPs per Organizational Unit (OU). You can apply five of each.
Also, similarly to SCPs, there’s a 5,120 character limit per policy, and you can create and store up to 1,000 RCPs in an organization.
Factoring it in to your cloud security
Tenable Cloud Security is a pioneer in the domain of cloud infrastructure entitlements management (CIEM), and we consider it an invaluable component of our cloud native application protection platform (CNAPP) solution.
Being precise in what identities have access to is crucial to understanding the security risk that identities pose and are exposed to.
For this reason, and as a close partner of AWS, we’ve already integrated the new RCP logic to our analysis of the permissions granted to identities.
For example, below you see an IAM user granted access to many buckets in an external account by, most likely, a mistaken resource-based policy applied at scale. Here’s how it looks without an RCP applied:
And here is how it looks with the RCP applied: The RCP limits access to the buckets based on their name pattern:
Spot the difference?
The second finding factors in the RCP and only alerts about excessive permissions granted on the specific bucket, where some actions are needed. This becomes clearer as we see the recommendation for a least-privilege policy generated by Tenable Cloud Security showing exactly which actions the identity requires with regard to this resource:
You can now focus on reducing this specific overpermissiveness not controlled by the RCP.
Conclusion
First of all, kudos to AWS for delivering on this feature.
There are many potential benefits from using RCPs to apply resource-based boundaries at scale.
While there’s plenty of room for RCPs to grow to support more features and services, we believe organizations should start to employ this control as part of their IAM strategy right away.
Simplify AWS cloud security with protection for hybrid and multi-cloud and visit us at AWS re:Invent in Las Vegas next month at booth #520!