# ------------------------------------------------------------------------------------------------- # CloudFormation Template 3 of 3 - Real Time Automated Remediation for CIS AWS Foundations Benchmark # # Provisions CloudWatch Logs Metric Filters for CIS Benchmarks # This template can be deployed independently of templates 1 and 2 for the CIS Benchmarks # # @author Kanishk Mahajan # --------------------------------------------------------------------------------------------------- AWSTemplateFormatVersion: 2010-09-09 Description: CIS AWS Foundations Benchmark Metric Alarms (qs-1t0eilb5g) Parameters: CloudTrailLogGroup: Description: Name of the CloudWatch Log group for CloudTrail Type: String Default: CloudTrail/DefaultLogGroup Resources: #=============================================================================================================================== # Pre-requisites Set up #=============================================================================================================================== # ------------------------------------------------------------------------------------------------------------------------------------ # CIS AWS Foundations Benchmark - 3.1 Ensure a log metric filter and alarm exist for unauthorized API calls # ------------------------------------------------------------------------------------------------------------------------------------ UnauthorizedApiCallsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-Unauthorized Activity Attempt AlarmDescription: Alarm if Multiple unauthorized actions or logins attempted MetricName: UnauthorizedAttemptCount Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: '1' Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold UnauthorizedApiCallsFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.errorCode = "*UnauthorizedOperation") || ($.errorCode = "AccessDenied*") } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: UnauthorizedAttemptCount # ------------------------------------------------------------------------------------------------------------------------------------ # CIS AWS Foundations Benchmark - 3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA # ------------------------------------------------------------------------------------------------------------------------------------ NoMfaConsoleLoginsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-Console Signin Without MFA AlarmDescription: Alarm if there is a Management Console sign-in without MFA MetricName: ConsoleSigninWithoutMFA Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold NoMfaConsoleLoginsFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventName = "ConsoleLogin") && ($.additionalEventData.MFAUsed != "Yes") } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: ConsoleSigninWithoutMFA # ------------------------------------------------------------------------------------------------------------------------------------ # CIS AWS Foundations Benchmark - 1.1 Avoid the use of the "root" account # CIS AWS Foundations Benchmark - 3.3 Ensure a log metric filter and alarm exist for usage of "root" account # ------------------------------------------------------------------------------------------------------------------------------------ RootAccountLoginsAlarm: Type: AWS::CloudWatch::Alarm DependsOn: - NoMfaConsoleLoginsAlarm Properties: AlarmName: CIS-Root Activity AlarmDescription: Alarm if a 'root' user uses the account MetricName: RootUserEventCount Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold RootAccountLoginsFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: RootUserEventCount # -------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.4 Ensure a log metric filter and alarm exist for IAM policy changes # -------------------------------------------------------------------------------------------------------------------------------------------- IAMPolicyChangesAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-IAM Policy Changes AlarmDescription: Alarm if an IAM policy changes MetricName: IAMPolicyChangeEventCount Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold IAMPolicyChangesFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.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) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: IAMPolicyChangeEventCount # -------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 1.20 Ensure a support role has been created to manage incidents with AWS Support # -------------------------------------------------------------------------------------------------------------------------------------------- CISSupportRole: Type: 'AWS::IAM::Role' Properties: RoleName: !Sub cissupportrole-${AWS::Region} AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Principal: AWS: 'Fn::Join': - '' - - 'arn:aws:iam::' - Ref: 'AWS::AccountId' - ':root' Action: - 'sts:AssumeRole' Path: / ManagedPolicyArns: - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AWSSupportAccess' # -------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes # -------------------------------------------------------------------------------------------------------------------------------------------- CloudtrailConfigChangesAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-Cloudtrail Config Changes AlarmDescription: Alarm if the configuration for Cloudtrail changes MetricName: CloudtrailConfigChangeEventCount Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold CloudtrailConfigChangesFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: CloudtrailConfigChangeEventCount # -------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures # -------------------------------------------------------------------------------------------------------------------------------------------- FailedConsoleLoginsAlarm: Type: AWS::CloudWatch::Alarm DependsOn: - RootAccountLoginsAlarm Properties: AlarmName: CIS-Console Login Failures AlarmDescription: Alarm if there are AWS Management Console authentication failures MetricName: ConsoleLoginFailures Namespace: LogMetrics Statistic: Sum Period: '300' EvaluationPeriods: '1' Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold FailedConsoleLoginsFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventName = ConsoleLogin) && ($.errorMessage = "Failed authentication") } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: ConsoleLoginFailures # ------------------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs # ------------------------------------------------------------------------------------------------------------------------------------------------------- DisabledOrDeletedCmksAlarm: Type: AWS::CloudWatch::Alarm DependsOn: - FailedConsoleLoginsAlarm Properties: AlarmName: CIS-KMS Key Disabled or Scheduled for Deletion AlarmDescription: Alarm if customer created CMKs get disabled or scheduled for deletion MetricName: KMSCustomerKeyDeletion Namespace: LogMetrics Statistic: Sum Period: 60 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold DisabledOrDeletedCmksFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventSource = kms.amazonaws.com) && (($.eventName=DisableKey) || ($.eventName=ScheduleKeyDeletion)) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: KMSCustomerKeyDeletion # ------------------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes # ------------------------------------------------------------------------------------------------------------------------------------------------------- S3BucketPolicyChangeAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-S3 Bucket Policy Changed AlarmDescription: Alarm if any S3 bucket policies are changed MetricName: S3BucketPolicyChanges Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold S3BucketPolicyChangeFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventSource = s3.amazonaws.com) && (($.eventName = PutBucketAcl) || ($.eventName = PutBucketPolicy) || ($.eventName = PutBucketCors) || ($.eventName = PutBucketLifecycle) || ($.eventName = PutBucketReplication) || ($.eventName = DeleteBucketPolicy) || ($.eventName = DeleteBucketCors) || ($.eventName = DeleteBucketLifecycle) || ($.eventName = DeleteBucketReplication)) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: S3BucketPolicyChanges # ------------------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes # ------------------------------------------------------------------------------------------------------------------------------------------------------- AWSConfigConfigurationChangeAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-AWS Config Configuration has changed AlarmDescription: Alarm if the configuration for AWS Config changes MetricName: AWSConfigConfigurationChanges Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold AWSConfigConfigurationChangeFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)|| ($.eventName=DeleteDeliveryChannel)|| ($.eventName=PutDeliveryChannel)|| ($.eventName=PutConfigurationRecorder)) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: AWSConfigConfigurationChanges # ------------------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.10 Ensure a log metric filter and alarm exist for security group changes # ------------------------------------------------------------------------------------------------------------------------------------------------------- SecurityGroupChangeAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-Security Groups Have Changed AlarmDescription: Alarm if there are any changes to security groups MetricName: SecurityGroupChanges Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold SecurityGroupChangeFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: SecurityGroupChanges # ------------------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists # ------------------------------------------------------------------------------------------------------------------------------------------------------- NACLChangeAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-NACLs Have Changed AlarmDescription: Alarm if there are any changes to Network ACLs (NACLs) MetricName: NACLChanges Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold NACLChangeFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: NACLChanges # ------------------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.12 Ensure a log metric filter and alarm exist for changes to network gateways # ------------------------------------------------------------------------------------------------------------------------------------------------------- NetworkGatewayChangeAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-Network Gateways Have Changed AlarmDescription: Alarm if there are any changes to network gateways MetricName: NetworkGatewayChanges Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold NetworkGatewayChangeFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: NetworkGatewayChanges # ------------------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.13 Ensure a log metric filter and alarm exist for route table changes # ------------------------------------------------------------------------------------------------------------------------------------------------------- RouteTableChangeAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-Route Tables Have Changed AlarmDescription: Alarm if there are any changes to route tables MetricName: RouteTableChanges Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold RouteTableChangeFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: RouteTableChanges # ------------------------------------------------------------------------------------------------------------------------------------------------------- # CIS AWS Foundations Benchmark - 3.14 Ensure a log metric filter and alarm exist for VPC changes # ------------------------------------------------------------------------------------------------------------------------------------------------------- VPCChangeAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: CIS-VPC Has Changed AlarmDescription: Alarm if there are any changes to any VPCs MetricName: VPCChanges Namespace: LogMetrics Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 1 TreatMissingData: notBreaching ComparisonOperator: GreaterThanOrEqualToThreshold VPCChangeFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref CloudTrailLogGroup FilterPattern: |- { ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) } MetricTransformations: - MetricValue: '1' MetricNamespace: LogMetrics MetricName: VPCChanges