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'