Skip to content

Commit 5930ceb

Browse files
authored
Merge pull request #104 from cloudgraphdev/feature/CG-1282-support-monitoring-rules
Feature/cg 1282 support monitoring rules
2 parents ec51380 + 73ac7ad commit 5930ceb

18 files changed

Lines changed: 3481 additions & 1 deletion

src/aws/cis-1.5.0/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,18 @@ Policy Pack based on the [AWS Foundations 1.5.0](https://drive.google.com/file/d
8989
| AWS CIS 3.9 | Ensure VPC flow logging is enabled in all VPCs |
9090
| AWS CIS 3.10 | Ensure that Object-level logging for write events is enabled for S3 bucket |
9191
| AWS CIS 3.11 | Ensure that Object-level logging for read events is enabled for S3 bucket |
92+
| AWS CIS 4.1 | Ensure a log metric filter and alarm exist for unauthorized API calls |
93+
| AWS CIS 4.2 | Ensure a log metric filter and alarm exist for Management Console sign-in without MFA |
94+
| AWS CIS 4.3 | Ensure a log metric filter and alarm exist for usage of 'root' account |
95+
| AWS CIS 4.4 | Ensure a log metric filter and alarm exist for IAM policy changes |
96+
| AWS CIS 4.5 | Ensure a log metric filter and alarm exist for CloudTrail configuration changes |
97+
| AWS CIS 4.6 | Ensure a log metric filter and alarm exist for AWS Management Console authentication failures |
98+
| AWS CIS 4.7 | Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs |
99+
| AWS CIS 4.8 | Ensure a log metric filter and alarm exist for S3 bucket policy changes |
100+
| AWS CIS 4.9 | Ensure a log metric filter and alarm exist for AWS Config configuration changes |
101+
| AWS CIS 4.10 | Ensure a log metric filter and alarm exist for security group changes |
102+
| AWS CIS 4.11 | Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) |
103+
| AWS CIS 4.12 | Ensure a log metric filter and alarm exist for changes to network gateways |
104+
| AWS CIS 4.13 | Ensure a log metric filter and alarm exist for route table changes |
105+
| AWS CIS 4.14 | Ensure a log metric filter and alarm exist for VPC changes |
106+
| AWS CIS 4.15 | Ensure a log metric filter and alarm exists for AWS Organizations changes |
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
2+
/* eslint-disable @typescript-eslint/no-explicit-any */
3+
// AWS CIS 1.2.0 Rule equivalent 3.1
4+
export default {
5+
id: 'aws-cis-1.5.0-4.1',
6+
title:
7+
'AWS CIS 4.1 Ensure a log metric filter and alarm exist for unauthorized API calls',
8+
description: `Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to
9+
CloudWatch Logs and establishing corresponding metric filters and alarms. It is
10+
recommended that a metric filter and alarm be established for unauthorized API calls.`,
11+
audit: `Perform the following to ensure that there is at least one active multi-region CloudTrail with prescribed metric filters and alarms configured:
12+
13+
1. Identify the log group name configured for use with active multi-region CloudTrail:
14+
15+
- List all CloudTrails: *aws cloudtrail describe-trails*
16+
- Identify Multi region Cloudtrails: *Trails with "IsMultiRegionTrail" set to true*
17+
- From value associated with CloudWatchLogsLogGroupArn note *<cloudtrail_log_group_name>*
18+
19+
Example: for CloudWatchLogsLogGroupArn that looks like _arn:aws:logs:<region>:<aws_account_number>:log-group:NewGroup:*, <cloudtrail_log_group_name>_ would be *NewGroup*
20+
21+
- Ensure Identified Multi region CloudTrail is active
22+
23+
*aws cloudtrail get-trail-status --name <Name_of_a_Multi-region_CloudTrail>* ensure *IsLogging* is set to *TRUE*
24+
25+
- Ensure identified Multi-region Cloudtrail captures all Management Events
26+
27+
*aws cloudtrail get-event-selectors --trail-name <trailname_shown_in_describe-trails>*
28+
Ensure there is at least one Event Selector for a Trail with *IncludeManagementEvents* set to *true* and *ReadWriteType* set to *All*
29+
30+
2. Get a list of all associated metric filters for this *<cloudtrail_log_group_name>*:
31+
32+
aws logs describe-metric-filters --log-group-name "<cloudtrail_log_group_name>"
33+
34+
3. Ensure the output from the above command contains the following:
35+
36+
"filterPattern": "{ ($.errorCode = "*UnauthorizedOperation") || ($.errorCode = "AccessDenied*") }"
37+
38+
4. Note the *<unauthorized_api_calls_metric>* value associated with the filterPattern found in step 3.
39+
5. Get a list of CloudWatch alarms and filter on the *<unauthorized_api_calls_metric>* captured in step 4.
40+
41+
aws cloudwatch describe-alarms --query 'MetricAlarms[?MetricName== "<unauthorized_api_calls_metric>"]'
42+
43+
6. Note the *AlarmActions* value - this will provide the SNS topic ARN value.
44+
7. Ensure there is at least one active subscriber to the SNS topic
45+
46+
aws sns list-subscriptions-by-topic --topic-arn <sns_topic_arn>
47+
48+
at least one subscription should have "SubscriptionArn" with valid aws ARN.
49+
50+
Example of valid "SubscriptionArn": "arn:aws:sns:<region>:<aws_account_number>:<SnsTopicName>:<SubscriptionID>"`,
51+
rationale: 'Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.',
52+
remediation: `Perform the following to setup the metric filter, alarm, SNS topic, and subscription:
53+
54+
1. Create a metric filter based on the filter pattern provided which checks for unauthorized API calls and the *<cloudtrail_log_group_name>* taken from audit step 1.
55+
56+
aws logs put-metric-filter --log-group-name <cloudtrail_log_group_name> -- filter-name "<unauthorized_api_calls_metric>" --metric-transformations metricName= "<unauthorized_api_calls_metric>",metricNamespace='CISBenchmark',metricValue=1 --filter-pattern '{ ($.errorCode = "*UnauthorizedOperation") || ($.errorCode = "AccessDenied*") }'
57+
58+
**Note**: You can choose your own metricName and metricNamespace strings. Using the same metricNamespace for all Foundations Benchmark metrics will group them together.
59+
60+
2. Create an SNS topic that the alarm will notify
61+
62+
aws sns create-topic --name <sns_topic_name>
63+
64+
**Note** : you can execute this command once and then re-use the same topic for all monitoring alarms.
65+
66+
3. Create an SNS subscription to the topic created in step 2
67+
68+
aws sns subscribe --topic-arn <sns_topic_arn> --protocol <protocol_for_sns> -- notification-endpoint <sns_subscription_endpoints>
69+
70+
**Note**: you can execute this command once and then re-use the SNS subscription for all monitoring alarms.
71+
72+
4. Create an alarm that is associated with the CloudWatch Logs Metric Filter created in step 1 and an SNS topic created in step 2
73+
74+
aws cloudwatch put-metric-alarm --alarm-name "<unauthorized_api_calls_alarm>" --metric-name "<unauthorized_api_calls_metric>" --statistic Sum --period 300 --threshold 1 --comparison-operator GreaterThanOrEqualToThreshold --evaluation-periods 1 -- namespace 'CISBenchmark' --alarm-actions <sns_topic_arn>`,
75+
references: [
76+
'https://aws.amazon.com/sns/',
77+
'CCE-79186-3',
78+
'https://docs.aws.amazon.com/awscloudtrail/latest/userguide/receive-cloudtrail-log-files-from-multiple-regions.html',
79+
'https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html',
80+
'https://docs.aws.amazon.com/sns/latest/dg/SubscribeTopic.html',
81+
],
82+
gql: `{
83+
queryawsAccount {
84+
id
85+
__typename
86+
cloudtrail {
87+
isMultiRegionTrail
88+
status {
89+
isLogging
90+
}
91+
eventSelectors {
92+
id
93+
readWriteType
94+
includeManagementEvents
95+
}
96+
cloudwatchLog {
97+
arn
98+
metricFilters {
99+
id
100+
filterName
101+
filterPattern
102+
metricTransformations {
103+
metricName
104+
}
105+
}
106+
cloudwatch {
107+
metric
108+
arn
109+
actions
110+
sns {
111+
arn
112+
subscriptions {
113+
arn
114+
}
115+
}
116+
}
117+
}
118+
}
119+
}
120+
}`,
121+
resource: 'queryawsAccount[*]',
122+
severity: 'medium',
123+
check: ({ resource }: any) : any => {
124+
return resource.cloudtrail
125+
?.filter(
126+
(cloudtrail: any) =>
127+
cloudtrail.cloudwatchLog?.length &&
128+
cloudtrail.isMultiRegionTrail === 'Yes' &&
129+
cloudtrail.status?.isLogging &&
130+
cloudtrail.eventSelectors?.some(
131+
(selector: any) =>
132+
selector.readWriteType === 'All' &&
133+
selector.includeManagementEvents
134+
)
135+
)
136+
?.some((cloudtrail: any) => {
137+
const log = cloudtrail.cloudwatchLog[0]
138+
139+
return log.metricFilters?.some((metricFilter: any) => {
140+
const metricTrasformation = metricFilter.metricTransformations?.find(
141+
(mt: any) =>
142+
log.cloudwatch?.find((cw: any) => cw.metric === mt.metricName)
143+
)
144+
145+
if (!metricTrasformation) return false
146+
const metricCloudwatch = log.cloudwatch?.find(
147+
(cw: any) => cw.metric === metricTrasformation.metricName
148+
)
149+
150+
return (
151+
metricCloudwatch?.sns?.some((sns: any) =>
152+
sns?.subscriptions?.some((sub: any) =>
153+
sub.arn.includes('arn:aws:')
154+
)
155+
) &&
156+
/(\$.errorCode)\s*=\s*"UnauthorizedOperation"/.test(
157+
metricFilter.filterPattern
158+
) &&
159+
/(\$.errorCode)\s*=\s*"AccessDenied"/.test(
160+
metricFilter.filterPattern
161+
)
162+
)
163+
})
164+
})
165+
},
166+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
2+
/* eslint-disable @typescript-eslint/no-explicit-any */
3+
// AWS CIS 1.2.0 Rule equivalent 3.10
4+
const filterPatternRegex =
5+
/\$\.eventName\s*=\s*AuthorizeSecurityGroupIngress.+\$\.eventName\s*=\s*AuthorizeSecurityGroupEgress.+\$\.eventName\s*=\s*RevokeSecurityGroupIngress.+\$\.eventName\s*=\s*RevokeSecurityGroupEgress.+\$\.eventName\s*=\s*CreateSecurityGroup.+\$\.eventName\s*=\s*DeleteSecurityGroup/
6+
7+
export default {
8+
id: 'aws-cis-1.5.0-4.10',
9+
title:
10+
'AWS CIS 4.10 Ensure a log metric filter and alarm exist for security group changes',
11+
description: `Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to
12+
CloudWatch Logs and establishing corresponding metric filters and alarms. Security
13+
Groups are a stateful packet filter that controls ingress and egress traffic within a VPC. It is
14+
recommended that a metric filter and alarm be established changes to Security Groups.`,
15+
audit: `Perform the following to ensure that there is at least one active multi-region CloudTrail with prescribed metric filters and alarms configured:
16+
17+
1. Identify the log group name configured for use with active multi-region CloudTrail:
18+
19+
- List all CloudTrails: *aws cloudtrail describe-trails*
20+
- Identify Multi region Cloudtrails: *Trails with "IsMultiRegionTrail" set to true*
21+
- From value associated with CloudWatchLogsLogGroupArn note *<cloudtrail_log_group_name>*
22+
23+
Example: for CloudWatchLogsLogGroupArn that looks like _arn:aws:logs:<region>:<aws_account_number>:log-group:NewGroup:*, <cloudtrail_log_group_name>_ would be *NewGroup*
24+
25+
- Ensure Identified Multi region CloudTrail is active
26+
27+
*aws cloudtrail get-trail-status --name <Name_of_a_Multi-region_CloudTrail>* ensure *IsLogging* is set to *TRUE*
28+
29+
- Ensure identified Multi-region Cloudtrail captures all Management Events
30+
31+
*aws cloudtrail get-event-selectors --trail-name <trailname_shown_in_describe-trails>*
32+
Ensure there is at least one Event Selector for a Trail with *IncludeManagementEvents* set to *true* and *ReadWriteType* set to *All*
33+
34+
2. Get a list of all associated metric filters for this *<cloudtrail_log_group_name>*:
35+
36+
aws logs describe-metric-filters --log-group-name "<cloudtrail_log_group_name>"
37+
38+
3. Ensure the output from the above command contains the following:
39+
40+
"filterPattern": "{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup) }"
41+
42+
4. Note the *<security_group_changes_metric>* value associated with the *filterPattern* found in step 3.
43+
5. Get a list of CloudWatch alarms and filter on the *<security_group_changes_metric>* captured in step 4.
44+
45+
aws cloudwatch describe-alarms --query 'MetricAlarms[?MetricName== "<security_group_changes_metric>"]'
46+
47+
6. Note the *AlarmActions* value - this will provide the SNS topic ARN value.
48+
7. Ensure there is at least one active subscriber to the SNS topic
49+
50+
aws sns list-subscriptions-by-topic --topic-arn <sns_topic_arn>
51+
52+
at least one subscription should have "SubscriptionArn" with valid aws ARN.
53+
54+
Example of valid "SubscriptionArn": "arn:aws:sns:<region>:<aws_account_number>:<SnsTopicName>:<SubscriptionID>"`,
55+
rationale: 'Monitoring changes to security group will help ensure that resources and services are not unintentionally exposed.',
56+
remediation: `Perform the following to setup the metric filter, alarm, SNS topic, and subscription:
57+
58+
1. Create a metric filter based on filter pattern provided which checks for security groups changes and the *<cloudtrail_log_group_name>* taken from audit step 1.
59+
60+
aws logs put-metric-filter --log-group-name <cloudtrail_log_group_name> -- filter-name "<security_group_changes_metric>" --metric-transformations metricName= "<security_group_changes_metric>" ,metricNamespace='CISBenchmark',metricValue=1 --filter-pattern '{($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup) }'
61+
62+
**Note** : You can choose your own metricName and metricNamespace strings. Using the same metricNamespace for all Foundations Benchmark metrics will group them together.
63+
64+
2. Create an SNS topic that the alarm will notify
65+
66+
aws sns create-topic --name <sns_topic_name>
67+
68+
**Note** : you can execute this command once and then re-use the same topic for all
69+
monitoring alarms.
70+
71+
3. Create an SNS subscription to the topic created in step 2
72+
73+
aws sns subscribe --topic-arn <sns_topic_arn> --protocol <protocol_for_sns> -- notification-endpoint <sns_subscription_endpoints>
74+
75+
**Note**: you can execute this command once and then re-use the SNS subscription for all monitoring alarms.
76+
77+
4. Create an alarm that is associated with the CloudWatch Logs Metric Filter created in step 1 and an SNS topic created in step 2
78+
79+
aws cloudwatch put-metric-alarm --alarm-name "<security_group_changes_alarm>" --metric-name "<security_group_changes_metric>" --statistic Sum --period 300 --threshold 1 --comparison-operator GreaterThanOrEqualToThreshold --evaluation-periods 1 -- namespace 'CISBenchmark' --alarm-actions <sns_topic_arn>`,
80+
references: [
81+
'CCE-79195-4',
82+
'https://docs.aws.amazon.com/awscloudtrail/latest/userguide/receive-cloudtrail-log-files-from-multiple-regions.html',
83+
'https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html',
84+
'https://docs.aws.amazon.com/sns/latest/dg/SubscribeTopic.html',
85+
],
86+
gql: `{
87+
queryawsAccount {
88+
id
89+
__typename
90+
cloudtrail {
91+
isMultiRegionTrail
92+
status {
93+
isLogging
94+
}
95+
eventSelectors {
96+
id
97+
readWriteType
98+
includeManagementEvents
99+
}
100+
cloudwatchLog {
101+
arn
102+
metricFilters {
103+
id
104+
filterName
105+
filterPattern
106+
metricTransformations {
107+
metricName
108+
}
109+
}
110+
cloudwatch {
111+
metric
112+
arn
113+
actions
114+
sns {
115+
arn
116+
subscriptions {
117+
arn
118+
}
119+
}
120+
}
121+
}
122+
}
123+
}
124+
}`,
125+
resource: 'queryawsAccount[*]',
126+
severity: 'high',
127+
check: ({ resource }: any): any => {
128+
return resource.cloudtrail
129+
?.filter(
130+
(cloudtrail: any) =>
131+
cloudtrail.cloudwatchLog?.length &&
132+
cloudtrail.isMultiRegionTrail === 'Yes' &&
133+
cloudtrail.status?.isLogging &&
134+
cloudtrail.eventSelectors?.some(
135+
(selector: any) =>
136+
selector.readWriteType === 'All' &&
137+
selector.includeManagementEvents
138+
)
139+
)
140+
?.some((cloudtrail: any) => {
141+
const log = cloudtrail.cloudwatchLog[0]
142+
143+
return log.metricFilters?.some((metricFilter: any) => {
144+
const metricTrasformation = metricFilter.metricTransformations?.find(
145+
(mt: any) =>
146+
log.cloudwatch?.find((cw: any) => cw.metric === mt.metricName)
147+
)
148+
149+
if (!metricTrasformation) return false
150+
const metricCloudwatch = log.cloudwatch?.find(
151+
(cw: any) => cw.metric === metricTrasformation.metricName
152+
)
153+
154+
return (
155+
metricCloudwatch?.sns?.some((sns: any) =>
156+
sns?.subscriptions?.some((sub: any) =>
157+
sub.arn.includes('arn:aws:')
158+
)
159+
) &&
160+
filterPatternRegex.test(metricFilter.filterPattern)
161+
)
162+
})
163+
})
164+
},
165+
}

0 commit comments

Comments
 (0)