Skip to content

Commit 9b216d9

Browse files
authored
Migration from regional to global API identifiers (#8)
1 parent 46fcefc commit 9b216d9

9 files changed

+188
-145
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [2.0.0] - 2024-12-19
8+
### Breaking Changes
9+
- Migration from regional to global API identifiers
10+
711
## [1.0.0] - 2023-06-22
812
### Added
913
- Initial public release

README.md

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
- [AWS Prescriptive Guidance](#aws-prescriptive-guidance)
55
- [Goal](#goal)
6-
- [Prerequisites and limitations](#prerequisites-and-limitations)
6+
- [Prerequisites and Limitations](#prerequisites-and-limitations)
77
- [Architecture](#architecture)
88
- [Tools](#tools)
99
- [Best practices](#best-practices)
@@ -37,15 +37,15 @@ Implementing AWS Control Tower controls helps establish a strong security founda
3737

3838
To deploy AWS Control Tower controls as IaC, you can also use HashiCorp Terraform instead of AWS CDK. For more information, see [Deploy and manage AWS Control Tower controls by using Terraform](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/deploy-and-manage-aws-control-tower-controls-by-using-terraform.html).
3939

40-
### Target Audience
40+
### Intended Audience
4141

4242
This pattern is recommended for users who have experience with AWS Control Tower, CloudFormation, AWS CDK, and AWS Organizations.
4343

44-
## Prerequisites and limitations
44+
## Prerequisites and Limitations
4545

4646
### Prerequisites
4747

48-
- Active AWS accounts managed as an organization in AWS Organizations and an AWS Control Tower landing zone. For instructions, see [Create an account structure](https://www.wellarchitectedlabs.com/cost/100_labs/100_1_aws_account_setup/2_account_structure/) (AWS Well-Architected Labs).
48+
- Active AWS accounts managed as an organization in AWS Organizations and an AWS Control Tower landing zone. For instructions, see [Getting started](https://docs.aws.amazon.com/controltower/latest/userguide/getting-started-with-control-tower.html) in the AWS Control Tower documentation.
4949

5050
- AWS Command Line Interface (AWS CLI), [installed](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [configured](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html).
5151

@@ -63,6 +63,11 @@ This pattern is recommended for users who have experience with AWS Control Tower
6363

6464
### Limitations
6565

66+
- For AWS Control Tower controls, this pattern requires the use of [global identifiers](https://docs.aws.amazon.com/controltower/latest/controlreference/all-global-identifiers.html) that are in the following format:
67+
`arn:<PARTITION>:controlcatalog:::control/<CONTROL_CATALOG_OPAQUE_ID>`
68+
**Note:** In most cases, the value for `<PARTITION>` is aws.
69+
Previous versions of this pattern used [regional identifiers](https://docs.aws.amazon.com/controltower/latest/controlreference/control-metadata-tables.html) that are no longer supported. We recommend that you migrate from regional identifiers to global identifiers. Global identifiers help you manage controls and expand the number of controls you can use.
70+
6671
- This pattern provides instructions for deploying this solution across AWS accounts, from a deployment account to the organization’s management account. For testing purposes, you can deploy this solution directly in the management account, but instructions for this configuration are not explicitly provided.
6772

6873

@@ -76,7 +81,7 @@ AWS Control Tower controls are categorized according to their behavior and their
7681

7782
There are three primary types of control behaviors:
7883

79-
1. Preventive controls are designed to prevent actions from occurring. These are implemented with [service control policies (SCPs)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) in AWS Organizations. The status of a preventive control is either enforced or not enabled. Preventive controls are supported in all AWS Regions.
84+
1. Preventive controls are designed to prevent actions from occurring. These are implemented with [service control policies (SCPs)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) or [resource control policies (RCPs)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html) in AWS Organizations. The status of a preventive control is either enforced or not enabled. Preventive controls are supported in all AWS Regions.
8085

8186
2. Detective controls are designed to detect specific events when they occur and log the action in CloudTrail. These are implemented with [AWS Config rules](https://docs.aws.amazon.com/config/latest/developerguide/evaluate-config.html). The status of a detective control is either clear, in violation, or not enabled. Detective controls apply only in those AWS Regions supported by AWS Control Tower.
8287

@@ -136,7 +141,7 @@ To deploy this solution, you need
136141

137142
| Name | Version |
138143
|------|---------|
139-
| <a name="requirement_ct"></a> [AWS Control Tower](https://aws.amazon.com/controltower/) | >= 3.0 |
144+
| <a name="requirement_ct"></a> [AWS Control Tower](https://aws.amazon.com/controltower/) | >= 3.2 |
140145
| <a name="requirement_python"></a> [Python](https://www.python.org/) | >= 3.9 |
141146
| <a name="requirement_npm"></a> [npm](https://www.npmjs.com/) | >= 8.9.0 |
142147

@@ -180,14 +185,14 @@ ROLE_ARN = "arn:aws:iam::111122223333:role/CT-Controls-Role"
180185
GUARDRAILS_CONFIGURATION = [
181186
{
182187
"Enable-Control": {
183-
"AWS-GR_ENCRYPTED_VOLUMES",
188+
"503uicglhjkokaajywfpt6ros",
184189
...
185190
},
186191
"OrganizationalUnitIds": ["ou-1111-11111111", "ou-2222-22222222"...],
187192
},
188193
{
189194
"Enable-Control": {
190-
"AWS-GR_SUBNET_AUTO_ASSIGN_PUBLIC_IP_DISABLED",
195+
"50z1ot237wl8u1lv5ufau6qqo",
191196
...
192197
},
193198
"OrganizationalUnitIds": ["ou-2222-22222222"...],
@@ -203,14 +208,15 @@ GUARDRAILS_CONFIGURATION = [
203208
204209
4. In the `ROLE_ARN` parameter, enter the ARN of the role you created in the management account.
205210
206-
5. In the `GUARDRAILS_CONFIGURATION` section, in the `Enable-Control` parameter, enter the control API identifiers. Enter the identifier in double quotation marks, and separate multiple identifiers with commas. Each control has a unique API identifier for each Region in which AWS Control Tower is available. To find the control identifier, do the following:
207-
- In [Tables of control metadata](https://docs.aws.amazon.com/controltower/latest/userguide/control-metadata-tables.html), locate the control you want to enable.
208-
- In the Control API identifiers, by Region column, locate the API identifier for the Region in which you are making the API call, such as `arn:aws:controltower:us-east-1::control/AWS-GR_ENCRYPTED_VOLUMES`.
209-
- Extract the control identifier from the Regional identifier, such as `AWS-GR_ENCRYPTED_VOLUMES`.
211+
5. Open [All global identifiers](https://docs.aws.amazon.com/controltower/latest/controlreference/all-global-identifiers.html) in the AWS Control Tower documentation.
212+
213+
6. In the JSON-formatted list, locate the control that you want to implement, and then copy its global identifier (also known as the `{CONTROL_CATALOG_OPAQUE_ID}` value). For example, the global identifier for the `AWS-GR_ENCRYPTED_VOLUMES` control is `503uicglhjkokaajywfpt6ros`.
214+
215+
7. In the `GUARDRAILS_CONFIGURATION` section, in the `Enable-Control` parameter, enter the global identifier that you copied. Enter the identifier in double quotation marks, and separate multiple identifiers with commas.
210216
211-
6. In the `GUARDRAILS_CONFIGURATION` section, in the `OrganizationalUnitIds` parameter, enter the ID of the organizational unit where you want to enable the control, such as `ou-1111-11111111`. Enter the ID in double quotation marks, and separate multiple IDs with commas. For more information about how to retrieve OU IDs, see [Viewing the details of an OU](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html#orgs_view_ou).
217+
8. In the `GUARDRAILS_CONFIGURATION` section, in the `OrganizationalUnitIds` parameter, enter the ID of the organizational unit where you want to enable the control, such as `ou-1111-11111111`. Enter the ID in double quotation marks, and separate multiple IDs with commas. For more information about how to retrieve OU IDs, see [Viewing the details of an OU](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html#orgs_view_ou).
212218
213-
7. Save and close the constants.py file. For an example of an updated constants.py file, see the [Additional information](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/deploy-and-manage-aws-control-tower-controls-by-using-aws-cdk-and-aws-cloudformation.html#deploy-and-manage-aws-control-tower-controls-by-using-aws-cdk-and-aws-cloudformation-additional) section of this pattern.
219+
9. Save and close the constants.py file. For an example of an updated constants.py file, see the [Additional information](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/deploy-and-manage-aws-control-tower-controls-by-using-aws-cdk-and-aws-cloudformation.html#deploy-and-manage-aws-control-tower-controls-by-using-aws-cdk-and-aws-cloudformation-additional) section of this pattern.
214220
215221
216222
## Deployment

constants.py

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,41 +34,41 @@
3434
GUARDRAILS_CONFIGURATION = [
3535
{
3636
"Enable-Control": {
37-
"AWS-GR_ENCRYPTED_VOLUMES",
38-
"AWS-GR_EBS_OPTIMIZED_INSTANCE",
39-
"AWS-GR_EC2_VOLUME_INUSE_CHECK",
40-
"AWS-GR_RDS_INSTANCE_PUBLIC_ACCESS_CHECK",
41-
"AWS-GR_RDS_SNAPSHOTS_PUBLIC_PROHIBITED",
42-
"AWS-GR_RDS_STORAGE_ENCRYPTED",
43-
"AWS-GR_RESTRICTED_COMMON_PORTS",
44-
"AWS-GR_RESTRICTED_SSH",
45-
"AWS-GR_RESTRICT_ROOT_USER",
46-
"AWS-GR_RESTRICT_ROOT_USER_ACCESS_KEYS",
47-
"AWS-GR_ROOT_ACCOUNT_MFA_ENABLED",
48-
"AWS-GR_S3_BUCKET_PUBLIC_READ_PROHIBITED",
49-
"AWS-GR_S3_BUCKET_PUBLIC_WRITE_PROHIBITED",
37+
"503uicglhjkokaajywfpt6ros", # AWS-GR_ENCRYPTED_VOLUMES
38+
"2j9gjxqfo040xtx8kd1jf4ni6", # AWS-GR_EBS_OPTIMIZED_INSTANCE
39+
"8c3i4catfgmyy1e19476v06rr", # AWS-GR_EC2_VOLUME_INUSE_CHECK
40+
"4jc77cq1lcr7g64xywwypykv8", # AWS-GR_RDS_INSTANCE_PUBLIC_ACCESS_CHECK
41+
"1h4eyqyyonp19dlrreqf1i3w0", # AWS-GR_RDS_SNAPSHOTS_PUBLIC_PROHIBITED
42+
"e34kieahgkm0lggs5g0s412jt", # AWS-GR_RDS_STORAGE_ENCRYPTED
43+
"df2ta5ytg2zatj1q7y5e09u32", # AWS-GR_RESTRICTED_COMMON_PORTS
44+
"6rilu41n0gb9w6mxrkyewoer4", # AWS-GR_RESTRICTED_SSH
45+
"5kvme4m5d2b4d7if2fs5yg2ui", # AWS-GR_RESTRICT_ROOT_USER
46+
"8ui9y3oace2513xarz8aqojl7", # AWS-GR_RESTRICT_ROOT_USER_ACCESS_KEYS
47+
"24izmu4k16gv9tvd7sexnyrfy", # AWS-GR_ROOT_ACCOUNT_MFA_ENABLED
48+
"8sw3pbid15t9cbww8d2w2qwgf", # AWS-GR_S3_BUCKET_PUBLIC_READ_PROHIBITED
49+
"9j9nwxj789d82sypnukhyyowy", # AWS-GR_S3_BUCKET_PUBLIC_WRITE_PROHIBITED
5050
},
5151
"OrganizationalUnitIds": ["ou-1111-11111111"],
5252
},
5353
{
5454
"Enable-Control": {
55-
"AWS-GR_SUBNET_AUTO_ASSIGN_PUBLIC_IP_DISABLED",
56-
"AWS-GR_AUTOSCALING_LAUNCH_CONFIG_PUBLIC_IP_DISABLED",
57-
"AWS-GR_DISALLOW_CROSS_REGION_NETWORKING",
58-
"AWS-GR_DISALLOW_VPC_INTERNET_ACCESS",
59-
"AWS-GR_DISALLOW_VPN_CONNECTIONS",
60-
"AWS-GR_DMS_REPLICATION_NOT_PUBLIC",
61-
"AWS-GR_EBS_SNAPSHOT_PUBLIC_RESTORABLE_CHECK",
62-
"AWS-GR_EC2_INSTANCE_NO_PUBLIC_IP",
63-
"AWS-GR_EKS_ENDPOINT_NO_PUBLIC_ACCESS",
64-
"AWS-GR_ELASTICSEARCH_IN_VPC_ONLY",
65-
"AWS-GR_EMR_MASTER_NO_PUBLIC_IP",
66-
"AWS-GR_LAMBDA_FUNCTION_PUBLIC_ACCESS_PROHIBITED",
67-
"AWS-GR_NO_UNRESTRICTED_ROUTE_TO_IGW",
68-
"AWS-GR_REDSHIFT_CLUSTER_PUBLIC_ACCESS_CHECK",
69-
"AWS-GR_S3_ACCOUNT_LEVEL_PUBLIC_ACCESS_BLOCKS_PERIODIC",
70-
"AWS-GR_SAGEMAKER_NOTEBOOK_NO_DIRECT_INTERNET_ACCESS",
71-
"AWS-GR_SSM_DOCUMENT_NOT_PUBLIC",
55+
"50z1ot237wl8u1lv5ufau6qqo", # AWS-GR_SUBNET_AUTO_ASSIGN_PUBLIC_IP_DISABLED
56+
"aemn4s3hxv9erree434pvjboi", # AWS-GR_AUTOSCALING_LAUNCH_CONFIG_PUBLIC_IP_DISABLED
57+
"dvuaav61i5cnfazfelmvn9m6k", # AWS-GR_DISALLOW_CROSS_REGION_NETWORKING
58+
"41ngl8m5c4eb1myoz0t707n7h", # AWS-GR_DISALLOW_VPC_INTERNET_ACCESS
59+
"5rlqt6yj6u0v0gb62pqdy4ae", # AWS-GR_DISALLOW_VPN_CONNECTIONS
60+
"dekrrxbiux86m6jdowdsbamze", # AWS-GR_DMS_REPLICATION_NOT_PUBLIC
61+
"87qo8rsoettjrxjevmjqcw1tu", # AWS-GR_EBS_SNAPSHOT_PUBLIC_RESTORABLE_CHECK
62+
"4v7xtm83uvvyulk1wwpm4qm3s", # AWS-GR_EC2_INSTANCE_NO_PUBLIC_IP
63+
"aeellyghb27pbehyzua1nyena", # AWS-GR_EKS_ENDPOINT_NO_PUBLIC_ACCESS
64+
"2civrte1w8tqff4vbtzdl4abq", # AWS-GR_ELASTICSEARCH_IN_VPC_ONLY
65+
"5cnql6so7p7bs0khdjodjr9e2", # AWS-GR_EMR_MASTER_NO_PUBLIC_IP
66+
"b2gzofz99eb7nsuj5g8wcimse", # AWS-GR_LAMBDA_FUNCTION_PUBLIC_ACCESS_PROHIBITED
67+
"b8pjfqosgkgknznstduvel4rh", # AWS-GR_NO_UNRESTRICTED_ROUTE_TO_IGW
68+
"1oxkwnc4hwhi2ndv6ekwy7np7", # AWS-GR_REDSHIFT_CLUSTER_PUBLIC_ACCESS_CHECK
69+
"6wmutsohbkwhfw6sf7cbt5e81", # AWS-GR_S3_ACCOUNT_LEVEL_PUBLIC_ACCESS_BLOCKS_PERIODIC
70+
"66gfl06uj1v999z53szvu0exa", # AWS-GR_SAGEMAKER_NOTEBOOK_NO_DIRECT_INTERNET_ACCESS
71+
"dfanrd8y5p7oj8fjyugqnakfr", # AWS-GR_SSM_DOCUMENT_NOT_PUBLIC
7272
},
7373
"OrganizationalUnitIds": ["ou-2222-22222222"],
7474
},

img/ctc-architecture.png

4.21 KB
Loading

requirements/requirements-dev.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
-c requirements.in
22

33
bandit
4-
black<=22.12.0 # latest version of safety requires a previous version of black
4+
black
55
coverage
6-
flake8~=3.9
6+
flake8
77
isort
88
mypy
99
pylint

0 commit comments

Comments
 (0)