Drawing A Line In The Cloud – How Permission Boundaries Confine Access Limits

IAM Permission Boundaries

Effectively controlling and maintaining proper access to our critical business infrastructure is one of, if not the primary concern of any organization. Let’s face it though, the human element is the leading risk to our best intentions and design when it comes to security. Be it as bad as insider threats or as simple as a lazy typo in a policy; access can be opened to areas we didn’t intend, and when that’s our cloud infrastructure, sometimes the access given are the keys to the castle.

Enter Permission Boundaries. Permission Boundaries are a recent feature added to AWS’ IAM service which can be applied to users and roles that creates a fence around the upper-limit of their possible permissions. Since IAM is a global service, (in that its resources are not bound to a region) any one user or role has the potential to make very large sweeping changes across many VPCs, resources, and regions if permissions are not properly defined and also contained.

Example – Controlling Data Boundaries

Take for example a scenario where we are supporting numerous VPCs and S3 buckets in a single account with each VPC serving a separate customer. No one customer’s S3 data or resources should ever mix with another’s.

Let’s say that for each customer VPC an EC2 instance is created and a corresponding S3 bucket is too. So we create and apply an IAM role for the instance with a corresponding policy and instance profile allowing it full access to just the bucket we need for “Customer-X”:

{

"Version": "2012-10-17",

"Statement": [

{

"Sid": "Customer-X",

"Effect": "Allow",

"Action": "s3:*",

"Resource": [

"arn:aws:s3:::customer-x",

"arn:aws:s3:::customer-x/*"

]

}

]

}

Knowing that this is the extent of access this instance should have, we add the same policy as a Permission Boundary. This now means no matter what other policies are applied to the role, the instance will only ever be able to work within the “customer-x” bucket.

Fast-forward a few months, our company is doing great and growing rapidly which means so is the number of customers we’re supporting and thus the number of resources to manage. SSM is a great AWS service to enable orchestration of actions across our EC2 instances for things like patching, change management, shell access, and more. So we install the SSM agent across our instances as well as apply the AWS Managed Policy “AmazonEC2RoleforSSM” to allow for SSM management.

Something’s wrong though, we can’t perform any of the actions we expected. We remember that we applied Permission Boundaries and realize that the boundary must be updated with additional exceptions to match the policy we want to apply.

As we dig deeper into the policy, we see that “AmazonEC2RoleforSSM” actually allows s3:GetObject and s3:PutObject to all buckets in our account – had the original boundary not been in place, cross-customer data access would have been possible and thus possibly breaching contracts, NDAs, and compliance standards. We just saved our customers’ integrity and a lot of personal stress.
Leveraging IaC
Taking this a step further and applying a DevOps approach, we can fold permission boundaries into our Infrastructure as Code (IaC) to ensure compliance is more automated and assured.

New to IAM, we can now tag our users and roles with a key:value pair such as customer:customername. From there we can use a platform such as Terraform to then iterate through IAM resources in our code-base; if a role matches a particular customer tag, then the corresponding custom Permission Boundary policy is applied ensuring that all resources managed in our code are kept to a standard.