Skip to content

Commit c409acb

Browse files
authored
Merge pull request #44 from aws-solutions/release/v1.3.2
Bugfix for CIS 3.1-3.14
2 parents f1722c0 + 8869909 commit c409acb

File tree

11 files changed

+211
-82
lines changed

11 files changed

+211
-82
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ 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+
## [1.3.2] - 2021-11-09
8+
- Corrected CIS 3.1 filter pattern
9+
- Corrected SNS Access Policy for SO0111-SHARR-LocalAlarmNotification
10+
- Corrected KMS CMK Access Policy used by the SNS topic to allow CloudWatch use
11+
- EvaluationPeriods for CIS 3.x alarms changed from 240 (20 hours) to 12 (1 hour)
12+
713
## [1.3.1] - 2021-09-10
814

915
### Changed

deployment/build-s3-dist.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# This controls the CDK and AWS Solutions Constructs version. Solutions
2121
# Constructs versions map 1:1 to CDK versions. When setting this value,
2222
# choose the latest AWS Solutions Constructs version.
23-
required_cdk_version=1.117.0
23+
required_cdk_version=1.132.0
2424

2525
# Functions to reduce repetitive code
2626
# do_cmd will exit if the command has a non-zero return code.

source/package.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@
1919
},
2020
"devDependencies": {
2121
"@aws-cdk/assert": "~###CDK###",
22-
"@types/node": "16.7.1",
22+
"@types/node": "16.11.7",
2323
"aws-cdk": "~###CDK###",
2424
"ts-node": "^10.2.1",
25-
"typescript": "^4.3.5"
26-
},
27-
"dependencies": {
25+
"typescript": "^4.3.5",
2826
"@aws-cdk/aws-events": "~###CDK###",
2927
"@aws-cdk/aws-iam": "~###CDK###",
3028
"@aws-cdk/aws-kms": "~###CDK###",

source/playbooks/CIS120/ssmdocs/scripts/cis_get_input_values.py

Lines changed: 58 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -16,135 +16,134 @@
1616

1717
CIS_mappings = {
1818
"3.1": {
19-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_1",
20-
"filter_pattern": '{$.errorCode = "AccessDenied" || $.errorCode = "UnauthorizedOperation"}',
21-
"metric_name": "SHARR_CIS_1_2_Finding_3_1_UnauthorizedAPICalls",
19+
"filter_name": "UnauthorizedAPICalls",
20+
"filter_pattern": '{($.errorCode="*UnauthorizedOperation") || ($.errorCode="AccessDenied*")}',
21+
"metric_name": "UnauthorizedAPICalls",
2222
"metric_value": 1,
23-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_1_UnauthorizedAPICalls",
24-
"alarm_desc": "Alarm for CIS finding 3.1-UnauthorizedAPICalls",
23+
"alarm_name": "UnauthorizedAPICalls",
24+
"alarm_desc": "Alarm for UnauthorizedAPICalls > 0",
2525
"alarm_threshold": 1
2626
},
2727
"3.2": {
28-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_2_ConsoleSigninWithoutMFA",
28+
"filter_name": "ConsoleSigninWithoutMFA",
2929
"filter_pattern": '{($.eventName="ConsoleLogin") && ($.additionalEventData.MFAUsed !="Yes")}',
30-
"metric_name": "SHARR_CIS_1_2_Finding_3_2_ConsoleSigninWithoutMFA",
30+
"metric_name": "ConsoleSigninWithoutMFA",
3131
"metric_value": 1,
32-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_2_ConsoleSigninWithoutMFA",
33-
"alarm_desc": "Alarm for CIS finding 3.2 ConsoleSigninWithoutMFA",
32+
"alarm_name": "ConsoleSigninWithoutMFA",
33+
"alarm_desc": "Alarm for ConsoleSigninWithoutMFA > 0",
3434
"alarm_threshold": 1
3535
},
3636
"3.3": {
37-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_3_RootAccountUsage",
37+
"filter_name": "RootAccountUsage",
3838
"filter_pattern": '{$.userIdentity.type="Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType !="AwsServiceEvent"}',
39-
"metric_name": "SHARR_CIS_1_2_Finding_3_3_RootAccountUsage",
39+
"metric_name": "RootAccountUsage",
4040
"metric_value": 1,
41-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_3_RootAccountUsage",
42-
"alarm_desc": "Alarm for CIS finding 3.3 RootAccountUsage",
41+
"alarm_name": "RootAccountUsage",
42+
"alarm_desc": "Alarm for RootAccountUsage > 0",
4343
"alarm_threshold": 1
44-
4544
},
4645
"3.4": {
47-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_4_IAMPolicyChanges",
46+
"filter_name": "IAMPolicyChanges",
4847
"filter_pattern": '{($.eventName=DeleteGroupPolicy) || ($.eventName=DeleteRolePolicy) || ($.eventName=DeleteUserPolicy) || ($.eventName=PutGroupPolicy) || ($.eventName=PutRolePolicy) || ($.eventName=PutUserPolicy) || ($.eventName=CreatePolicy) || ($.eventName=DeletePolicy) || ($.eventName=CreatePolicyVersion) || ($.eventName=DeletePolicyVersion) || ($.eventName=AttachRolePolicy) || ($.eventName=DetachRolePolicy) || ($.eventName=AttachUserPolicy) || ($.eventName=DetachUserPolicy) || ($.eventName=AttachGroupPolicy) || ($.eventName=DetachGroupPolicy)}',
49-
"metric_name": "SHARR_CIS_1_2_Finding_3_4_IAMPolicyChanges",
48+
"metric_name": "IAMPolicyChanges",
5049
"metric_value": 1,
51-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_4_IAMPolicyChanges",
52-
"alarm_desc": "Alarm for CIS finding 3.4 IAMPolicyChanges",
50+
"alarm_name": "IAMPolicyChanges",
51+
"alarm_desc": "Alarm for IAMPolicyChanges > 0",
5352
"alarm_threshold": 1
5453
},
5554
"3.5": {
56-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_5_CloudTrailChanges",
55+
"filter_name": "CloudTrailChanges",
5756
"filter_pattern": '{($.eventName=CreateTrail) || ($.eventName=UpdateTrail) || ($.eventName=DeleteTrail) || ($.eventName=StartLogging) || ($.eventName=StopLogging)}',
58-
"metric_name": "SHARR_CIS_1_2_Finding_3_5_CloudTrailChanges",
57+
"metric_name": "CloudTrailChanges",
5958
"metric_value": 1,
60-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_5_CloudTrailChanges",
61-
"alarm_desc": "Alarm for CIS finding 3.5 CloudTrailChanges",
59+
"alarm_name": "CloudTrailChanges",
60+
"alarm_desc": "Alarm for CloudTrailChanges > 0",
6261
"alarm_threshold": 1
6362
},
6463
"3.6": {
65-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_6_ConsoleAuthenticationFailure",
64+
"filter_name": "ConsoleAuthenticationFailure",
6665
"filter_pattern": '{($.eventName=ConsoleLogin) && ($.errorMessage="Failed authentication")}',
67-
"metric_name": "SHARR_CIS_1_2_Finding_3_6_ConsoleAuthenticationFailure",
66+
"metric_name": "ConsoleAuthenticationFailure",
6867
"metric_value": 1,
69-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_6_ConsoleAuthenticationFailure",
70-
"alarm_desc": "Alarm for CIS finding 3.6 ConsoleAuthenticationFailure",
68+
"alarm_name": "ConsoleAuthenticationFailure",
69+
"alarm_desc": "Alarm for ConsoleAuthenticationFailure > 0",
7170
"alarm_threshold": 1
7271
},
7372
"3.7": {
74-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_7_DisableOrDeleteCMK",
73+
"filter_name": "DisableOrDeleteCMK",
7574
"filter_pattern": '{($.eventSource=kms.amazonaws.com) && (($.eventName=DisableKey) || ($.eventName=ScheduleKeyDeletion))}',
76-
"metric_name": "SHARR_CIS_1_2_Finding_3_7_DisableOrDeleteCMK",
75+
"metric_name": "DisableOrDeleteCMK",
7776
"metric_value": 1,
78-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_7_DisableOrDeleteCMK",
79-
"alarm_desc": "Alarm for CIS finding 3.7 DisableOrDeleteCMK",
77+
"alarm_name": "DisableOrDeleteCMK",
78+
"alarm_desc": "Alarm for DisableOrDeleteCMK > 0",
8079
"alarm_threshold": 1
8180
},
8281
"3.8": {
83-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_8_S3BucketPolicyChanges",
82+
"filter_name": "S3BucketPolicyChanges",
8483
"filter_pattern": '{($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}',
85-
"metric_name": "SHARR_CIS_1_2_Finding_3_8_S3BucketPolicyChanges",
84+
"metric_name": "S3BucketPolicyChanges",
8685
"metric_value": 1,
87-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_8_S3BucketPolicyChanges",
88-
"alarm_desc": "Alarm for CIS finding 3.8 S3BucketPolicyChanges",
86+
"alarm_name": "S3BucketPolicyChanges",
87+
"alarm_desc": "Alarm for S3BucketPolicyChanges > 0",
8988
"alarm_threshold": 1
9089
},
9190
"3.9": {
92-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_9_AWSConfigChanges",
91+
"filter_name": "AWSConfigChanges",
9392
"filter_pattern": '{($.eventSource=config.amazonaws.com) && (($.eventName=StopConfigurationRecorder) || ($.eventName=DeleteDeliveryChannel) || ($.eventName=PutDeliveryChannel) || ($.eventName=PutConfigurationRecorder))}',
94-
"metric_name": "SHARR_CIS_1_2_Finding_3_9_AWSConfigChanges",
93+
"metric_name": "AWSConfigChanges",
9594
"metric_value": 1,
96-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_9_AWSConfigChanges",
97-
"alarm_desc": "Alarm for CIS finding 3.9 AWSConfigChanges",
95+
"alarm_name": "AWSConfigChanges",
96+
"alarm_desc": "Alarm for AWSConfigChanges > 0",
9897
"alarm_threshold": 1
9998
},
10099
"3.10": {
101-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_10_SecurityGroupChanges",
100+
"filter_name": "SecurityGroupChanges",
102101
"filter_pattern": '{($.eventName=AuthorizeSecurityGroupIngress) || ($.eventName=AuthorizeSecurityGroupEgress) || ($.eventName=RevokeSecurityGroupIngress) || ($.eventName=RevokeSecurityGroupEgress) || ($.eventName=CreateSecurityGroup) || ($.eventName=DeleteSecurityGroup)}',
103-
"metric_name": "SHARR_CIS_1_2_Finding_3_10_SecurityGroupChanges",
102+
"metric_name": "SecurityGroupChanges",
104103
"metric_value": 1,
105-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_10_SecurityGroupChanges",
106-
"alarm_desc": "Alarm for CIS finding 3.10 SecurityGroupChanges",
104+
"alarm_name": "SecurityGroupChanges",
105+
"alarm_desc": "Alarm for SecurityGroupChanges > 0",
107106
"alarm_threshold": 1
108107
},
109108
"3.11": {
110-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_11_NetworkACLChanges",
109+
"filter_name": "NetworkACLChanges",
111110
"filter_pattern": '{($.eventName=CreateNetworkAcl) || ($.eventName=CreateNetworkAclEntry) || ($.eventName=DeleteNetworkAcl) || ($.eventName=DeleteNetworkAclEntry) || ($.eventName=ReplaceNetworkAclEntry) || ($.eventName=ReplaceNetworkAclAssociation)}',
112-
"metric_name": "SHARR_CIS_1_2_Finding_3_11_NetworkACLChanges",
111+
"metric_name": "NetworkACLChanges",
113112
"metric_value": 1,
114-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_11_NetworkACLChanges",
115-
"alarm_desc": "Alarm for CIS finding 3.11 NetworkACLChanges",
113+
"alarm_name": "NetworkACLChanges",
114+
"alarm_desc": "Alarm for NetworkACLChanges > 0",
116115
"alarm_threshold": 1
117116
},
118117
"3.12": {
119-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_12_NetworkGatewayChanges",
118+
"filter_name": "NetworkGatewayChanges",
120119
"filter_pattern": '{($.eventName=CreateCustomerGateway) || ($.eventName=DeleteCustomerGateway) || ($.eventName=AttachInternetGateway) || ($.eventName=CreateInternetGateway) || ($.eventName=DeleteInternetGateway) || ($.eventName=DetachInternetGateway)}',
121-
"metric_name": "SHARR_CIS_1_2_Finding_3_12_NetworkGatewayChanges",
120+
"metric_name": "NetworkGatewayChanges",
122121
"metric_value": 1,
123-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_12_NetworkGatewayChanges",
124-
"alarm_desc": "Alarm for CIS finding 3.12 NetworkGatewayChanges",
122+
"alarm_name": "NetworkGatewayChanges",
123+
"alarm_desc": "Alarm for NetworkGatewayChanges > 0",
125124
"alarm_threshold": 1
126125
},
127126
"3.13": {
128-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_13_RouteTableChanges",
127+
"filter_name": "RouteTableChanges",
129128
"filter_pattern": '{($.eventName=CreateRoute) || ($.eventName=CreateRouteTable) || ($.eventName=ReplaceRoute) || ($.eventName=ReplaceRouteTableAssociation) || ($.eventName=DeleteRouteTable) || ($.eventName=DeleteRoute) || ($.eventName=DisassociateRouteTable)}',
130-
"metric_name": "SHARR_CIS_1_2_Finding_3_13_RouteTableChanges",
129+
"metric_name": "RouteTableChanges",
131130
"metric_value": 1,
132-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_13_RouteTableChanges",
133-
"alarm_desc": "Alarm for CIS finding 3.13 RouteTableChanges",
131+
"alarm_name": "RouteTableChanges",
132+
"alarm_desc": "Alarm for RouteTableChanges > 0",
134133
"alarm_threshold": 1
135134
},
136135
"3.14": {
137-
"filter_name": "SHARR_Filter_CIS_1_2_Finding_3_14_VPCChanges",
136+
"filter_name": "VPCChanges",
138137
"filter_pattern": '{($.eventName=CreateVpc) || ($.eventName=DeleteVpc) || ($.eventName=ModifyVpcAttribute) || ($.eventName=AcceptVpcPeeringConnection) || ($.eventName=CreateVpcPeeringConnection) || ($.eventName=DeleteVpcPeeringConnection) || ($.eventName=RejectVpcPeeringConnection) || ($.eventName=AttachClassicLinkVpc) || ($.eventName=DetachClassicLinkVpc) || ($.eventName=DisableVpcClassicLink) || ($.eventName=EnableVpcClassicLink)}',
139-
"metric_name": "SHARR_CIS_1_2_Finding_3_14_VPCChanges",
138+
"metric_name": "VPCChanges",
140139
"metric_value": 1,
141-
"alarm_name": "SHARR_Alarm_CIS_1_2_Finding_3_14_VPCChanges",
142-
"alarm_desc": "Alarm for CIS finding 3.14 VPCChanges",
140+
"alarm_name": "VPCChanges",
141+
"alarm_desc": "Alarm for VPCChanges > 0",
143142
"alarm_threshold": 1
144143
}
145144
}
146145

147146

148147
def verify(event, context):
149148

150-
return CIS_mappings.get(event['ControlId'], None)
149+
return CIS_mappings.get(event['ControlId'], None)

source/remediation_runbooks/scripts/CreateLogMetricFilterAndAlarm.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ def put_metric_filter(cw_log_group, filter_name, filter_pattern, metric_name, me
6363
{
6464
'metricName': metric_name,
6565
'metricNamespace': metric_namespace,
66-
'metricValue': str(metric_value)
67-
},
66+
'metricValue': str(metric_value),
67+
'unit': 'Count'
68+
}
6869
]
6970
)
7071
except Exception as e:
@@ -99,10 +100,12 @@ def put_metric_alarm(alarm_name, alarm_desc, alarm_threshold, metric_name, metri
99100
Namespace=metric_namespace,
100101
Statistic='Sum',
101102
Period=300,
102-
Unit='Seconds',
103-
EvaluationPeriods=240,
103+
Unit='Count',
104+
EvaluationPeriods=12,
105+
DatapointsToAlarm=1,
104106
Threshold=alarm_threshold,
105-
ComparisonOperator='GreaterThanOrEqualToThreshold'
107+
ComparisonOperator='GreaterThanOrEqualToThreshold',
108+
TreatMissingData='notBreaching'
106109
)
107110
except Exception as e:
108111
exit("Exception occurred while putting metric alarm: " + str(e))
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/python
2+
###############################################################################
3+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. #
4+
# #
5+
# Licensed under the Apache License Version 2.0 (the "License"). You may not #
6+
# use this file except in compliance with the License. A copy of the License #
7+
# is located at #
8+
# #
9+
# http://www.apache.org/licenses/LICENSE-2.0 #
10+
# #
11+
# or in the "license" file accompanying this file. This file is distributed #
12+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express #
13+
# or implied. See the License for the specific language governing permis- #
14+
# sions and limitations under the License. #
15+
###############################################################################
16+
17+
import json
18+
import boto3
19+
from botocore.config import Config
20+
from botocore.exceptions import ClientError
21+
22+
boto_config = Config(
23+
retries ={
24+
'mode': 'standard'
25+
}
26+
)
27+
28+
def connect_to_sns():
29+
return boto3.client('sns', config=boto_config)
30+
31+
def connect_to_ssm():
32+
return boto3.client('ssm', config=boto_config)
33+
34+
def create_encrypted_topic(event, context):
35+
36+
kms_key_arn = event['kms_key_arn']
37+
new_topic = False
38+
topic_arn = ''
39+
topic_name = event['topic_name']
40+
41+
try:
42+
sns = connect_to_sns()
43+
topic_arn = sns.create_topic(
44+
Name=topic_name,
45+
Attributes={
46+
'KmsMasterKeyId': kms_key_arn.split('key/')[1]
47+
}
48+
)['TopicArn']
49+
new_topic = True
50+
51+
except ClientError as client_exception:
52+
exception_type = client_exception.response['Error']['Code']
53+
if exception_type == 'InvalidParameter':
54+
print(f'Topic {topic_name} already exists. This remediation may have been run before.')
55+
print('Ignoring exception - remediation continues.')
56+
topic_arn = sns.create_topic(
57+
Name=topic_name
58+
)['TopicArn']
59+
else:
60+
exit(f'ERROR: Unhandled client exception: {client_exception}')
61+
62+
except Exception as e:
63+
exit(f'ERROR: could not create SNS Topic {topic_name}: {str(e)}')
64+
65+
if new_topic:
66+
try:
67+
ssm = connect_to_ssm()
68+
ssm.put_parameter(
69+
Name='/Solutions/SO0111/SNS_Topic_CIS3.x',
70+
Description='SNS Topic for AWS Config updates',
71+
Type='String',
72+
Overwrite=True,
73+
Value=topic_arn
74+
)
75+
except Exception as e:
76+
exit(f'ERROR: could not create SNS Topic {topic_name}: {str(e)}')
77+
78+
create_topic_policy(topic_arn)
79+
80+
return {"topic_arn": topic_arn}
81+
82+
def create_topic_policy(topic_arn):
83+
sns = connect_to_sns()
84+
try:
85+
topic_policy = {
86+
"Id": "Policy_ID",
87+
"Statement": [
88+
{
89+
"Sid": "AWSConfigSNSPolicy",
90+
"Effect": "Allow",
91+
"Principal": {
92+
"Service": "cloudwatch.amazonaws.com"
93+
},
94+
"Action": "SNS:Publish",
95+
"Resource": topic_arn,
96+
}]
97+
}
98+
99+
sns.set_topic_attributes(
100+
TopicArn=topic_arn,
101+
AttributeName='Policy',
102+
AttributeValue=json.dumps(topic_policy)
103+
)
104+
except Exception as e:
105+
exit(f'ERROR: Failed to SetTopicAttributes for {topic_arn}: {str(e)}')

source/remediation_runbooks/scripts/test/test_createlogmetricfilterandalarm.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,9 @@ def test_put_metric_filter_pass(mocker):
8585
{
8686
'metricName': event['MetricName'],
8787
'metricNamespace':event['MetricNamespace'],
88-
'metricValue': str (event['MetricValue'])
89-
},
88+
'metricValue': str (event['MetricValue']),
89+
'unit': 'Count'
90+
}
9091
]
9192
}
9293
)
@@ -179,10 +180,12 @@ def test_put_metric_alarm(mocker):
179180
'Namespace': event['MetricNamespace'],
180181
'Statistic': 'Sum',
181182
'Period': 300,
182-
'Unit': 'Seconds',
183-
'EvaluationPeriods': 240,
183+
'Unit': 'Count',
184+
'EvaluationPeriods': 12,
185+
'DatapointsToAlarm': 1,
184186
'Threshold': (event['AlarmThreshold']),
185-
'ComparisonOperator': 'GreaterThanOrEqualToThreshold'
187+
'ComparisonOperator': 'GreaterThanOrEqualToThreshold',
188+
'TreatMissingData': 'notBreaching'
186189
}
187190
)
188191
cloudwatch_stubber.activate()

0 commit comments

Comments
 (0)