Hardening your AWS environment with (not so popular) SCPs part 2

In the previous episode of our series we’ve introduced some not so popular policies for AWS Organizations. They focused on keeping your secrets private and perhaps saving you some money. In this episode we want to continue these series with a look at how we can keep even more things out of the pesky view of the internet. 

In the previous episode of our series we’ve introduced some not so popular policies for AWS Organizations. They focused on keeping your secrets private and perhaps saving you some money. In this episode we want to continue these series with a look at how we can keep even more things out of the pesky view of the internet. 

Ideally most of us would like to keep what we make in the organization private. Many of the digital documents produced inside an organization can and will contain sensitive data. It makes sense to prevent sharing outside your organization wherever possible. 

Let’s start with AMIs – the source images used by EC2 to spin up your VMs. Usually, they are customized by the DevOps teams to include application code. Unless you are in the market for selling your AMIs on the AWS Marketplace there should be no need to share them outside your organization. Since September 2023 AWS automatically blocks public sharing for new organizations. To prevent anyone removing this apply the following:

 

{ 
   "Version": "2012-10-17", 
   "Statement": [ 
       { 
           "Action": [ 
               "ec2:DisableImageBlockPublicAccess" 
           ], 
           "Resource": "*", 
           "Effect": "Deny" 
       } 
   ] 
}

 

If your AWS Organization is older than that you should go individually to each of the accounts and enable the block yourself with this API call: 

 

aws ec2 enable-image-block-public-access --region 'us-east-1' 

 

While we are in the EC2 space a good tip is to enable the EBS Default Encryption. Inside of each account and region you utilize you will need to issue the following command:

aws ec2 enable-ebs-encryption-by-default --region 'us-east-1' 

A corresponding SCPs will prevent users from reverting back the setting:
 

{ 
   "Version": "2012-10-17", 
   "Statement": 
    {
       "Effect": "Deny", 
       "Action": [ 
           "ec2:DisableEbsEncryptionByDefault" 
       ], 
       "Resource": "*" 
    }
}


So, what else should not be made public? After a myriad of mishaps and public shaming, we all know that S3 buckets should not be open to the whole world most of the time. However, most people don’t know that SSM Documents used for automation can also be made publicly available. Similarly, AMIs can contain sensitive information related to the setup and inner company workings. 

The following applied to your environment will disable the possibility:

aws ssm update-service-setting  \ 

    --setting-id /ssm/documents/console/public-sharing-permission \ 

    --setting-value Disable \ 

    --region 'us-east-1'
 

And the corresponding SCP will prevent any tampering with the setting:
 

{ 
    "Version": "2012-10-17", 
   "Statement": [ 
       { 
           "Sid": "DenySSMDocPublicSharingSetting", 
           "Effect": "Deny", 
           "Action": [ "ssm:UpdateServiceSetting", "ssm:ResetServiceSetting" ], 
           "Resource": "arn:aws:ssm:*:*:servicesetting/ssm/documents/console/public-sharing-permission"
       } 
    ]
}


Perhaps the most crucial thing that organizations should consider is if they should allow sharing with AWS Resource Access Manager (RAM). RAM allows us to share various resources like VPCs, Database images or network settings between accounts. Conveniently this feature also allows end users to share the same resources outside of your organization (full list here). Most of the time we would like to keep those resources private. With the below SCP you will prevent the end users from sharing outside your org:

       { 
           "Effect": "Deny", 
           "Action": [ 
               "ram:CreateResourceShare", 
               "ram:UpdateResourceShare" 
           ], 
           "Resource": "*", 
           "Condition": { 
                "Bool": { 
                   "ram:RequestedAllowsExternalPrincipals": "true" 
                } 
           } 
       }, 
       { 
           "Effect": "Deny", 
           "Action": "ram:AcceptResourceShareInvitation", 
           "Resource": "*" 
       } 


We do not live however in a perfect world where we can deny anything (and AWS exception management for SCPs is not existent) so perhaps an organization needs to share some resources between organizations. Many companies operate more than one AWS Organization or they have a special 3rd party they want to give access to. In that case perhaps it is worth limiting access only to the known good organizations:
 

{
            "Effect": "Deny",
            "Action": [
                "ram:AssociateResourceShare",
               "ram:CreateResourceShare"
            ],
            "Resource": "*",
            "Condition": {
               "ForAnyValue:StringNotEquals": {
                   "ram:Principal": [
                       "arn:aws:organizations::123456789012:organization/o-12345",
                       "arn:aws:organizations::123456789012:ou/o-12345/ou-abcdef12345",
                       "111111111111"
                    ]
                }
            }
        }

Conclusion

The above allows sharing with a dedicated organization, specific OU inside an organization and a specific account number. Adjust according to your needs. 

This concludes the second episode of not so well-known SCPs for your AWS Organizations. In the next episode we will focus on the AI headache and how SCPs and organizational settings can help us manage how the AWS organizations use those mostly new services.