├── .DS_Store ├── 01_dashboards └── guidance.txt ├── 02_cloudwatchagent └── guidance.txt ├── 03_instancereachability └── Cloudwatch_add_reachability_check.sh ├── 04_cloudwatchevents └── guidance.txt ├── 05_alarms ├── db_freespace.sh ├── ec2_events │ ├── add_cw_event_ec2_retirement.sh │ └── template.json └── guidance.txt ├── 06_snstoslack └── snstoslack_lambda.js ├── 07_cismetricfilters ├── cisbenchmark.yaml └── url_for_cf.txt ├── README.md └── helpful_links.txt /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arpcefxl/awsmonitoringstrategies/ae0c5cb89431314e87b4cc3e3f05817bd7513b7e/.DS_Store -------------------------------------------------------------------------------- /01_dashboards/guidance.txt: -------------------------------------------------------------------------------- 1 | build a dashboard using the AWS console 2 | -------------------------------------------------------------------------------- /02_cloudwatchagent/guidance.txt: -------------------------------------------------------------------------------- 1 | Install/configure CloudWatch Agent using the AWS Console 2 | 3 | Create EC2 IAM role with CloudWatchAgentServerPolicy, and AmazonEC2RoleforSSM attached, name it CloudWatchAgentServerRole 4 | Create EC2 IAM role with CloudWatchAgentAdminPolicy and AmazonEC2RoleforSSM attached, name it CloudWatchAgentAdminRole 5 | For on-premises or multi-cloud users, you would also create an IAM user for those resources to access the appropriate services 6 | Switch to EC2 7 | Change running instance role to CloudWatchAgentAdminRole 8 | Start run command, pick AWS-ConfigureAWSPackage 9 | Choose install, and type AmazonCloudWatchAgent 10 | Choose instance(s) 11 | Click Run 12 | Wait for a few seconds, refresh, then click on view output to verify it worked 13 | SSH to instance 14 | execute the following: 15 | sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard 16 | Answer all questions and verify config placed into SSM 17 | Switch to run command 18 | Choose AmazonCloudWatch-ManageAgent (page 4) 19 | Action->Configure 20 | In Optional Configuration Location, type AmazonCloudWatch-linux 21 | Click Run 22 | Switch To CloudWatch 23 | takes a little bit 24 | Click on Metrics, then CWAgent 25 | At this point, EC2 instance role can be switched to CloudWatchAgentServerRole 26 | 27 | -------------------------------------------------------------------------------- /03_instancereachability/Cloudwatch_add_reachability_check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | REGION=$1 3 | SNSTOPIC=$2 4 | 5 | #Generate a list of instance IDs for instances in RUNNING state 6 | INSTANCES=`/usr/local/bin/aws ec2 describe-instances --region $REGION --output text --filters "Name=instance-state-code,Values=16" --query Reservations[*].Instances[*].InstanceId |tr '\t' '\n'` 7 | 8 | #Generate a list of existing alarms to compare against 9 | #Executing this once prevents us from running this for every instance 10 | ALARMS=`/usr/local/bin/aws cloudwatch describe-alarms --alarm-name-prefix StatusCheckFailed-Alarm --state-value OK --output text --region $REGION --query 'MetricAlarms[].Dimensions[].Value' | tr '\t' '\n'` 11 | 12 | #Loop through all instances in the region, so we can test for existing alarms 13 | for i in `echo $INSTANCES`; do 14 | INSTANCE=$i 15 | echo "checking on $INSTANCE" 16 | 17 | if [[ $ALARMS != *"$INSTANCE"* ]]; then 18 | #Grab the value of the Name tag 19 | name=`/usr/local/bin/aws --output text ec2 describe-tags --region $REGION --filters "Name=resource-id,Values=$INSTANCE" "Name=key,Values=Name" --query Tags[*].Value` 20 | #Create the new alarm 21 | #Alarm name uses the name tag value 22 | #SNS topic ARN provided on script command line 23 | echo "creating alarms for $INSTANCE named $name" 24 | /usr/local/bin/aws cloudwatch put-metric-alarm --alarm-name StatusCheckFailed-Alarm_$name --alarm-description "Alarm when StatusCheckFailed metric has a value of one for two periods" --metric-name StatusCheckFailed --namespace AWS/EC2 --statistic Maximum --dimensions Name=InstanceId,Value=$INSTANCE --region $REGION --period 300 --unit Count --evaluation-periods 2 --threshold 1 --comparison-operator GreaterThanOrEqualToThreshold --alarm-actions $SNSTOPIC --insufficient-data-actions $SNSTOPIC 25 | 26 | fi 27 | done 28 | 29 | -------------------------------------------------------------------------------- /04_cloudwatchevents/guidance.txt: -------------------------------------------------------------------------------- 1 | Create CloudWatch Event rules in the AWS Console 2 | -------------------------------------------------------------------------------- /05_alarms/db_freespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | REGION=$1 4 | DBID=$2 5 | MINSIZE=10000000000 6 | 7 | #UNCOMMENT IF YOU ARE RUNNING ON PROPER LINUX 8 | #linux date 9 | tenminago=`date -u +%FT%TZ -d "10 minutes ago"` 10 | now=`date -u +%FT%TZ` 11 | 12 | #UNCOMMENT IF YOU ARE RUNNING ON MACOS 13 | #macos date 14 | #tenminago=`date -v -10M -u +%FT%TZ` 15 | #now=`date -u +%FT%TZ` 16 | 17 | freesize=`aws --region $REGION cloudwatch get-metric-statistics \ 18 | --metric-name FreeStorageSpace --start-time $tenminago \ 19 | --end-time $now --period 3600 --namespace AWS/RDS \ 20 | --statistics Average \ 21 | --dimensions Name=DBInstanceIdentifier,Value=$DBID \ 22 | --query Datapoints[].Average \ 23 | --output text` 24 | 25 | #Convert the output of the free size to an integer for easy comparison 26 | freesizeint=`echo ${freesize%.*}` 27 | 28 | #Print out the amount of free space 29 | echo "free size is $freesizeint" 30 | 31 | if [ "$freesizeint" -lt "$MINSIZE" ]; then 32 | echo "DB volume will be extended due to limited space" 33 | 34 | #Figure out existing storage for DB instance 35 | currentstorage=`aws rds describe-db-instances \ 36 | --db-instance-identifier $DBID --region $REGION \ 37 | --query DBInstances[].AllocatedStorage --output text` 38 | 39 | #Print out the current provisioned storage 40 | echo "The current storage size is $currentstorage" 41 | 42 | #Add 10Gb to the existing storage 43 | NEWSTORAGE=$(($currentstorage + 10)) 44 | echo "Increasing storage size to $NEWSTORAGE" 45 | aws rds modify-db-instance --db-instance-identifier $DBID \ 46 | --allocated-storage $NEWSTORAGE --apply-immediately --region $REGION 47 | else 48 | echo "DB size is fine" 49 | fi 50 | -------------------------------------------------------------------------------- /05_alarms/ec2_events/add_cw_event_ec2_retirement.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | REGION=$1 4 | SNSTOPIC=$2 5 | 6 | #Create the event rule first. These can exist with no targets 7 | aws events put-rule --name "EC2RetirementNotification" \ 8 | --event-pattern "{\"source\":[\"aws.health\"],\"detail-type\":[\"AWS Health Event\"],\"detail\":{\"service"\":[\"EC2\"],\"eventTypeCategory"\":[\"scheduledChange\"],\"eventTypeCode"\":[\"AWS_EC2_INSTANCE_RETIREMENT_SCHEDULED\"]}"}" \ 9 | --region $REGION 10 | 11 | #Remove target.json from previous script run 12 | rm target.json 13 | #Replace the template values with correct values 14 | sed "s/TOPICARN/$SNSTOPIC/g" template.json > target.json 15 | 16 | #Create the event target using the updated json template 17 | aws events put-targets --rule EC2RetirementNotification \ 18 | --targets file://target.json --region $REGION 19 | 20 | -------------------------------------------------------------------------------- /05_alarms/ec2_events/template.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id":"1", 4 | "Arn":"TOPICARN" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /05_alarms/guidance.txt: -------------------------------------------------------------------------------- 1 | Create Billing Alarm/Budget in AWS Console 2 | ec2 instance action alarms 3 | script based on db free space (using cli) and command to extend by 10 gb 4 | -------------------------------------------------------------------------------- /06_snstoslack/snstoslack_lambda.js: -------------------------------------------------------------------------------- 1 | var https = require('https'); 2 | var util = require('util'); 3 | 4 | exports.handler = function(event, context) { 5 | console.log(JSON.stringify(event, null, 2)); 6 | console.log('From SNS:', event.Records[0].Sns.Message); 7 | 8 | var postData = { 9 | "channel": "#guardduty-alerts", 10 | "username": "GuardDuty Finding", 11 | "text": "*" + event.Records[0].Sns.Subject + "*", 12 | "icon_emoji": ":aws:" 13 | }; 14 | 15 | var message = event.Records[0].Sns.Message; 16 | var severity = "good"; 17 | 18 | var dangerMessages = [ 19 | " but with errors", 20 | " to RED", 21 | "During an aborted deployment", 22 | "Failed to deploy application", 23 | "Failed to deploy configuration", 24 | "has a dependent object", 25 | "is not authorized to perform", 26 | "Pending to Degraded", 27 | "Stack deletion failed", 28 | "Unsuccessful command execution", 29 | "You do not have permission", 30 | "Your quota allows for 0 more running instance"]; 31 | 32 | var warningMessages = [ 33 | " aborted operation.", 34 | " to YELLOW", 35 | "Adding instance ", 36 | "Degraded to Info", 37 | "Deleting SNS topic", 38 | "is currently running under desired capacity", 39 | "Ok to Info", 40 | "Ok to Warning", 41 | "Pending Initialization", 42 | "Removed instance ", 43 | "Rollback of environment" 44 | ]; 45 | 46 | for(var dangerMessagesItem in dangerMessages) { 47 | if (message.indexOf(dangerMessages[dangerMessagesItem]) != -1) { 48 | severity = "danger"; 49 | break; 50 | } 51 | } 52 | 53 | // Only check for warning messages if necessary 54 | if (severity == "good") { 55 | for(var warningMessagesItem in warningMessages) { 56 | if (message.indexOf(warningMessages[warningMessagesItem]) != -1) { 57 | severity = "warning"; 58 | break; 59 | } 60 | } 61 | } 62 | postData.attachments = [ 63 | { 64 | "color": severity, 65 | "text": message 66 | } 67 | ]; 68 | 69 | var options = { 70 | method: 'POST', 71 | hostname: 'hooks.slack.com', 72 | port: 443, 73 | path: '/services/CHANGE TO YOUR WEBHOOK URL' 74 | }; 75 | var req = https.request(options, function(res) { 76 | res.setEncoding('utf8'); 77 | res.on('data', function (chunk) { 78 | context.done(null); 79 | }); 80 | }); 81 | req.on('error', function(e) { 82 | console.log('problem with request: ' + e.message); 83 | }); 84 | 85 | req.write(util.format("%j", postData)); 86 | req.end(); 87 | }; 88 | 89 | -------------------------------------------------------------------------------- /07_cismetricfilters/cisbenchmark.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | AWSTemplateFormatVersion: 2010-09-09 3 | Description: CIS AWS Foundations Benchmark Metric Alarms 4 | Parameters: 5 | AlarmNotificationTopicARN: 6 | Description: SNS topic to send alerts to 7 | Type: String 8 | CloudtrailLogGroupName: 9 | Description: Name of the Cloudtrail log group 10 | Type: String 11 | Resources: 12 | #=============================================================================================================================== 13 | # MetricFilter and CloudWatch Alarm Section 14 | #=============================================================================================================================== 15 | 16 | # ------------------------------------------------------------------------------------------------------------------------------------ 17 | # CIS AWS Foundations Benchmark - 3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) 18 | # ------------------------------------------------------------------------------------------------------------------------------------ 19 | UnauthorizedApiCallsAlarm: 20 | Type: AWS::CloudWatch::Alarm 21 | Properties: 22 | AlarmName: CIS-Unauthorized Activity Attempt 23 | AlarmDescription: Alarm if Multiple unauthorized actions or logins attempted 24 | MetricName: UnauthorizedAttemptCount 25 | Namespace: CloudTrailMetrics 26 | Statistic: Sum 27 | Period: 300 28 | EvaluationPeriods: '1' 29 | Threshold: 1 30 | TreatMissingData: notBreaching 31 | AlarmActions: 32 | - !Ref AlarmNotificationTopicARN 33 | ComparisonOperator: GreaterThanOrEqualToThreshold 34 | UnauthorizedApiCallsFilter: 35 | Type: AWS::Logs::MetricFilter 36 | Properties: 37 | LogGroupName: !Ref CloudtrailLogGroupName 38 | FilterPattern: |- 39 | { 40 | ($.errorCode = "*UnauthorizedOperation") || 41 | ($.errorCode = "AccessDenied*") 42 | } 43 | MetricTransformations: 44 | - MetricValue: '1' 45 | MetricNamespace: CloudTrailMetrics 46 | MetricName: UnauthorizedAttemptCount 47 | 48 | # ------------------------------------------------------------------------------------------------------------------------------------ 49 | # CIS AWS Foundations Benchmark - 3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) 50 | # ------------------------------------------------------------------------------------------------------------------------------------ 51 | NoMfaConsoleLoginsAlarm: 52 | Type: AWS::CloudWatch::Alarm 53 | Properties: 54 | AlarmName: CIS-Console Signin Without MFA 55 | AlarmDescription: Alarm if there is a Management Console sign-in without MFA 56 | MetricName: ConsoleSigninWithoutMFA 57 | Namespace: CloudTrailMetrics 58 | Statistic: Sum 59 | Period: 300 60 | EvaluationPeriods: 1 61 | Threshold: 1 62 | TreatMissingData: notBreaching 63 | AlarmActions: 64 | - !Ref AlarmNotificationTopicARN 65 | ComparisonOperator: GreaterThanOrEqualToThreshold 66 | NoMfaConsoleLoginsFilter: 67 | Type: AWS::Logs::MetricFilter 68 | Properties: 69 | LogGroupName: !Ref CloudtrailLogGroupName 70 | FilterPattern: |- 71 | { 72 | ($.eventName = "ConsoleLogin") && 73 | ($.additionalEventData.MFAUsed != "Yes") 74 | } 75 | MetricTransformations: 76 | - MetricValue: '1' 77 | MetricNamespace: CloudTrailMetrics 78 | MetricName: ConsoleSigninWithoutMFA 79 | 80 | # ------------------------------------------------------------------------------------------------------------------------------------ 81 | # CIS AWS Foundations Benchmark - 1.1 Avoid the use of the "root" account (Scored) 82 | # CIS AWS Foundations Benchmark - 3.3 Ensure a log metric filter and alarm exist for usage of "root" account (Scored) 83 | # ------------------------------------------------------------------------------------------------------------------------------------ 84 | RootAccountLoginsAlarm: 85 | Type: AWS::CloudWatch::Alarm 86 | DependsOn: 87 | - NoMfaConsoleLoginsAlarm 88 | Properties: 89 | AlarmName: CIS-Root Activity 90 | AlarmDescription: Alarm if a 'root' user uses the account 91 | MetricName: RootUserEventCount 92 | Namespace: CloudTrailMetrics 93 | Statistic: Sum 94 | Period: 300 95 | EvaluationPeriods: 1 96 | Threshold: 1 97 | TreatMissingData: notBreaching 98 | AlarmActions: 99 | - !Ref AlarmNotificationTopicARN 100 | ComparisonOperator: GreaterThanOrEqualToThreshold 101 | RootAccountLoginsFilter: 102 | Type: AWS::Logs::MetricFilter 103 | Properties: 104 | LogGroupName: !Ref CloudtrailLogGroupName 105 | FilterPattern: |- 106 | { 107 | $.userIdentity.type = "Root" && 108 | $.userIdentity.invokedBy NOT EXISTS && 109 | $.eventType != "AwsServiceEvent" 110 | } 111 | MetricTransformations: 112 | - MetricValue: '1' 113 | MetricNamespace: CloudTrailMetrics 114 | MetricName: RootUserEventCount 115 | 116 | # -------------------------------------------------------------------------------------------------------------------------------------------- 117 | # CIS AWS Foundations Benchmark - 3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) 118 | # -------------------------------------------------------------------------------------------------------------------------------------------- 119 | IAMPolicyChangesAlarm: 120 | Type: AWS::CloudWatch::Alarm 121 | Properties: 122 | AlarmName: CIS-IAM Policy Changes 123 | AlarmDescription: Alarm if an IAM policy changes 124 | MetricName: IAMPolicyChangeEventCount 125 | Namespace: CloudTrailMetrics 126 | Statistic: Sum 127 | Period: 300 128 | EvaluationPeriods: 1 129 | Threshold: 1 130 | TreatMissingData: notBreaching 131 | AlarmActions: 132 | - !Ref AlarmNotificationTopicARN 133 | ComparisonOperator: GreaterThanOrEqualToThreshold 134 | IAMPolicyChangesFilter: 135 | Type: AWS::Logs::MetricFilter 136 | Properties: 137 | LogGroupName: !Ref CloudtrailLogGroupName 138 | FilterPattern: |- 139 | { 140 | ($.eventName=DeleteGroupPolicy) || 141 | ($.eventName=DeleteRolePolicy) || 142 | ($.eventName=DeleteUserPolicy) || 143 | ($.eventName=PutGroupPolicy) || 144 | ($.eventName=PutRolePolicy) || 145 | ($.eventName=PutUserPolicy) || 146 | ($.eventName=CreatePolicy) || 147 | ($.eventName=DeletePolicy) || 148 | ($.eventName=CreatePolicyVersion) || 149 | ($.eventName=DeletePolicyVersion) || 150 | ($.eventName=AttachRolePolicy) || 151 | ($.eventName=DetachRolePolicy) || 152 | ($.eventName=AttachUserPolicy) || 153 | ($.eventName=DetachUserPolicy) || 154 | ($.eventName=AttachGroupPolicy) || 155 | ($.eventName=DetachGroupPolicy) 156 | } 157 | MetricTransformations: 158 | - MetricValue: '1' 159 | MetricNamespace: CloudTrailMetrics 160 | MetricName: IAMPolicyChangeEventCount 161 | 162 | # -------------------------------------------------------------------------------------------------------------------------------------------- 163 | # CIS AWS Foundations Benchmark - 3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) 164 | # -------------------------------------------------------------------------------------------------------------------------------------------- 165 | CloudtrailConfigChangesAlarm: 166 | Type: AWS::CloudWatch::Alarm 167 | Properties: 168 | AlarmName: CIS-Cloudtrail Config Changes 169 | AlarmDescription: Alarm if the configuration for Cloudtrail changes 170 | MetricName: CloudtrailConfigChangeEventCount 171 | Namespace: CloudTrailMetrics 172 | Statistic: Sum 173 | Period: 300 174 | EvaluationPeriods: 1 175 | Threshold: 1 176 | TreatMissingData: notBreaching 177 | AlarmActions: 178 | - !Ref AlarmNotificationTopicARN 179 | ComparisonOperator: GreaterThanOrEqualToThreshold 180 | CloudtrailConfigChangesFilter: 181 | Type: AWS::Logs::MetricFilter 182 | Properties: 183 | LogGroupName: !Ref CloudtrailLogGroupName 184 | FilterPattern: |- 185 | { 186 | ($.eventName = CreateTrail) || 187 | ($.eventName = UpdateTrail) || 188 | ($.eventName = DeleteTrail) || 189 | ($.eventName = StartLogging) || 190 | ($.eventName = StopLogging) 191 | } 192 | MetricTransformations: 193 | - MetricValue: '1' 194 | MetricNamespace: CloudTrailMetrics 195 | MetricName: CloudtrailConfigChangeEventCount 196 | 197 | # -------------------------------------------------------------------------------------------------------------------------------------------- 198 | # CIS AWS Foundations Benchmark - 3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) 199 | # -------------------------------------------------------------------------------------------------------------------------------------------- 200 | FailedConsoleLoginsAlarm: 201 | Type: AWS::CloudWatch::Alarm 202 | DependsOn: 203 | - RootAccountLoginsAlarm 204 | Properties: 205 | AlarmName: CIS-Console Login Failures 206 | AlarmDescription: Alarm if there are AWS Management Console authentication failures 207 | MetricName: ConsoleLoginFailures 208 | Namespace: CloudTrailMetrics 209 | Statistic: Sum 210 | Period: '300' 211 | EvaluationPeriods: '1' 212 | Threshold: 1 213 | TreatMissingData: notBreaching 214 | AlarmActions: 215 | - !Ref AlarmNotificationTopicARN 216 | ComparisonOperator: GreaterThanOrEqualToThreshold 217 | FailedConsoleLoginsFilter: 218 | Type: AWS::Logs::MetricFilter 219 | Properties: 220 | LogGroupName: !Ref CloudtrailLogGroupName 221 | FilterPattern: |- 222 | { 223 | ($.eventName = ConsoleLogin) && 224 | ($.errorMessage = "Failed authentication") 225 | } 226 | MetricTransformations: 227 | - MetricValue: '1' 228 | MetricNamespace: CloudTrailMetrics 229 | MetricName: ConsoleLoginFailures 230 | 231 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 232 | # CIS AWS Foundations Benchmark - 3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) 233 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 234 | DisabledOrDeletedCmksAlarm: 235 | Type: AWS::CloudWatch::Alarm 236 | DependsOn: 237 | - FailedConsoleLoginsAlarm 238 | Properties: 239 | AlarmName: CIS-KMS Key Disabled or Scheduled for Deletion 240 | AlarmDescription: Alarm if customer created CMKs get disabled or scheduled for 241 | deletion 242 | MetricName: KMSCustomerKeyDeletion 243 | Namespace: CloudTrailMetrics 244 | Statistic: Sum 245 | Period: 60 246 | EvaluationPeriods: 1 247 | Threshold: 1 248 | TreatMissingData: notBreaching 249 | AlarmActions: 250 | - !Ref AlarmNotificationTopicARN 251 | ComparisonOperator: GreaterThanOrEqualToThreshold 252 | DisabledOrDeletedCmksFilter: 253 | Type: AWS::Logs::MetricFilter 254 | Properties: 255 | LogGroupName: !Ref CloudtrailLogGroupName 256 | FilterPattern: |- 257 | { 258 | ($.eventSource = kms.amazonaws.com) && 259 | (($.eventName=DisableKey) || ($.eventName=ScheduleKeyDeletion)) 260 | } 261 | MetricTransformations: 262 | - MetricValue: '1' 263 | MetricNamespace: CloudTrailMetrics 264 | MetricName: KMSCustomerKeyDeletion 265 | 266 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 267 | # CIS AWS Foundations Benchmark - 3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) 268 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 269 | S3BucketPolicyChangeAlarm: 270 | Type: AWS::CloudWatch::Alarm 271 | Properties: 272 | AlarmName: CIS-S3 Bucket Policy Changed 273 | AlarmDescription: Alarm if any S3 bucket policies are changed 274 | MetricName: S3BucketPolicyChanges 275 | Namespace: CloudTrailMetrics 276 | Statistic: Sum 277 | Period: 300 278 | EvaluationPeriods: 1 279 | Threshold: 1 280 | TreatMissingData: notBreaching 281 | AlarmActions: 282 | - !Ref AlarmNotificationTopicARN 283 | ComparisonOperator: GreaterThanOrEqualToThreshold 284 | S3BucketPolicyChangeFilter: 285 | Type: AWS::Logs::MetricFilter 286 | Properties: 287 | LogGroupName: !Ref CloudtrailLogGroupName 288 | FilterPattern: |- 289 | { 290 | ($.eventSource = s3.amazonaws.com) && 291 | (($.eventName = PutBucketAcl) || 292 | ($.eventName = PutBucketPolicy) || 293 | ($.eventName = PutBucketCors) || 294 | ($.eventName = PutBucketLifecycle) || 295 | ($.eventName = PutBucketReplication) || 296 | ($.eventName = DeleteBucketPolicy) || 297 | ($.eventName = DeleteBucketCors) || 298 | ($.eventName = DeleteBucketLifecycle) || 299 | ($.eventName = DeleteBucketReplication)) 300 | } 301 | MetricTransformations: 302 | - MetricValue: '1' 303 | MetricNamespace: CloudTrailMetrics 304 | MetricName: S3BucketPolicyChanges 305 | 306 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 307 | # CIS AWS Foundations Benchmark - 3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) 308 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 309 | AWSConfigConfigurationChangeAlarm: 310 | Type: AWS::CloudWatch::Alarm 311 | Properties: 312 | AlarmName: CIS-AWS Config Configuration has changed 313 | AlarmDescription: Alarm if the configuration for AWS Config changes 314 | MetricName: AWSConfigConfigurationChanges 315 | Namespace: CloudTrailMetrics 316 | Statistic: Sum 317 | Period: 300 318 | EvaluationPeriods: 1 319 | Threshold: 1 320 | TreatMissingData: notBreaching 321 | AlarmActions: 322 | - !Ref AlarmNotificationTopicARN 323 | ComparisonOperator: GreaterThanOrEqualToThreshold 324 | AWSConfigConfigurationChangeFilter: 325 | Type: AWS::Logs::MetricFilter 326 | Properties: 327 | LogGroupName: !Ref CloudtrailLogGroupName 328 | FilterPattern: |- 329 | { 330 | ($.eventSource = config.amazonaws.com) && 331 | (($.eventName=StopConfigurationRecorder)|| 332 | ($.eventName=DeleteDeliveryChannel)|| 333 | ($.eventName=PutDeliveryChannel)|| 334 | ($.eventName=PutConfigurationRecorder)) 335 | } 336 | MetricTransformations: 337 | - MetricValue: '1' 338 | MetricNamespace: CloudTrailMetrics 339 | MetricName: AWSConfigConfigurationChanges 340 | 341 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 342 | # CIS AWS Foundations Benchmark - 3.10 Ensure a log metric filter and alarm exist for security group changes (Scored) 343 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 344 | SecurityGroupChangeAlarm: 345 | Type: AWS::CloudWatch::Alarm 346 | Properties: 347 | AlarmName: CIS-Security Groups Have Changed 348 | AlarmDescription: Alarm if there are any changes to security groups 349 | MetricName: SecurityGroupChanges 350 | Namespace: CloudTrailMetrics 351 | Statistic: Sum 352 | Period: 300 353 | EvaluationPeriods: 1 354 | Threshold: 1 355 | TreatMissingData: notBreaching 356 | AlarmActions: 357 | - !Ref AlarmNotificationTopicARN 358 | ComparisonOperator: GreaterThanOrEqualToThreshold 359 | SecurityGroupChangeFilter: 360 | Type: AWS::Logs::MetricFilter 361 | Properties: 362 | LogGroupName: !Ref CloudtrailLogGroupName 363 | FilterPattern: |- 364 | { 365 | ($.eventName = AuthorizeSecurityGroupIngress) || 366 | ($.eventName = AuthorizeSecurityGroupEgress) || 367 | ($.eventName = RevokeSecurityGroupIngress) || 368 | ($.eventName = RevokeSecurityGroupEgress) || 369 | ($.eventName = CreateSecurityGroup) || 370 | ($.eventName = DeleteSecurityGroup) 371 | } 372 | MetricTransformations: 373 | - MetricValue: '1' 374 | MetricNamespace: CloudTrailMetrics 375 | MetricName: SecurityGroupChanges 376 | 377 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 378 | # CIS AWS Foundations Benchmark - 3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) 379 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 380 | NACLChangeAlarm: 381 | Type: AWS::CloudWatch::Alarm 382 | Properties: 383 | AlarmName: CIS-NACLs Have Changed 384 | AlarmDescription: Alarm if there are any changes to Network ACLs (NACLs) 385 | MetricName: NACLChanges 386 | Namespace: CloudTrailMetrics 387 | Statistic: Sum 388 | Period: 300 389 | EvaluationPeriods: 1 390 | Threshold: 1 391 | TreatMissingData: notBreaching 392 | AlarmActions: 393 | - !Ref AlarmNotificationTopicARN 394 | ComparisonOperator: GreaterThanOrEqualToThreshold 395 | NACLChangeFilter: 396 | Type: AWS::Logs::MetricFilter 397 | Properties: 398 | LogGroupName: !Ref CloudtrailLogGroupName 399 | FilterPattern: |- 400 | { 401 | ($.eventName = CreateNetworkAcl) || 402 | ($.eventName = CreateNetworkAclEntry) || 403 | ($.eventName = DeleteNetworkAcl) || 404 | ($.eventName = DeleteNetworkAclEntry) || 405 | ($.eventName = ReplaceNetworkAclEntry) || 406 | ($.eventName = ReplaceNetworkAclAssociation) 407 | } 408 | MetricTransformations: 409 | - MetricValue: '1' 410 | MetricNamespace: CloudTrailMetrics 411 | MetricName: NACLChanges 412 | 413 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 414 | # CIS AWS Foundations Benchmark - 3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) 415 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 416 | NetworkGatewayChangeAlarm: 417 | Type: AWS::CloudWatch::Alarm 418 | Properties: 419 | AlarmName: CIS-Network Gateways Have Changed 420 | AlarmDescription: Alarm if there are any changes to network gateways 421 | MetricName: NetworkGatewayChanges 422 | Namespace: CloudTrailMetrics 423 | Statistic: Sum 424 | Period: 300 425 | EvaluationPeriods: 1 426 | Threshold: 1 427 | TreatMissingData: notBreaching 428 | AlarmActions: 429 | - !Ref AlarmNotificationTopicARN 430 | ComparisonOperator: GreaterThanOrEqualToThreshold 431 | NetworkGatewayChangeFilter: 432 | Type: AWS::Logs::MetricFilter 433 | Properties: 434 | LogGroupName: !Ref CloudtrailLogGroupName 435 | FilterPattern: |- 436 | { 437 | ($.eventName = CreateCustomerGateway) || 438 | ($.eventName = DeleteCustomerGateway) || 439 | ($.eventName = AttachInternetGateway) || 440 | ($.eventName = CreateInternetGateway) || 441 | ($.eventName = DeleteInternetGateway) || 442 | ($.eventName = DetachInternetGateway) 443 | } 444 | MetricTransformations: 445 | - MetricValue: '1' 446 | MetricNamespace: CloudTrailMetrics 447 | MetricName: NetworkGatewayChanges 448 | 449 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 450 | # CIS AWS Foundations Benchmark - 3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) 451 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 452 | RouteTableChangeAlarm: 453 | Type: AWS::CloudWatch::Alarm 454 | Properties: 455 | AlarmName: CIS-Route Tables Have Changed 456 | AlarmDescription: Alarm if there are any changes to route tables 457 | MetricName: RouteTableChanges 458 | Namespace: CloudTrailMetrics 459 | Statistic: Sum 460 | Period: 300 461 | EvaluationPeriods: 1 462 | Threshold: 1 463 | TreatMissingData: notBreaching 464 | AlarmActions: 465 | - !Ref AlarmNotificationTopicARN 466 | ComparisonOperator: GreaterThanOrEqualToThreshold 467 | RouteTableChangeFilter: 468 | Type: AWS::Logs::MetricFilter 469 | Properties: 470 | LogGroupName: !Ref CloudtrailLogGroupName 471 | FilterPattern: |- 472 | { 473 | ($.eventName = CreateRoute) || 474 | ($.eventName = CreateRouteTable) || 475 | ($.eventName = ReplaceRoute) || 476 | ($.eventName = ReplaceRouteTableAssociation) || 477 | ($.eventName = DeleteRouteTable) || 478 | ($.eventName = DeleteRoute) || 479 | ($.eventName = DisassociateRouteTable) 480 | } 481 | MetricTransformations: 482 | - MetricValue: '1' 483 | MetricNamespace: CloudTrailMetrics 484 | MetricName: RouteTableChanges 485 | 486 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 487 | # CIS AWS Foundations Benchmark - 3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) 488 | # ------------------------------------------------------------------------------------------------------------------------------------------------------- 489 | VPCChangeAlarm: 490 | Type: AWS::CloudWatch::Alarm 491 | Properties: 492 | AlarmName: CIS-VPC Has Changed 493 | AlarmDescription: Alarm if there are any changes to any VPCs 494 | MetricName: VPCChanges 495 | Namespace: CloudTrailMetrics 496 | Statistic: Sum 497 | Period: 300 498 | EvaluationPeriods: 1 499 | Threshold: 1 500 | TreatMissingData: notBreaching 501 | AlarmActions: 502 | - !Ref AlarmNotificationTopicARN 503 | ComparisonOperator: GreaterThanOrEqualToThreshold 504 | VPCChangeFilter: 505 | Type: AWS::Logs::MetricFilter 506 | Properties: 507 | LogGroupName: !Ref CloudtrailLogGroupName 508 | FilterPattern: |- 509 | { 510 | ($.eventName = CreateVpc) || 511 | ($.eventName = DeleteVpc) || 512 | ($.eventName = ModifyVpcAttribute) || 513 | ($.eventName = AcceptVpcPeeringConnection) || 514 | ($.eventName = CreateVpcPeeringConnection) || 515 | ($.eventName = DeleteVpcPeeringConnection) || 516 | ($.eventName = RejectVpcPeeringConnection) || 517 | ($.eventName = AttachClassicLinkVpc) || 518 | ($.eventName = DetachClassicLinkVpc) || 519 | ($.eventName = DisableVpcClassicLink) || 520 | ($.eventName = EnableVpcClassicLink) 521 | } 522 | MetricTransformations: 523 | - MetricValue: '1' 524 | MetricNamespace: CloudTrailMetrics 525 | MetricName: VPCChanges 526 | -------------------------------------------------------------------------------- /07_cismetricfilters/url_for_cf.txt: -------------------------------------------------------------------------------- 1 | https://github.com/rewindio/aws-security-hub-CIS-metrics/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # awsmonitoringstrategies 2 | Scripts and other text provided as part of my AWS Monitoring Strategies course 3 | -------------------------------------------------------------------------------- /helpful_links.txt: -------------------------------------------------------------------------------- 1 | All services in AWS have their own documentation portal at https://aws.amazon/com/ 2 | Example for CloudWatch: 3 | https://aws.amazon.com/cloudwatch/ 4 | All other services mentioned have similar URLs 5 | 6 | Different ways of managing access control to S3: 7 | https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html 8 | https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html 9 | https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html 10 | https://aws.amazon.com/about-aws/whats-new/2018/11/introducing-amazon-s3-block-public-access/ 11 | 12 | CloudWatch support in AWS 13 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CW_Support_For_AWS.html 14 | 15 | CloudWatch Dashboards 16 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html 17 | https://aws.amazon.com/about-aws/whats-new/2018/11/amazon-cloudwatch-introduces-automatic-dashboards-to-monitor-all-aws-resources/ 18 | 19 | CloudWatch Agent install 20 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html 21 | 22 | Legacy Perl CloudWatch agent 23 | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/mon-scripts.html 24 | 25 | CloudWatch Agent automated install 26 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-on-first-instance.html 27 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-on-first-instance.html#CW-Agent-Instance-Create-Configuration-File-first 28 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/create-cloudwatch-agent-configuration-file-wizard.html 29 | 30 | Route 53 Failover 31 | https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-failover-configuring.html 32 | 33 | CloudWatch Logs 34 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html 35 | https://aws.amazon.com/blogs/aws/new-amazon-cloudwatch-logs-insights-fast-interactive-log-analytics/ 36 | 37 | CloudWatch Agent summary 38 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html 39 | 40 | CloudWatch Alarm details 41 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html 42 | 43 | CloudWatch metric filters 44 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html 45 | 46 | CloudWatch Events summary 47 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/WhatIsCloudWatchEvents.html 48 | 49 | CloudWatch Event types 50 | https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html 51 | 52 | CloudTrail unsupported services 53 | https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-unsupported-aws-services.html 54 | 55 | AWS Config summary 56 | https://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html 57 | 58 | AWS Config Rules 59 | https://docs.aws.amazon.com/config/latest/developerguide/managed-rules-by-aws-config.html 60 | 61 | VPC Flow Logs summary 62 | https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html 63 | 64 | SSM Features 65 | https://aws.amazon.com/systems-manager/features/ 66 | 67 | --------------------------------------------------------------------------------