-
Notifications
You must be signed in to change notification settings - Fork 36
/
aws-control-tower-securityhub-enabler.template
291 lines (279 loc) · 9.74 KB
/
aws-control-tower-securityhub-enabler.template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
AWSTemplateFormatVersion: 2010-09-09
Description: Creates an SNS topic and Lambda function to enable SecurityHub in the Security account.
Parameters:
SecurityAccountId:
Type: String
Description: Which account will be the SecurityHub Admin account? Enter the AWS account ID. (This is generally the AWS Control Tower Audit account)
AllowedPattern: '^[0-9]{12}$'
ConstraintDescription: The Security Account ID must be a 12 character string.
MinLength: 12
MaxLength: 12
OrganizationId:
Type: String
Description: AWS Organizations ID for the Control Tower. This is used to restrict permissions to least privilege.
AllowedPattern: '^[o][\-][a-z0-9]{10}$'
ConstraintDescription: The Org Id must be a 12 character string starting with o- and followed by 10 lower case alphanumeric characters
MinLength: 12
MaxLength: 12
RegionFilter:
Type: String
Description: Should Security Hub be enabled for all Security Hub supported regions, or only Control Tower supported regions
Default: ControlTower
AllowedValues:
- SecurityHub
- ControlTower
OUFilter:
Type: String
Description: Should Security Hub be enabled for all accounts, or only accounts Control Tower Managed OUs?
Default: All
AllowedValues:
- All
- ControlTower
S3SourceBucket:
Type: String
Description: S3 bucket containing SecurityHubEnabler Lambda deployment package
Default: ""
S3SourceKey:
Type: String
Description: S3 object key for SecurityHubEnabler Lambda deployment package
Default: securityhub_enabler.zip
ComplianceFrequency:
Type: Number
Description: Frequency (in days between 1 and 30, default is 7) to check organizational compliance
Default: 7
ConstraintDescription: Compliance Frequency must be a number between 1 and 30, inclusive.
MinValue: 1
MaxValue: 30
RoleToAssume:
Type: String
Description: IAM role to be assumed in child accounts to enable SecurityHub. The default is AWSControlTowerExecution for a Control Tower environment.
Default: 'AWSControlTowerExecution'
AWSStandard:
Type: String
Description: Should Security Hub enable the AWS Foundational Security Best Practices v1.0.0 Security Standard?
Default: "Yes"
AllowedValues:
- "Yes"
- "No"
CIS120Standard:
Type: String
Description: Should Security Hub enable the CIS AWS Foundations Benchmark v1.2.0 Security Standard?
Default: "Yes"
AllowedValues:
- "Yes"
- "No"
CIS140Standard:
Type: String
Description: Should Security Hub enable the CIS AWS Foundations Benchmark v1.4.0 Security Standard?
Default: "No"
AllowedValues:
- "Yes"
- "No"
PCIStandard:
Type: String
Description: Should Security Hub enable the PCI DSS v3.2.1 Security Standard?
Default: "No"
AllowedValues:
- "Yes"
- "No"
NISTStandard:
Type: String
Description: Should Security Hub enable the NIST SP 800-53 Rev5 Security Standard?
Default: "No"
AllowedValues:
- "Yes"
- "No"
Conditions:
ComplianceFrequencySingleDay: !Equals
- !Ref 'ComplianceFrequency'
- 1
Resources:
SecurityHubEnablerRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: SecurityHubEnablerPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- organizations:ListAccounts
- organizations:DescribeAccount
- organizations:ListPoliciesForTarget
- organizations:ListParents
Resource: '*'
Condition:
StringEquals:
"aws:PrincipalOrgId": !Ref OrganizationId
- Effect: Allow
Action:
- sts:AssumeRole
Resource: !Sub 'arn:aws:iam::*:role/${RoleToAssume}'
Condition:
StringEquals:
"aws:PrincipalOrgId": !Ref OrganizationId
- Effect: Allow
Action:
- sns:Publish
Resource: !Ref SecurityHubEnablerTopic
- Effect: Allow
Action:
- 'logs:CreateLogGroup'
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
Resource:
- !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*'
- Effect: Allow
Action:
- 'sts:AssumeRole'
Resource: !Sub 'arn:aws:iam::*:role/${RoleToAssume}'
- Effect: Allow
Action:
- 'CloudFormation:ListStackInstances'
Resource: !Sub 'arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stackset/AWSControlTowerBP-BASELINE-CLOUDWATCH:*'
- Effect: Allow
Action:
- 'iam:CreateServiceLinkedRole'
- 'ec2:describeRegions'
- 'securityhub:AcceptInvitation'
- 'securityhub:AcceptAdministratorInvitation'
- 'securityhub:BatchEnableStandards'
- 'securityhub:BatchDisableStandards'
- 'securityhub:CreateMembers'
- 'securityhub:DisassociateFromAdministratorAccount'
- 'securityhub:DisassociateMembers'
- 'securityhub:DisableSecurityHub'
- 'securityhub:DeleteMembers'
- 'securityhub:EnableSecurityHub'
- 'securityhub:GetEnabledStandards'
- 'securityhub:GetFindings'
- 'securityhub:GetMasterAccount'
- 'securityhub:InviteMembers'
- 'securityhub:ListInvitations'
- 'securityhub:ListMembers'
Resource: '*'
Metadata:
cfn_nag:
rules_to_suppress:
- id: W11
reason: "Organizations doesn't have arns, so we have to use an asterisk in the policy"
SecurityHubEnablerLambda:
Type: "AWS::Lambda::Function"
DependsOn:
- SecurityHubEnablerRole
Properties:
Handler: "securityhub_enabler.lambda_handler"
Role: !Sub "arn:aws:iam::${AWS::AccountId}:role/${SecurityHubEnablerRole}"
Code:
S3Bucket: !Ref S3SourceBucket
S3Key: !Ref S3SourceKey
Runtime: "python3.10"
MemorySize: 256
Timeout: 900
# ###################################################################
ReservedConcurrentExecutions: 2
# ###################################################################
Environment:
Variables:
ou_filter: !Ref OUFilter
region_filter: !Ref RegionFilter
assume_role: !Sub ${RoleToAssume}
ct_admin_account: !Sub ${AWS::AccountId}
sh_admin_account: !Sub ${SecurityAccountId}
topic: !Ref SecurityHubEnablerTopic
aws_standard: !Ref AWSStandard
cis_standard: !Ref CIS120Standard
cis_140_standard: !Ref CIS140Standard
nist_standard: !Ref NISTStandard
pci_standard: !Ref PCIStandard
log_level: "ERROR"
SecurityHubEnablerTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: SecurityHub_Enabler
TopicName: SecurityHubEnablerTopic
Metadata:
cfn_nag:
rules_to_suppress:
- id: W47
reason: "Not sensitive data, doesn't need encryption with kms"
SecurityHubEnablerTopicLambdaPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt SecurityHubEnablerLambda.Arn
Principal: sns.amazonaws.com
SourceArn: !Ref SecurityHubEnablerTopic
SecurityHubEnablerSubscription:
Type: AWS::SNS::Subscription
Properties:
Endpoint: !GetAtt SecurityHubEnablerLambda.Arn
Protocol: lambda
TopicArn: !Ref SecurityHubEnablerTopic
ScheduledRule:
Type: AWS::Events::Rule
Properties:
Description: "SecurityHubScheduledComplianceTrigger"
ScheduleExpression: !If
- ComplianceFrequencySingleDay
- !Sub "rate(${ComplianceFrequency} day)"
- !Sub "rate(${ComplianceFrequency} days)"
State: "ENABLED"
Targets:
-
Arn: !GetAtt SecurityHubEnablerLambda.Arn
Id: "DailyInvite"
LifeCycleRule:
Type: AWS::Events::Rule
Properties:
Description: "SecurityHubLifeCycleTrigger"
EventPattern:
source:
- "aws.controltower"
detail-type:
- "AWS Service Event via CloudTrail"
detail:
eventName:
- "CreateManagedAccount"
State: "ENABLED"
Targets:
-
Arn: !GetAtt SecurityHubEnablerLambda.Arn
Id: "DailyInvite"
PermissionForSchedEventToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt SecurityHubEnablerLambda.Arn
Action: "lambda:InvokeFunction"
Principal: "events.amazonaws.com"
SourceArn: !GetAtt ScheduledRule.Arn
PermissionForCTEventToInvokeLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt SecurityHubEnablerLambda.Arn
Action: "lambda:InvokeFunction"
Principal: "events.amazonaws.com"
SourceArn: !GetAtt LifeCycleRule.Arn
FirstRun:
Type: Custom::SecurityHubEnablerLambdaFirstRun
DependsOn:
- SecurityHubEnablerTopic
- SecurityHubEnablerRole
- SecurityHubEnablerTopicLambdaPermission
- SecurityHubEnablerSubscription
Properties:
ServiceToken: !GetAtt SecurityHubEnablerLambda.Arn