Customising AWS Control Tower with CfCT
Tags: cloud, aws, operations, security
Published: 2022-09-24 12:20:32

If you missed the previous posts on Deploying a Landing Zone with AWS Control Tower or you've not had much experience with the service, I'd recommend going back through and reading those firstly before continuing.

*   [Part 1 - Deploying AWS Control Tower](https://dev.to/adamdivall/deploying-a-landing-zone-with-aws-control-tower-part-1-3k4j)
*   [Part 2 - AWS Control Tower Post Configuration Tasks focusing on Organisational Structure and Guardrails](https://dev.to/adamdivall/deploying-a-landing-zone-with-aws-control-tower-part-2-5e2a)
*   [Part 3 - AWS Control Tower Post Configuration Tasks focusing on IAM Identity Center and Provisioning New AWS Accounts](https://dev.to/adamdivall/deploying-a-landing-zone-with-aws-control-tower-part-3-2bpb)

In this post, I'm going to walkthrough how you can start customising Control Tower using the <a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/security-reference-architecture/welcome.html" target="_blank">Security Reference Architecture (SRA)</a>.  The SRA utilises <a href="https://aws.amazon.com/solutions/implementations/customizations-for-aws-control-tower/" target="_blank">Customisations for Control Tower (CfCT)</a> which deploys a DevOps pipeline that works with CloudFormation templates and Control Tower lifecycle events.

By no means is this the only way of customising the Landing Zone that Control Tower deploys but its my personal preference, as this was also how the previous version of AWS Landing Zones was based upon and therefore I'm more familiar with its setup and configuration. It does have some drawbacks though, in that it is only single threaded and therefore slow in large environments.  There are alternatives though including:

*   <a href="https://service-catalog-tools-workshop.com/" target="_blank">Service Catalog Tools</a>
*   <a href="https://github.com/awslabs/aws-deployment-framework" target="_blank">AWS Deployment Framework (ADF)</a>
*   <a href="https://github.com/aws-ia/terraform-aws-control_tower_account_factory" target="_blank">Account Factory for Terraform</a>

### Why would I want to customise Control Tower?
I think the easiest way to answer this question is simply because whilst Control Tower provides the foundations for a Well-Architected Multi-Account Landing Zone, it's not completely perfect.  

In terms of AWS Services, Control Tower is still in it infancy and whilst AWS are constantly adding new functionality and guardrails; there are still some basic best practices that aren't there natively. For example, in my previous post, I mentioned that AWS Config doesn't get configured in the Management Account but it is in every other Member AWS Account.  

On the other hand, the majority of organisations need to tailor the Landing Zone to meet there specific security and governance requirements.  Therefore the reality is that there is no one size fits all, but there are synergies between them.

### Enable Trusted Access for CloudFormation StackSets in AWS Organizations

I personally didn't need to do this since Control Tower had already enabled this for me, however it's worth double checking just to play safe.

*   Login to the AWS Management Console using an Account with administrative permissions and navigate to the AWS Organizations Console.  This should be done within the Management Account.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fvxeoioljdacdiv4ybp.png)

*   Click **Services**.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h7o4v2y600sjx5p6p6xv.png)

*   Scroll down to CloudFormation StackSets and check that its Trusted Access is set to **Access enabled**.  If not, then Click **CloudFormation StackSets** and then Click **Enable trusted access**.

### Configure an AWS CLI Profile to the Management Account

*   Establish an AWS CLI Profile to the Management Account with administrative credentials via the AWS CLI using either a Command Prompt or from Powershell:
```
aws configure sso
```

*   In the SSO start URL, type the **URL of the SSO Login page**. For example., https://d-1234567890.awsapps.com/start  This can be found by logging into the IAM Identity Center Console and looking for the AWS access portal URL in the Settings.
*   In the SSO Region, type the **AWS Region** that was used for the Home Region when deploying Control Tower. For example., eu-west-2

A Web Browser will then Open prompting for Login Credentials if you're not already logged in.  

*   Login with your Username and Password.
*   Click **Allow**.
*   Select the **AWS Management Account** using the cursor keys.
*   Press **Return** for the default client Region and the default output format.
*   For the Profile name use something memorable as this can be anything. For example., ct-mgmt

### Deploying the SRA Common Pre-Requisites

There are a few things that we need installed on our local device as a pre-cursor for this part including Git, Bash Shell (which in my case I needed to install GitBash for Windows), the AWS CLI v2 and 7-Zip.  Since I'm running a Windows Device the instructions will be based on that.

*   Clone the SRA Source Files from GitHub via either a Command Prompt or from Powershell:
```
git clone https://github.com/aws-samples/aws-security-reference-architecture-examples.git .
```

Now that we have the SRA source files locally we need to start creating some CloudFormation Stacks in our Management Account using the YAML templates within the source. These templates setup the functionality for SRA to work before we even install the Customisations for Control Tower solution.

*   Launch the **sra-common-prerequisites-staging-s3-bucket.yaml** via the AWS CLI using either a Command Prompt or from Powershell:
```
aws cloudformation deploy --template-file /aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-staging-s3-bucket.yaml --stack-name sra-common-prerequisites-staging-s3-bucket --capabilities CAPABILITY_NAMED_IAM --profile ct-mgmt
```

*   Package and upload all the SRA Solutions to the Staging S3 Bucket via GitBash:
```
sh ./aws_sra_examples/utils/packaging_scripts/stage_solution.sh --profile ct-mgmt
```

*   Launch the **sra-common-prerequisites-management-account-parameters.yaml** via the AWS CLI using either a Command Prompt or from Powershell:
```
aws cloudformation deploy --template-file /aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-management-account-parameters.yaml --stack-name sra-common-prerequisites-management-account-parameters --capabilities CAPABILITY_NAMED_IAM --profile ct-mgmt
```

*   Launch the **sra-common-prerequisites-main-ssm.yaml** via the AWS CLI using either a Command Prompt or from Powershell:
```
aws cloudformation deploy --template-file /aws_sra_examples/solutions/common/common_prerequisites/templates/sra-common-prerequisites-main-ssm.yaml --stack-name sra-common-prerequisites-main-ssm --capabilities CAPABILITY_NAMED_IAM --profile ct-mgmt
```

### Deploy the Customisations for Control Tower Solution

The team at AWS that have developed the SRA utilised Customisations for Control Tower (CfCT) as the delivery mechanism for there customisations but since they don't maintain that solution itself, it's strongly recommended to check the current version of CfCT <a href="https://github.com/aws-solutions/aws-control-tower-customizations" target="_blank">here</a> prior to launching the CloudFormation Template.

You may find that you wish to edit **sra-common-cfct-setup-main.yaml** to reflect the following change instead:

```yaml
# TemplateURL: !Sub https://${pSRAStagingS3BucketName}.s3.${AWS::Region}.${AWS::URLSuffix}/${pSRASolutionName}/templates/customizations-for-aws-control-tower.template
TemplateURL: https://s3.amazonaws.com/solutions-reference/customizations-for-aws-control-tower/latest/custom-control-tower-initiation.template
```

The architecture that is deployed by CfCT is shown below.

![](https://docs.aws.amazon.com/controltower/latest/userguide/images/customizations-for-aws-control-tower-architecture-diagram.png)

*   Launch the **sra-common-cfct-setup-main.yaml** via the AWS CLI using either a Command Prompt or from Powershell:
```
aws cloudformation deploy --template-file /aws_sra_examples/solutions/common/common_cfct_setup/templates/sra-common-cfct-setup-main.yaml --stack-name sra-common-cfct-setup-main --capabilities CAPABILITY_NAMED_IAM --profile ct-mgmt
```

### What Customisations should I make?

This is always very subjective and there are many things that may factor into the answer. That being said here is my personal list in no particular order and best of all it's all included within the SRA Source Files with the exceptions of the SCPs. There are also other CloudFormation Templates available within the SRA source files that could be used or alternatively you may wish to create your own.

**CloudFormation**
1.  Enable Config in the Management Account
2.  Enable CloudTrail Organizational Trail for Data Events
3.  Enable EC2 Default EBS Encryption
4.  Configure a Hardened IAM Account Password Policy
5.  Enable S3 Block Public Access at the Account Level
6.  Configure AWS Account Alternate Contacts
7.  Enable IAM Access Analyzer and Configure for Delegated Administration
8.  Enable GuardDuty and Configure for Delegated Administration
9.  Enable Macie and Configure for Delegated Administration
10. Enable Security Hub and Configure for Delegated Administration

**Service Control Policies**
1.  Prevent Accounts from Leaving the Organisation
2.  Prevent the Disabling of any Security Tooling
3.  Prevent IAM User Creation

### Time to Customise our Control Tower Setup

This section will go through customising Control Tower based on my own personal recommendation

*   Install the git-remote-codecommit module via either a Command Prompt or Powershell.
```python
pip install git-remote-codecommit
```

*   Clone the CodeCommit repository that is deployed by CfCT via either a Command Prompt or Powershell. 
```
git clone codecommit://sra-mgmt@custom-control-tower-configuration custom-control-tower-configuration
```
**Note:** You'll need to ensure that you use the name of you AWS CLI profile prior to the `@` as shown in the example above.

*   Within your IDE of choice, under the custom-control-tower-configuration folder delete the **example-configuration** folder.

*   Under the custom-control-tower-configuration fodler create 3 new folders named **parameters**, **policies** and **templates**.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9804ipz6lvse2to4i17a.png)

*   Copy the following files from the SRA source files to **custom-control-tower-configuration\templates**.
    *   sra-account-alternate-contacts-main-ssm.yaml
    *   sra-cloudtrail-org-main-ssm.yaml
    *   sra-config-management-account-main-ssm.yaml
    *   sra-ec2-default-ebs-encryption-main-ssm.yaml
    *   sra-guardduty-org-main-ssm.yaml
    *   sra-iam-access-analyzer-main-ssm.yaml
    *   sra-iam-password-policy-main-ssm.yaml
    *   sra-macie-org-main-ssm.yaml
    *   sra-securityhub-org-main-ssm.yaml
*   Copy the following files from the SRA source files to **custom-control-tower-configuration\parameters**.
    *   sra-account-alternate-contacts-main-ssm.json
    *   sra-cloudtrail-org-main-ssm.json
    *   sra-config-management-account-main-ssm.json
    *   sra-ec2-default-ebs-encryption-main-ssm.json
    *   sra-guardduty-org-main-ssm.json
    *   sra-iam-access-analyzer-main-ssm.json
    *   sra-iam-password-policy-main-ssm.json
    *   sra-macie-org-main-ssm.json
    *   sra-s3-block-account-public-access-main-ssm.json
    *   sra-securityhub-org-main-ssm.json
*   Amend the values as required in each of the JSON files above to customise the configuration of each of the different templates. For example., IAM Password Policy configuration will be defined in the sra-iam-password-policy-main-ssm.json.
*   Create **scp-prevent-accounts-leaving-org.json** in **custom-control-tower-configuration\policies** and paste in the below contents.
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PreventMemberLeavingOrg",
            "Effect": "Deny",
            "Action": [
                "organizations:LeaveOrganization"
            ],
            "Resource": "*"
        }
    ]
}
```
*   Create **scp-prevent-disabling-security-tooling.json** in **custom-control-tower-configuration\policies** and paste in the below contents.
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PreventMemberLeavingOrg",
            "Effect": "Deny",
            "Action": [
                "organizations:LeaveOrganization"
            ],
            "Resource": "*"
        }
    ]
}
```
*   Create **scp-prevent-iam-users-creation.json** in **custom-control-tower-configuration\policies** and paste in the below contents.
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PreventIAMUserCreation",
            "Effect": "Deny",
            "Action": [
                "iam:CreateUser",
                "iam:CreateAccessKey"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```
*   Modify the contents of **manifest.yaml** as per below.
```yaml
---
#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets
region: eu-west-2
version: 2021-03-15

# Control Tower Custom Resources (Service Control Policies or CloudFormation)
resources:
  # -----------------------------------------------------------------------------
  # Account Alternate Contacts
  # -----------------------------------------------------------------------------
  - name: sra-account-alternate-contacts-main-ssm
    resource_file: templates/sra-account-alternate-contacts-main-ssm.yaml
    parameter_file: parameters/sra-account-alternate-contacts-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # Config Management Account
  # -----------------------------------------------------------------------------
  - name: sra-config-management-account-main-ssm
    resource_file: templates/sra-config-management-account-main-ssm.yaml
    parameter_file: parameters/sra-config-management-account-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # Organization CloudTrail
  # -----------------------------------------------------------------------------
  - name: sra-cloudtrail-org-main-ssm
    resource_file: templates/sra-cloudtrail-org-main-ssm.yaml
    parameter_file: parameters/sra-cloudtrail-org-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # S3 Block Account Public Access Solution
  # -----------------------------------------------------------------------------
  - name: sra-s3-block-account-public-access-main-ssm
    resource_file: templates/sra-s3-block-account-public-access-main-ssm.yaml
    parameter_file: parameters/sra-s3-block-account-public-access-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # EC2 Default EBS Encryption Solution
  # -----------------------------------------------------------------------------
  - name: sra-ec2-default-ebs-encryption-main-ssm
    resource_file: templates/sra-ec2-default-ebs-encryption-main-ssm.yaml
    parameter_file: parameters/sra-ec2-default-ebs-encryption-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # IAM Password Policy
  # -----------------------------------------------------------------------------
  - name: sra-iam-password-policy-main-ssm
    resource_file: templates/sra-iam-password-policy-main-ssm.yaml
    parameter_file: parameters/sra-iam-password-policy-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # IAM Access Analyzer Solution
  # -----------------------------------------------------------------------------
  - name: sra-iam-access-analyzer-main-ssm
    resource_file: templates/sra-iam-access-analyzer-main-ssm.yaml
    parameter_file: parameters/sra-iam-access-analyzer-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # Organization GuardDuty
  # -----------------------------------------------------------------------------
  - name: sra-guardduty-org-main-ssm
    resource_file: templates/sra-guardduty-org-main-ssm.yaml
    parameter_file: parameters/sra-guardduty-org-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # Organization SecurityHub
  # -----------------------------------------------------------------------------
  - name: sra-securityhub-org-main-ssm
    resource_file: templates/sra-securityhub-org-main-ssm.yaml
    parameter_file: parameters/sra-securityhub-org-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # Organization Macie
  # -----------------------------------------------------------------------------
  - name: sra-macie-org-main-ssm
    resource_file: templates/sra-macie-org-main-ssm.yaml
    parameter_file: parameters/sra-macie-org-main-ssm.json
    deploy_method: stack_set
    deployment_targets:
      accounts:
        - CT Management

  # -----------------------------------------------------------------------------
  # SCP Prevent Member Account Leaving Organization
  # -----------------------------------------------------------------------------
  - name: scp-prevent-accounts-leaving-org
    description: "This SCP prevents users or roles in any affected account from leaving AWS Organizations, either directly as a command or through the console."
    resource_file: policies/scp-prevent-accounts-leaving-org.json
    deploy_method: scp
    deployment_targets:
      organizational_units:
        - Root

  # -----------------------------------------------------------------------------
  # SCP Prevent Creation IAM Users
  # -----------------------------------------------------------------------------
  - name: scp-prevent-iam-users-creation
    description: "This SCP restricts IAM principals from creating new IAM users or IAM Access Keys in an AWS account."
    resource_file: policies/scp-prevent-iam-users-creation.json
    deploy_method: scp
    deployment_targets:
      organizational_units:
        - Root
```
*   Commit the files that we've previously just copied, modified and deleted to CodeCommit via either a Command Prompt or Powershell.
```
git add .
git commit -m "Committing Changes"
git push
```

This will now trigger the DevOps Pipeline and assuming that no issues have occurred will show as Succeeded.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rel82gecfmbvv717ksnp.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nkuejy9s212a03yv3nkb.png)

Hope this helps and enables you to customise your own Control Tower Environments.