IAMパスワードポリシーの自動修復
CIS AWS Foundations Benchmark というセキュリティガイドラインが公開されており、このガイドラインは、AWSアカウントをセキュアに保つために必要なAWSのセキュリティ設定を集めたベストプラクティス集として活用できる。
この CIS AWS Foundations Benchmark
では、CloudTrailによって検知された特定のイベントに対して以下のような対応を求めている。
- 3.1 不正な API 呼び出しに対してログメトリクスフィルタとアラームが存在することを確認します
- 3.2 MFA なしの AWS マネジメントコンソール サインインに対してログメトリクスフィルタとアラームが存在することを確認します
- 3.3 「ルート」アカウントに対してログメトリクスフィルタとアラームが存在することを確認します
- 3.4 MFA なしの IAM ポリシーの変更に対してログメトリクスフィルタとアラームが存在することを確認します
- 3.5 MFA なしの CloudTrail 設定の変更に対してログメトリクスフィルタとアラームが存在することを確認します
- 3.6 AWS マネジメントコンソール 認証の失敗に対してログメトリクスフィルタとアラームが存在することを確認します
- 3.7 カスタマー作成の CMK の無効化またはスケジュールされた削除に対してログメトリクスフィルタとアラームが存在することを確認します
- 3.8 S3 バケットの変更に対してログメトリクスフィルタとアラームが存在することを確認します
- 3.9 AWS Config 設定の変更に対してログメトリクスフィルタとアラームが存在することを確認します
- 3.10 セキュリティグループの変更に対するメトリクスフィルタとアラームが存在することを確認します
- 3.11 ネットワークアクセスコントロールリスト (NACL) への変更に対するログメトリクスとアラームが存在することを確認します
- 3.12 ネットワークゲートウェイへの変更に対するログメトリクスとアラームが存在することを確認します
- 3.13 ルートテーブルの変更に対してログメトリクスフィルタとアラームが存在することを確認します
- 3.14 VPC の変更に対してログメトリクスフィルタとアラームが存在することを確認します
上述のログメトリクスフィルタとアラームを設定し、CIS AWS Foundations Benchmark
に 準拠するために以下の設定を行う。
- CloudWatch Logs の MetricFilter を作成する
- 上のメトリクスに対する CloudWatch Alarm を作成する
- 閾値を超えた場合にAmazon SNSに通知を送る
Resources:
# CIS 3.1 a log metric filter and alarm exist for unauthorized API calls
CloudWatchLogsMetricFilterCloudTrailUnauthorizedAPICalls:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.errorCode="*UnauthorizedOperation") || ($.errorCode="AccessDenied*")}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: UnauthorizedAPICalls
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailUnauthorizedAPICalls:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *不正なAPIコールを検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-Unauthorized-API-Calls'
ComparisonOperator: GreaterThanOrEqualToThreshold
DatapointsToAlarm: 6
EvaluationPeriods: 60
MetricName: UnauthorizedAPICalls
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.2 a log metric filter and alarm exist for AWS Management Console sign-in without MFA
CloudWatchLogsMetricFilterCloudTrailLoginWithoutMFA:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName="ConsoleLogin") && ($.additionalEventData.MFAUsed !="Yes")}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: LoginWithoutMFA
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailLoginWithoutMFA:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *MFAなしのログインを検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-Login-Without-MFA'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: LoginWithoutMFA
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.3 a log metric filter and alarm exist for usage of "root" account
CloudWatchLogsMetricFilterCloudTrailForRootAcount:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{$.userIdentity.type="Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType !="AwsServiceEvent"}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: ForRootAcount
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailForRootAcount:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *ルートアカウントに対する変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-For-RootAcount'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: ForRootAcount
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.4 a log metric filter and alarm exist for IAM policy changes
CloudWatchLogsMetricFilterCloudTrailIamPolicyChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
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)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: IamPolicyChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailIamPolicyChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *IAMポリシーの変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-IamPolicy-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: IamPolicyChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.5 a log metric filter and alarm exist for CloudTrail configuration changes
CloudWatchLogsMetricFilterCloudTrailCloudTrailConfigurationChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateTrail) || ($.eventName=UpdateTrail) || ($.eventName=DeleteTrail) || ($.eventName=StartLogging) || ($.eventName=StopLogging)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: CloudTrailConfigurationChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailCloudTrailConfigurationChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *CloudTrailの設定変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-CloudTrailConfiguration-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: CloudTrailConfigurationChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.6 a log metric filter and alarm exist for AWS Management Console authentication failures
CloudWatchLogsMetricFilterCloudTrailAuthenticationFailuresDetected:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=ConsoleLogin) && ($.errorMessage="Failed authentication")}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: AuthenticationFailuresDetected
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailAuthenticationFailuresDetected:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *ログイン認証失敗を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-AuthenticationFailures-Detected'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: AuthenticationFailuresDetected
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.7 a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs
CloudWatchLogsMetricFilterCloudTrailCustomerCreatedCMKsChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventSource=kms.amazonaws.com) && (($.eventName=DisableKey) || ($.eventName=ScheduleKeyDeletion))}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: CustomerCreatedCMKsChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailCustomerCreatedCMKsChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *カスタマー作成CMKの無効化もしくは削除を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-CustomerCreatedCMKs-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: CustomerCreatedCMKsChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.8 a log metric filter and alarm exist for S3 bucket policy changes
CloudWatchLogsMetricFilterCloudTrailS3BucketPolicyChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: S3BucketPolicyChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailS3BucketPolicyChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *S3のバケットポリシーの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-S3BucketPolicy-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: S3BucketPolicyChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.9 a log metric filter and alarm exist for AWS Config configuration changes
CloudWatchLogsMetricFilterCloudTrailConfigConfigurationChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventSource=config.amazonaws.com) && (($.eventName=StopConfigurationRecorder) || ($.eventName=DeleteDeliveryChannel) || ($.eventName=PutDeliveryChannel) || ($.eventName=PutConfigurationRecorder))}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: ConfigConfigurationChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailConfigConfigurationChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *Configの設定変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-ConfigConfiguration-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: ConfigConfigurationChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.10 a log metric filter and alarm exist for changes to Security Group
CloudWatchLogsMetricFilterCloudTrailSecurityGroupChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=AuthorizeSecurityGroupIngress) || ($.eventName=AuthorizeSecurityGroupEgress) || ($.eventName=RevokeSecurityGroupIngress) || ($.eventName=RevokeSecurityGroupEgress) || ($.eventName=CreateSecurityGroup) || ($.eventName=DeleteSecurityGroup)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: SecurityGroupChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailSecurityGroupChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *セキュリティグループの変更を検知* しました。'
AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-SecurityGroup-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: SecurityGroupChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.11 a log metric filter and alarm exist for changes to Network Access Control Lists (NACL)
CloudWatchLogsMetricFilterCloudTrailNACLChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateNetworkAcl) || ($.eventName=CreateNetworkAclEntry) || ($.eventName=DeleteNetworkAcl) || ($.eventName=DeleteNetworkAclEntry) || ($.eventName=ReplaceNetworkAclEntry) || ($.eventName=ReplaceNetworkAclAssociation)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: NACLChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailNACLChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *NACLの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-NACL-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: NACLChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.12 a log metric filter and alarm exist for changes to network gateways
CloudWatchLogsMetricFilterCloudTrailNetworkGatewayChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateCustomerGateway) || ($.eventName=DeleteCustomerGateway) || ($.eventName=AttachInternetGateway) || ($.eventName=CreateInternetGateway) || ($.eventName=DeleteInternetGateway) || ($.eventName=DetachInternetGateway)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: NetworkGatewayChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailNetworkGatewayChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *ネットワークゲートウェイの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-NetworkGateway-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: NetworkGatewayChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.13 a log metric filter and alarm exist for route table changes
CloudWatchLogsMetricFilterCloudTrailRouteTableChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateRoute) || ($.eventName=CreateRouteTable) || ($.eventName=ReplaceRoute) || ($.eventName=ReplaceRouteTableAssociation) || ($.eventName=DeleteRouteTable) || ($.eventName=DeleteRoute) || ($.eventName=DisassociateRouteTable)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: RouteTableChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailRouteTableChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *ルートテーブルの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-RouteTable-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: RouteTableChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
# CIS 3.14 a log metric filter and alarm exist for VPC changes
CloudWatchLogsMetricFilterCloudTrailVpcChanges:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '{($.eventName=CreateVpc) || ($.eventName=DeleteVpc) || ($.eventName=ModifyVpcAttribute) || ($.eventName=AcceptVpcPeeringConnection) || ($.eventName=CreateVpcPeeringConnection) || ($.eventName=DeleteVpcPeeringConnection) || ($.eventName=RejectVpcPeeringConnection) || ($.eventName=AttachClassicLinkVpc) || ($.eventName=DetachClassicLinkVpc) || ($.eventName=DisableVpcClassicLink) || ($.eventName=EnableVpcClassicLink)}'
LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail
MetricTransformations:
- MetricName: VpcChanges
MetricNamespace: LogMetrics
MetricValue: '1'
CloudWatchAlarmMetricFilterCloudTrailVpcChanges:
Type: 'AWS::CloudWatch::Alarm'
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref SnsTopicARN
AlarmDescription: '*CloudTrail* が *VPCの変更を検知* しました。'
AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-Vpc-Changes'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: VpcChanges
Namespace: LogMetrics
OKActions:
- !Ref SnsTopicARN
Period: 60
Statistic: Maximum
Threshold: 1
TreatMissingData: notBreaching
また、これらのメトリクスのアラーム通知先となる、Amazon SNS
と Topic Policy
を作成する。
Resources:
SNSAlert:
Type: 'AWS::SNS::Topic'
Properties:
DisplayName: !Sub 'System Notifications from ${AWS::StackName}'
TopicName: !Sub '${AWS::StackName}-system-notifications'
SNSAlertTopicPolicy:
Type: 'AWS::SNS::TopicPolicy'
Properties:
Topics:
- !Ref SNSAlert
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
# All AWS Services
Principal:
AWS: '*'
Resource: '*'
Action: 'SNS:Publish'