Cloud Security
Using AWS Service Control Policies To Protect All Your AWS Accounts

Using AWS Service Control Policies To Protect All Your AWS Accounts

If you have multiple AWS accounts, you more than likely are using AWS Organizations. A continually maturing feature of AWS Organizations is AWS Service Control Policies (SCP), which allows you to apply IAM like policies at the organizational level. This does require you to have your AWS Organizations, well, organized (excuse the pun) into OUs and enabled with all features.

This post will look at some policies that can go a long way in securing your organization. We are working at the Organizations level though, which will immediately affect every AWS account under that OU, so please handle it with care.

Note: In this post, I’ve refrained from the use of Whitelist and Blacklists and have moved towards describing the action itself, such as Permit, Disallow, Deny, etc. Thanks to Marcus Carey for raising awareness.

Table of Contents

  1. Pre-Requisites
  2. Prevent The Deletion or Stopping of CloudTrails with an AWS SCP
  3. Not Allowing Older Generation Instances
  4. Not allowing outside West and East with an AWS SCP
  5. Fine Print of Using AWS SCPs
  6. Conclusion

Pre-Requisites

Image result for aws scp
Courtesy of AWS

Prevent The Deletion or Stopping of CloudTrails with an AWS SCP

CloudTrail is often our first line of defense when investigating incidents or understanding the root cause. Naturally, this is something we would not want unavailable. One way to do this is to prevent the disabling or deletion of CloudTrails:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "cloudtrail:StopLogging",
                "cloudtrail:DeleteTrail"
            ],
            "Resource": "*"
        }
    ]
}

If your company has a federated model towards AWS, you may want to control specific CloudTrails that are centrally managed by the IAAS team or Information Security. This would allow account admins to create and delete CloudTrails as they wish without affecting the integrity of your critical CloudTrails. Here is an example:

{
     "Version": "2012-10-17",
     "Statement": [
         {
             "Effect": "Deny",
             "Action": [
                 "cloudtrail:StopLogging",
                 "cloudtrail:DeleteTrail"
             ],
             "Resource": "arn:aws:cloudtrail:::trail/securitytrail"
         }
     ]
 }

So if we try to disable a CloudTrail covered by an SCP above, we get the following errors: “You don’t have the necessary CloudTrail permissions to delete trail” and “You don’t have the necessary CloudTrail permissions to turn off Cloudtrail.”

Coupled with a CloudTrail applied at the Organization Level, this would provide ultimate management of CloudTrail security across the AWS Organization.

Not Allowing Older Generation Instances

As AWS builds and expands its infrastructure, they continually release newer and newer instance models. To push people into using those instances (as well as capitalize on that infrastructure), they increase the pricing of older and previous generation instances. So utilizing a t3.nano would be more expensive than a t2.nano, for example:

t3.nano on-demand pricing – 6/9/19
t2.nano on-demand pricing – 6/9/19

So we’ll use SCP’s to prevent people from launching previous generation instances. They can still start/stop instances but will not be able to launch new instances:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RequireNewGenerationInstanceType",
            "Effect": "Deny",
            "Action": "ec2:RunInstances",
            "Resource": "arn:aws:ec2:*:*:instance/*",
            "Condition": {
                "StringNotEquals": {
                    "ec2:InstanceType": "t2.micro"
                },
                "StringLike": {
                    "ec2:InstanceType": [
                        "m*",
                        "r*",
                        "x1*",
                        "u-*",
                        "z*",
                        "p*",
                        "g*",
                        "f*",
                        "i*",
                        "d*",
                        "h*"
                    ]
                }
            }
        }
    ]
}

This IAM policy guide was super helpful while building an SCP policy to disallow multiple instance types. Specifically, the condition blocks:

<condition_block> = "Condition" : { <condition_map> }
<condition_map> = { 
  <condition_type_string> : { <condition_key_string> : <condition_value_list> },
  <condition_type_string> : { <condition_key_string> : <condition_value_list> }, ...
}  
<condition_value_list> = [<condition_value>, <condition_value>, ...]
<condition_value> = ("string" | "number" | "Boolean")

Now when we try to launch a t2 instance we get an error.

Not allowing outside West and East with an AWS SCP

AWS is global, but oftentimes, we are operating in only a few regions at most, such as us-east-* or us-west-*. If an attacker is trying to fly under the radar, they will launch instances in an obscure region where there is usually a lack of oversight.

To minimize our attack surface and make our lives a little easier, let’s limit where resources can be started in our AWS accounts. In this case, let’s limit to just us-east-1 and us-west-2. This is usually more than enough for many companies, especially smaller organizations.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyAllOutsideWestandEast",
            "Effect": "Deny",
            "NotAction": "ec2:describe*",
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:RequestedRegion": [
                        "us-east-1",
                        "us-west-2"
                    ]
                }
            }
        }
    ]
}

Here is an error when trying to launch an instance in a region not covered by the SCP above:

Error when trying to launch from a region no permitted above

Notice the following statement:

            "NotAction": "ec2:describe*"

The reason we may need additional describe capabilities is to have audit capabilities into the account. A lot of applications and tools are running queries against accounts to understand their posture either from a billing, resourcing, or security perspective.

However I still receive some errors even with the describe statement.

Unfortunately, AWS will not allow you to do the following in IAM:

*Describe*

or

*:Describe*

I don’t want to enumerate all the service describe clauses possible, so I am fine with the above. Up to you if you want to add additional descriptive statements.

Fine Print of Using AWS SCPs

Some things worth noting is that AWS SCPs do have their limitations. I suggest reading the following references, maybe a couple of times, before applying to your Organization:

SCPs do not apply to service-linked roles

Conclusion

As you can see, the AWS SCPs are very powerful. They are an excellent high impact preventative security tool. Preventative security pays dividends above corrective and detective controls, and should be employed where possible. However, this does mean we shouldn’t implement detective and corrective controls throughout. It’s good to have a backup, as you can imagine. In the end, I highly recommend the use of AWS SCPs throughout your AWS organization.

If this article was helpful to you, consider subscribing to my weekly newsletter, where I share my latest commentary as a vCISO for high growth startups.

Check out how we help startups accelerate and level up their security programs through vCISO (CISO As A Service) and DevSecOps As A Service.

Leave a Reply

Your email address will not be published. Required fields are marked *