Skip to content

Commit 7e29162

Browse files
committed
chore: in blueprint, update SCPs
* protect all LZA resource on member accounts * allow only the use of global services in us-east-1 * enable quarantining new accounts
1 parent 6fa3644 commit 7e29162

13 files changed

+659
-59
lines changed

blueprints/foundational/config.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,18 @@ export const templates: Template[] = [
275275
fileName: 'organization-config.yaml',
276276
parameters: {
277277
organizationalUnits,
278+
denyGlobalRegionScpTargets: {
279+
organizationalUnits: organizationalUnits
280+
.filter((ou) => !ou.name.includes('/')) // pick only top-level OUs
281+
.filter((ou) => !ou.ignore) // ignore OUs that are not managed by the LZA
282+
.map((ou) => ou.name),
283+
},
284+
denyAllRegionsExceptEnabledRegionsScpTargets: {
285+
organizationalUnits: organizationalUnits
286+
.filter((ou) => !ou.name.includes('/')) // pick only top-level OUs
287+
.filter((ou) => !ou.ignore) // ignore OUs that are not managed by the LZA
288+
.map((ou) => ou.name),
289+
},
278290
},
279291
},
280292
{
@@ -290,6 +302,19 @@ export const templates: Template[] = [
290302
environments: Object.values(environments),
291303
},
292304
},
305+
{
306+
fileName: 'service-control-policies/deny-global-region.json',
307+
parameters: {
308+
globalRegion: GLOBAL_REGION,
309+
},
310+
},
311+
{
312+
fileName:
313+
'service-control-policies/deny-all-regions-except-enabled-regions.json',
314+
parameters: {
315+
enabledRegions: ENABLED_REGIONS,
316+
},
317+
},
293318
];
294319

295320
export const config: Config = {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Assume Control Tower Execution Role
2+
3+
On member accounts of the AWS organization there are some custom guardrails in place that prevent even users with `AdministratorAccess` from specific actions like e.g., deleting a CloudFormation stack with an `LzaCustomization-` prefix.
4+
Therefore, to perform certain operations, you may need to assume the **Control Tower Execution Role**.
5+
This is particularly useful during development or debugging of LZA Customization stacks.
6+
7+
## Requirements
8+
9+
- You can access the `Management` account with `AdministratorAccess`.
10+
- You have the **account ID** of the target account in which you want to assume the `AWSControlTowerExecution` role.
11+
12+
## Steps
13+
14+
1. Open <https://<<AWS_IDENTITY_STORE_ID>>.awsapps.com/start>.
15+
2. You should see a list of AWS accounts that you have access to.
16+
3. Note down the **account ID** of the target account where you want to assume the role.
17+
4. Log in to the `Management` account with an admin permission set.
18+
5. In the upper-right corner of the AWS Console, click on your username and then the arrow next to **Add session**.
19+
6. Enter the **Account ID** of the target account.
20+
7. Select the `AWSControlTowerExecution` role.
21+
8. (Optional) Enter a display name for the session.
22+
9. (Optional) Choose a display color to help distinguish this session.
23+
10. Click **Switch role**.
24+
11. The session will now be available in the session menu for quick access in the future.

blueprints/foundational/templates/organization-config.yaml.liquid

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,67 @@ organizationalUnits:
44
- name: <% organizationalUnit.name %>
55
{% if organizationalUnit.ignore %}ignore: true{% endif %}
66
{% endfor %}
7+
# Enabling the quarantine service control policies (SCPs)
8+
quarantineNewAccounts:
9+
enable: true
10+
scpPolicyName: Quarantine
711
serviceControlPolicies:
812
# Foundational hardening: organization hardening SCPs
9-
# Source: https://aws.amazon.com/solutions/guidance/establishing-an-initial-foundation-using-control-tower-on-aws
10-
- name: PreventLeavingOrganization
11-
description: Prevent member accounts from leaving the organization.
12-
policy: ./service-control-policies/prevent-leaving-organization.json
13+
# Sources:
14+
# - https://aws.amazon.com/solutions/guidance/establishing-an-initial-foundation-using-control-tower-on-aws
15+
# - https://docs.aws.amazon.com/controltower/latest/controlreference/strongly-recommended-controls.html#disallow-root-access-keys
16+
- name: OrganizationHardening
17+
description: >
18+
- Prevent member accounts from leaving the organization.
19+
- Prevents users from creating resource shares that allow sharing with IAM users and roles that aren't part of the organization.
20+
- Secures your AWS accounts by disallowing creation of access keys for the root user.
21+
policy: service-control-policies/organization-hardening.json
1322
type: customerManaged
1423
deploymentTargets:
1524
organizationalUnits:
1625
- Root
17-
- name: PreventExternalSharing
18-
description: Prevents users from creating resource shares that allow sharing with IAM users and roles that aren't part of the organization.
19-
policy: ./service-control-policies/prevent-external-sharing.json
26+
# Denies access to the global AWS region
27+
- name: DenyGlobalRegion
28+
description: Prevents the use of the global region except for global services.
29+
policy: service-control-policies/deny-global-region.json
30+
type: customerManaged
31+
deploymentTargets:
32+
organizationalUnits: <% denyGlobalRegionScpTargets.organizationalUnits | json %>
33+
# Denies access to not allowed regions
34+
- name: DenyAllRegionsExceptEnabledRegions
35+
description: Prevents the use of any regions that are not enabled in the LZA configuration.
36+
policy: service-control-policies/deny-all-regions-except-enabled-regions.json
37+
type: customerManaged
38+
deploymentTargets:
39+
organizationalUnits: <% denyAllRegionsExceptEnabledRegionsScpTargets.organizationalUnits | json %>
40+
# Best practices from the GovCloud Example (see: https://awslabs.github.io/landing-zone-accelerator-on-aws/v1.9.0/sample-configurations/govcloud-us/security-controls/)
41+
- name: LzaGuardrails1
42+
description: This protects LZA resources from being modified.
43+
policy: service-control-policies/lza-guardrails-1.json
2044
type: customerManaged
2145
deploymentTargets:
2246
organizationalUnits:
23-
# This should be set to Root, however:
24-
# Currently, IPAM resource share sets AllowExternalPrincipals to true,
25-
# and there is no way to deactivate it.
26-
# See: https://github.com/awslabs/landing-zone-accelerator-on-aws/issues/230
27-
- Sandbox
28-
- Security
29-
- Workloads
30-
# https://docs.aws.amazon.com/controltower/latest/controlreference/strongly-recommended-controls.html#disallow-root-access-keys
31-
- name: GrRestrictRootUserAccessKeys
32-
description: Secures your AWS accounts by disallowing creation of access keys for the root user.
33-
policy: ./service-control-policies/restrict-root-user-access-keys.json
47+
- Root
48+
- name: LzaGuardrails2
49+
description: This protects LZA resources from being modified and prevents the creation and use of roles managed by the LZA.
50+
policy: service-control-policies/lza-guardrails-2.json
3451
type: customerManaged
3552
deploymentTargets:
3653
organizationalUnits:
3754
- Root
55+
- name: CustomizationsGuardrails
56+
description: This protects Customizations resources from being modified and prevents the creation and use of roles managed by the Customizations.
57+
policy: service-control-policies/customizations-guardrails.json
58+
type: customerManaged
59+
deploymentTargets:
60+
organizationalUnits:
61+
- Root
62+
- name: Quarantine
63+
description: This SCP is used to prevent changes to new accounts until the Accelerator has been executed successfully. This policy will be applied upon account creation if enabled.
64+
policy: service-control-policies/quarantine.json
65+
type: customerManaged
66+
deploymentTargets:
67+
organizationalUnits: []
3868
taggingPolicies:
3969
- name: EnforceDefaultTags
4070
description: Enforce default tags organization wide.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Sid": "LambdaStatement",
6+
"Effect": "Deny",
7+
"Action": [
8+
"lambda:AddPermission",
9+
"lambda:CreateEventSourceMapping",
10+
"lambda:CreateFunction",
11+
"lambda:DeleteEventSourceMapping",
12+
"lambda:DeleteFunction",
13+
"lambda:DeleteFunctionConcurrency",
14+
"lambda:Invoke*",
15+
"lambda:PutFunctionConcurrency",
16+
"lambda:RemovePermission",
17+
"lambda:UpdateEventSourceMapping",
18+
"lambda:UpdateFunctionCode",
19+
"lambda:UpdateFunctionConfiguration"
20+
],
21+
"Resource": "arn:${PARTITION}:lambda:*:*:function:LzaCustomization-*",
22+
"Condition": {
23+
"ArnNotLike": {
24+
"aws:PrincipalARN": [
25+
"arn:${PARTITION}:iam::*:role/LzaCustomization-*",
26+
"arn:${PARTITION}:iam::*:role/${ACCELERATOR_PREFIX}-*",
27+
"arn:${PARTITION}:iam::*:role/${MANAGEMENT_ACCOUNT_ACCESS_ROLE}",
28+
"arn:${PARTITION}:iam::*:role/cdk-accel-*"
29+
]
30+
}
31+
}
32+
},
33+
{
34+
"Sid": "PreventCloudWatchLogsModification",
35+
"Effect": "Deny",
36+
"Action": [
37+
"logs:DisassociateKmsKey",
38+
"logs:DeleteLogGroup",
39+
"logs:DeleteRetentionPolicy",
40+
"logs:AssociateKmsKey",
41+
"logs:PutRetentionPolicy",
42+
"logs:CreateLogGroup"
43+
],
44+
"Resource": [
45+
"arn:${PARTITION}:logs:*:*:log-group:LzaCustomization-*",
46+
"arn:${PARTITION}:logs:*:*:log-group:/aws/lambda/LzaCustomization-*"
47+
],
48+
"Condition": {
49+
"ArnNotLike": {
50+
"aws:PrincipalARN": [
51+
"arn:${PARTITION}:iam::*:role/LzaCustomization-*",
52+
"arn:${PARTITION}:iam::*:role/${ACCELERATOR_PREFIX}-*",
53+
"arn:${PARTITION}:iam::*:role/${MANAGEMENT_ACCOUNT_ACCESS_ROLE}",
54+
"arn:${PARTITION}:iam::*:role/cdk-accel-*"
55+
]
56+
}
57+
}
58+
},
59+
{
60+
"Sid": "PreventCloudWatchLogStreamModification",
61+
"Effect": "Deny",
62+
"Action": ["logs:DeleteLogStream"],
63+
"Resource": [
64+
"arn:${PARTITION}:logs:*:*:log-group:LzaCustomization-*:log-stream:*",
65+
"arn:${PARTITION}:logs:*:*:log-group:/aws/lambda/LzaCustomization-*:log-stream:*"
66+
],
67+
"Condition": {
68+
"ArnNotLike": {
69+
"aws:PrincipalARN": [
70+
"arn:${PARTITION}:iam::*:role/LzaCustomization-*",
71+
"arn:${PARTITION}:iam::*:role/${ACCELERATOR_PREFIX}-*",
72+
"arn:${PARTITION}:iam::*:role/${MANAGEMENT_ACCOUNT_ACCESS_ROLE}",
73+
"arn:${PARTITION}:iam::*:role/cdk-accel-*"
74+
]
75+
}
76+
}
77+
},
78+
{
79+
"Sid": "IamRolesStatement",
80+
"Effect": "Deny",
81+
"Action": ["iam:*"],
82+
"Resource": [
83+
"arn:${PARTITION}:iam::*:role/LzaCustomization-*"
84+
],
85+
"Condition": {
86+
"ArnNotLike": {
87+
"aws:PrincipalARN": [
88+
"arn:${PARTITION}:iam::*:role/LzaCustomization-*",
89+
"arn:${PARTITION}:iam::*:role/${ACCELERATOR_PREFIX}-*",
90+
"arn:${PARTITION}:iam::*:role/cdk-accel-*",
91+
"arn:${PARTITION}:iam::*:role/${MANAGEMENT_ACCOUNT_ACCESS_ROLE}",
92+
"arn:${PARTITION}:iam::*:role/AWSServiceRoleForConfig"
93+
]
94+
}
95+
}
96+
},
97+
{
98+
"Sid": "CloudFormationStatement",
99+
"Effect": "Deny",
100+
"Action": ["cloudformation:Delete*"],
101+
"Resource": "arn:${PARTITION}:cloudformation:*:*:stack/LzaCustomization-*",
102+
"Condition": {
103+
"ArnNotLike": {
104+
"aws:PrincipalARN": [
105+
"arn:${PARTITION}:iam::*:role/LzaCustomization-*",
106+
"arn:${PARTITION}:iam::*:role/${ACCELERATOR_PREFIX}-*",
107+
"arn:${PARTITION}:iam::*:role/${MANAGEMENT_ACCOUNT_ACCESS_ROLE}",
108+
"arn:${PARTITION}:iam::*:role/cdk-accel-*"
109+
]
110+
}
111+
}
112+
}
113+
]
114+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Condition": {
6+
"StringNotEquals": {
7+
"aws:RequestedRegion": <% enabledRegions | json %>
8+
},
9+
"ArnNotLike": {
10+
"aws:PrincipalARN": [
11+
"arn:${PARTITION}:iam::*:role/${MANAGEMENT_ACCOUNT_ACCESS_ROLE}"
12+
]
13+
}
14+
},
15+
"Resource": "*",
16+
"Effect": "Deny",
17+
"Action": "*"
18+
}
19+
]
20+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Condition": {
6+
"StringEquals": {
7+
"aws:RequestedRegion": [<% globalRegion | json %>]
8+
},
9+
"ArnNotLike": {
10+
"aws:PrincipalARN": [
11+
"arn:${PARTITION}:iam::*:role/LzaCustomization-*",
12+
"arn:${PARTITION}:iam::*:role/${ACCELERATOR_PREFIX}-*",
13+
"arn:${PARTITION}:iam::*:role/${MANAGEMENT_ACCOUNT_ACCESS_ROLE}",
14+
"arn:${PARTITION}:iam::*:role/cdk-accel-*"
15+
]
16+
}
17+
},
18+
"Resource": "*",
19+
"Effect": "Deny",
20+
"NotAction": [
21+
"a4b:*",
22+
"access-analyzer:*",
23+
"account:*",
24+
"acm:*",
25+
"activate:*",
26+
"artifact:*",
27+
"aws-marketplace-management:*",
28+
"aws-marketplace:*",
29+
"aws-portal:*",
30+
"billing:*",
31+
"billingconductor:*",
32+
"budgets:*",
33+
"ce:*",
34+
"chatbot:*",
35+
"chime:*",
36+
"cloudformation:*",
37+
"cloudfront:*",
38+
"cloudtrail:LookupEvents",
39+
"compute-optimizer:*",
40+
"config:*",
41+
"consoleapp:*",
42+
"consolidatedbilling:*",
43+
"cur:*",
44+
"datapipeline:GetAccountLimits",
45+
"devicefarm:*",
46+
"directconnect:*",
47+
"ec2:DescribeRegions",
48+
"ec2:DescribeTransitGateways",
49+
"ec2:DescribeVpnGateways",
50+
"ecr-public:*",
51+
"fms:*",
52+
"freetier:*",
53+
"globalaccelerator:*",
54+
"health:*",
55+
"iam:*",
56+
"importexport:*",
57+
"invoicing:*",
58+
"iq:*",
59+
"kms:*",
60+
"license-manager:ListReceivedLicenses",
61+
"lightsail:Get*",
62+
"mobileanalytics:*",
63+
"networkmanager:*",
64+
"notifications-contacts:*",
65+
"notifications:*",
66+
"organizations:*",
67+
"payments:*",
68+
"pricing:*",
69+
"quicksight:DescribeAccountSubscription",
70+
"resource-explorer-2:*",
71+
"route53-recovery-cluster:*",
72+
"route53-recovery-control-config:*",
73+
"route53-recovery-readiness:*",
74+
"route53:*",
75+
"route53domains:*",
76+
"s3:CreateMultiRegionAccessPoint",
77+
"s3:DeleteMultiRegionAccessPoint",
78+
"s3:DescribeMultiRegionAccessPointOperation",
79+
"s3:GetAccountPublicAccessBlock",
80+
"s3:GetBucketLocation",
81+
"s3:GetBucketPolicyStatus",
82+
"s3:GetBucketPublicAccessBlock",
83+
"s3:GetMultiRegionAccessPoint",
84+
"s3:GetMultiRegionAccessPointPolicy",
85+
"s3:GetMultiRegionAccessPointPolicyStatus",
86+
"s3:GetStorageLensConfiguration",
87+
"s3:GetStorageLensDashboard",
88+
"s3:ListAllMyBuckets",
89+
"s3:ListMultiRegionAccessPoints",
90+
"s3:ListStorageLensConfigurations",
91+
"s3:PutAccountPublicAccessBlock",
92+
"s3:PutMultiRegionAccessPointPolicy",
93+
"savingsplans:*",
94+
"shield:*",
95+
"sso:*",
96+
"sts:*",
97+
"support:*",
98+
"supportapp:*",
99+
"supportplans:*",
100+
"sustainability:*",
101+
"tag:GetResources",
102+
"tax:*",
103+
"trustedadvisor:*",
104+
"vendor-insights:ListEntitledSecurityProfiles",
105+
"waf-regional:*",
106+
"waf:*",
107+
"wafv2:*"
108+
]
109+
}
110+
]
111+
}

0 commit comments

Comments
 (0)