Control Tower Guardrails overview (Preventive, Detective and Proactive)

Table of Contents

A Guardrail (or Control) is a high-level rule that provides ongoing governance for your overall AWS environment. It’s expressed in plain language. AWS Control Tower implements preventive, detective, and proactive controls that help you govern your resources and monitor compliance across groups of AWS accounts.

A control applies to an entire organizational unit (OU), and every AWS account within the OU is affected by the control. Therefore, when users perform work in any AWS account in your landing zone, they’re always subject to the controls that are governing their account’s OU.

In this post, we will look at all three types of Controls, what AWS resources they are based on, and how they work.

Detective controls

The detective controls are implemented using AWS Config rules. They detect noncompliance of resources within your accounts, such as policy violations, and provide alerts through the dashboard.

There are 229 Detective controls available at the moment of writing this article:

Let’s try this detective control Detect whether encryption is enabled for Amazon EBS volumes attached to Amazon EC2 instances

The artifact for this control is the following AWS Config rule:

AWSTemplateFormatVersion: 2010-09-09
Description: Configure AWS Config rules to check for encryption of all storage volumes attached to compute
Parameters:
  ConfigRuleName:
    Type: 'String'
    Description: 'Name for the Config rule'
Resources:
  CheckForEncryptedVolumes:
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: !Sub ${ConfigRuleName}
      Description: Checks whether EBS volumes that are in an attached state are encrypted.
      Source:
        Owner: AWS
        SourceIdentifier: ENCRYPTED_VOLUMES
      Scope:
        ComplianceResourceTypes:
          - AWS::EC2::Volume

Once you enabled the Control, a new CloudFormation StackSet will appear and Deploy a new AWS Config rule to the target accounts:

How it looks like in the target account:

I have created a new EC2 instance with not-encrypted EBS volume:

And we see the detected violation in the Control Tower dashboard:

Preventive controls

A preventive control ensures that your accounts maintain compliance because it disallows actions that lead to policy violations. The status of a preventive control is either enforced or not enabled. Preventive controls are supported in all AWS Regions.

The preventive controls are implemented using Service Control Policies (SCPs), which are part of AWS Organizations.

There are 49 Preventive controls available at the moment of writing this article:

Let’s try this one Require that an Amazon EBS snapshot cannot be publicly restorable.

This control prevents unencrypted EBS snapshots from being made public, by disallowing sharing of EBS snapshots with all AWS accounts. Encrypted snapshots and snapshots with AWS Marketplace product codes cannot be made public.

Once you enabled a preventive control, you will see a new Service Control Policy in the AWS Organizations console:

This policy has been added to the target Organizational Unit:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CTEC2PV3",
            "Effect": "Deny",
            "Action": "ec2:ModifySnapshotAttribute",
            "Resource": "arn:*:ec2:*::snapshot/*",
            "Condition": {
                "StringEquals": {
                    "ec2:Add/group": "all"
                }
            }
        }
    ]
}

Let’s try to make an unencrypted snapshot public in the target account:

Request failed:

Proactive controls

Proactive controls check resources whenever those resources are created or updated through AWS CloudFormation stack operations. Specifically, these proactive controls are implemented as preCreate and preUpdate AWS CloudFormation hook handlers. Consequently, these controls may not affect requests made directly to services through the AWS console, AWS APIs, or other means such as AWS SDKs or other Infrastructure-as-Code (IaC) tools.

There are 235 Proactive controls available at the moment of writing this article:

As an example, let’s try the Proactive Control Require that Amazon S3 bucket requests use Secure Socket Layer,

Amazon S3 buckets should have policies that require all requests (Action: S3:*) to accept transmission of data over HTTPS in the S3 resource policy only, as indicated by the condition key aws:SecureTransport.

But, first of all, we need to enable another control, Disallow management of resource types, modules, and hooks within the AWS CloudFormation registry, as a prerequisite for all Proactive controls

Which enables the following SCP

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "GRDISALLOWMODIFICATIONCFNREGISTRY",
            "Effect": "Deny",
            "Action": [
                "cloudformation:RegisterType",
                "cloudformation:DeregisterType",
                "cloudformation:SetTypeConfiguration",
                "cloudformation:SetTypeDefaultVersion",
                "cloudformation:PublishType"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "ArnNotLike": {
                    "aws:PrincipalARN": "arn:aws:iam::*:role/AWSControlTowerExecution"
                }
            }
        }
    ]
}

Once we enabled the Proactive control for S3, we can see a CloudFormation StackSet, which deployed a CloudFormation Hook

Let’s try to deploy an S3 bucket with a deliberately incorrect bucket policy:

It fails during the deployment (hook failed):

If we add the condition “SecureTransport”:

Here, you can find the rule specification (maybe it can be helpful during the troubleshooting):

Part, which checks a bucket policy:

rule check_statement_ssl_requests_only(statement) {
    %statement{
        check_all_required_statement_properties(this)

        Effect == "Deny"
        Action[*] in ["s3:*", "*"]

        Principal == "*" or
        Principal {
            AWS exists
            AWS == "*"
        }

        Resource[*] == "*" or
        check_resource_for_bucket_arns(Resource) or
        check_resource_for_bucket_arn_refs(Resource)

        Condition is_struct
        Condition == {
            "Bool": {
                "aws:SecureTransport": "false"
            }
        }
    }
}

Conclusion

Control Tower Guardrails (or Conrols) help you centrally manage security in the AWS Organization. There are three types of control: Detective, based on AWS Config rules, which notifies you about non-compliant resources; Preventive, based on Service Control Policies, which explicitly denies some actions; and Proactive, based on CloudFormation hooks, which denies the creation of resources that don’t comply with the determined rules. Proactive controls make sense only if you use CloudFormation. One practical example was demonstrated for every type of control.