Monitoring

Create SNS Topic and Subscription

This SNS topic and subscription will be used for all monitoring enabled in the next steps

aws sns create-topic --name monitoring-topic
aws sns subscribe \
--topic-arn <ARN_OF_TOPIC> \
--protocol email \
--notification-endpoint <admin@example.com>

<ARN_OF_TOPIC> and admin@example.com should be substituted with proper values before running the previous command. Note down the ARN of topic for future use

Ensure a log metric filter and alarm exist for unauthorized API calls

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name UnAuthorizedAPICalls \
--filter-pattern '{($.errorCode="*UnauthorizedOperation") || ($.errorCode="AccessDenied*")}' \
--metric-transformations metricName=UnAuthorizedAPICalls,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name UnAuthorizedAPICallsAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name UnAuthorizedAPICalls \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for Management Console sign-in without MFA

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name NoMFASignIn \
--filter-pattern '{($.eventName="ConsoleLogin") && ($.additionalEventData.MFAUsed !="Yes")}' \
--metric-transformations metricName=NoMFASignIn,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name NoMFASignInAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name NoMFASignIn \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for usage of "root" account

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name RootAccountUsage \
--filter-pattern '{$.userIdentity.type="Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType !="AwsServiceEvent"}' \
--metric-transformations metricName=RootAccountUsage,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name RootAccountUsageAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name RootAccountUsage \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for IAM policy changes

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name IAMPolicyChange \
--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)}' \
--metric-transformations metricName=IAMPolicyChange,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name IAMPolicyChangeAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name IAMPolicyChange \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for CloudTrail configuration changes

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name CloudTrailConfigChange \
--filter-pattern '{($.eventName=CreateTrail) || ($.eventName=UpdateTrail) || ($.eventName=DeleteTrail) || ($.eventName=StartLogging) || ($.eventName=StopLogging)}' \
--metric-transformations metricName=CloudTrailConfigChange,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name CloudTrailConfigChangeAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name CloudTrailConfigChange \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for AWS Management Console authentication failures

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name ConsoleAuthFailure \
--filter-pattern '{($.eventName=ConsoleLogin) && ($.errorMessage="Failed authentication")}' \
--metric-transformations metricName=ConsoleAuthFailure,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name ConsoleAuthFailureAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name ConsoleAuthFailure \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name DisableOrDeleteCMK \
--filter-pattern '{($.eventSource=kms.amazonaws.com) && (($.eventName=DisableKey) || ($.eventName=ScheduleKeyDeletion))}' \
--metric-transformations metricName=DisableOrDeleteCMK,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name DisableOrDeleteCMKAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name DisableOrDeleteCMK \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for S3 bucket policy changes

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name S3bucketPolicyChange \
--filter-pattern '{($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}' \
--metric-transformations metricName=S3bucketPolicyChange,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name S3bucketPolicyChangeAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name S3bucketPolicyChange \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for AWS Config configuration changes

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name AWSConfigChange \
--filter-pattern '{($.eventSource=config.amazonaws.com) && (($.eventName=StopConfigurationRecorder) || ($.eventName=DeleteDeliveryChannel) || ($.eventName=PutDeliveryChannel) || ($.eventName=PutConfigurationRecorder))}' \
--metric-transformations metricName=AWSConfigChange,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name AWSConfigChangeAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name AWSConfigChange \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for security group changes

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name SecurityGroupChange \
--filter-pattern '{($.eventName=AuthorizeSecurityGroupIngress) || ($.eventName=AuthorizeSecurityGroupEgress) || ($.eventName=RevokeSecurityGroupIngress) || ($.eventName=RevokeSecurityGroupEgress) || ($.eventName=CreateSecurityGroup) || ($.eventName=DeleteSecurityGroup)}' \
--metric-transformations metricName=SecurityGroupChange,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name SecurityGroupChangeAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name SecurityGroupChange \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL)

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name NACLChange \
--filter-pattern '{($.eventName=CreateNetworkAcl) || ($.eventName=CreateNetworkAclEntry) || ($.eventName=DeleteNetworkAcl) || ($.eventName=DeleteNetworkAclEntry) || ($.eventName=ReplaceNetworkAclEntry) || ($.eventName=ReplaceNetworkAclAssociation)}' \
--metric-transformations metricName=NACLChange,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name NACLChangeAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name NACLChange \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for changes to network gateways

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name NetworkGatewayChange \
--filter-pattern '{($.eventName=CreateCustomerGateway) || ($.eventName=DeleteCustomerGateway) || ($.eventName=AttachInternetGateway) || ($.eventName=CreateInternetGateway) || ($.eventName=DeleteInternetGateway) || ($.eventName=DetachInternetGateway)}' \
--metric-transformations metricName=NetworkGatewayChange,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name NetworkGatewayChangeAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name NetworkGatewayChange \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for route table changes

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name RouteTableChange \
--filter-pattern '{($.eventName=CreateRoute) || ($.eventName=CreateRouteTable) || ($.eventName=ReplaceRoute) || ($.eventName=ReplaceRouteTableAssociation) || ($.eventName=DeleteRouteTable) || ($.eventName=DeleteRoute) || ($.eventName=DisassociateRouteTable)}' \
--metric-transformations metricName=RouteTableChange,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name RouteTableChangeAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name RouteTableChange \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>

Ensure a log metric filter and alarm exist for VPC changes

Create Metric Filter

aws logs put-metric-filter \
--log-group-name <CloudTrail_Log_Group_Name> \
--filter-name VPCChange \
--filter-pattern '{($.eventName=CreateVpc) || ($.eventName=DeleteVpc) || ($.eventName=ModifyVpcAttribute) || ($.eventName=AcceptVpcPeeringConnection) || ($.eventName=CreateVpcPeeringConnection) || ($.eventName=DeleteVpcPeeringConnection) || ($.eventName=RejectVpcPeeringConnection) || ($.eventName=AttachClassicLinkVpc) || ($.eventName=DetachClassicLinkVpc) || ($.eventName=DisableVpcClassicLink) || ($.eventName=EnableVpcClassicLink)}' \
--metric-transformations metricName=VPCChange,metricNamespace=LogMetrics,metricValue=1

Create Alarm using above Metric

aws cloudwatch put-metric-alarm \
--alarm-name VPCChangeAlarm \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--metric-name VPCChange \
--namespace LogMetrics \
--period 300 \
--statistic Sum \
--threshold 1 \
--alarm-actions <ARN_OF_TOPIC>