0

「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ①サービスの有効化

はじめに

AWSにはアカウントやリソースへの脅威検知に対応した、AWS Security Hub, Amazon Inspector, Amazon GuardDuty, AWS CloudTrail, AWS Config などのサービスが用意されています。

また、CIS AWS Foundations Benchmark というセキュリティガイドラインが公開されており、このガイドラインは、AWSアカウントをセキュアに保つために必要なAWSのセキュリティ設定を集めたベストプラクティス集として活用できます。自身のAWSアカウントがこのガイドラインにどの程度準拠しているのかを確認/監査する手段として、AWS Security Hubで、CIS AWS Foundations Standardという機能が提供されています。

本記事では、アカウントやリソースへの脅威検知が可能なAWSサービスを有効化するとともに、CIS AWS Foundations Benchmarkを指標とし、このガイドラインに限りなく準拠することで、セキュアで堅牢なAWSアカウントを実現します。また、これらをお手軽に実現できるCloudFormationテンプレートを公開しています。

TL;DR

以下のCloudFormationテンプレートを実行することで、セキュアで堅牢なAWSアカウントをお手軽に実現します。下にあるボタンをクリックすると、自身のAWSアカウントでCloudFormationテンプレートを実行することが可能となります。

cloudformation-launch-stack

作成されるAWSリソースとそのアーキテクチャ図はこちら。

図の下半分のsecurityと書かれた部分が、CloudFormationによって自動的に作成されます。なお、このCloudFormationテンプレートは、Nested Stackの構成となっており、下記のAWSサービスを単体で作成することも可能です。

作成されるAWSサービス 個別のCloudFormationテンプレート
AWS Security Hub cloudformation-launch-stack
Amazon Inspector cloudformation-launch-stack
Amazon GuardDuty cloudformation-launch-stack
AWS CloudTrail cloudformation-launch-stack
AWS Config cloudformation-launch-stack

このテンプレートは、Center for Internet Security (CIS) ベンチマークの以下の項目に準拠します。現時点では全ての項目には対応できていませんが、今後対応範囲を順次増やして、CIS AWS Foundations Benchmarkへの準拠の度合いを増やしていく予定です。

No. ルール 実行内容
1.3 90 日間以上使用されていない認証情報は無効にします Config で定期的に確認を行い、非準拠の場合は Lambda で自動的に削除します。
1.4 アクセスキーは 90 日ごとに更新します Config で定期的に確認を行い、非準拠の場合は Lambda で自動的に削除します。
1.5 IAM パスワードポリシーには少なくとも 1 つの大文字が必要です Config で定期的に確認を行い、非準拠の場合は SSM Automation で自動修復を行います。
1.6 IAM パスワードポリシーには少なくとも 1 つの小文字が必要です Config で定期的に確認を行い、非準拠の場合は SSM Automation で自動修復を行います。
1.7 IAM パスワードポリシーには少なくとも 1 つの記号が必要です Config で定期的に確認を行い、非準拠の場合は SSM Automation で自動修復を行います。
1.8 IAM パスワードポリシーには少なくとも 1 つの数字が必要です Config で定期的に確認を行い、非準拠の場合は SSM Automation で自動修復を行います。
1.9 IAM パスワードポリシーは 14 文字以上の長さが必要です Config で定期的に確認を行い、非準拠の場合は SSM Automation で自動修復を行います。
1.10 IAM パスワードポリシーはパスワードの再使用を禁止しています Config で定期的に確認を行い、非準拠の場合は SSM Automation で自動修復を行います。
1.12 ルートアカウントキーが存在しないことを確認します Config で定期的に確認を行い、非準拠の場合は SSM Automation で自動修復を行います。
2.1 CloudTrail はすべてのリージョンで有効になっています CloudTrail と関連サービスを有効化します。
2.2 CloudTrail ログファイルの検証は有効になっています CloudTrail と関連サービスを有効化します。
2.3 CloudTrail が記録する S3 バケットはパブリックアクセスできません CloudTrail と関連サービスを有効化します。
2.4 CloudTrail 証跡は Amazon CloudWatch Logs によって統合されています CloudTrail と関連サービスを有効化します。
2.5 すべてのリージョンで AWS Config が有効になっていることを確認します Config と関連サービスを有効化します。
2.6 S3 バケットアクセスログ記録が CloudTrail S3 バケットで有効になっていることを確認します CloudTrail と関連サービスを有効化します。
2.7 CloudTrail ログは保管時に AWS KMS CMK を使用して暗号化されていることを確認します CloudTrail と関連サービスを有効化します。
2.9 すべての VPC で VPC フローログ記録が有効になっていることを確認します Config で定期的に確認を行い、非準拠の場合は SSM Automation で自動修復を行います。
3.1 不正な API 呼び出しに対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.2 MFA なしの AWS マネジメントコンソール サインインに対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.3 ルート」アカウントに対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.4 MFA なしの IAM ポリシーの変更に対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.5 MFA なしの CloudTrail 設定の変更に対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.6 AWS マネジメントコンソール 認証の失敗に対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.7 カスタマー作成の CMK の無効化またはスケジュールされた削除に対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.8 S3 バケットの変更に対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.9 AWS Config 設定の変更に対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.10 セキュリティグループの変更に対するメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.11 ネットワークアクセスコントロールリスト (NACL) への変更に対するログメトリクスとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.12 ネットワークゲートウェイへの変更に対するログメトリクスとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.13 ルートテーブルの変更に対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。
3.14 VPC の変更に対してログメトリクスフィルタとアラームが存在することを確認します ログメトリクスフィルタとCloudWatchアラームを作成します。

アーキテクチャ

このテンプレートの設定内容は以下の通りです。なお、以下のYAMLコードは、aws-cloudformation-templates/security - GitHubで公開しているCloudFormationテンプレートから、本記事用に一部抜粋したものです。本記事作成用に一部改変を行なっていること、またリポジトリの最新のコードを常に反映している訳ではないことをご了承ください。詳細は、GitHubの該当リポジトリをご覧ください。

AWS Security Hub

サービスにリンクされたロールを作成

AWS Security Hub で使用する Service-Linked Role を作成します。

Resources:
  ServiceLinkedRoleForSecurityHub:
    Type: AWS::IAM::ServiceLinkedRole
    DeletionPolicy: Retain
    Properties: 
      AWSServiceName: securityhub.amazonaws.com
      Description: A service-linked role required for AWS Security Hub to access your resources.

AWS Security Hub を有効化

AWS Security Hubを有効化します。

Resources:
  SecurityHub:
    DependsOn:
      - ServiceLinkedRoleForSecurityHub
    Type: AWS::SecurityHub::Hub

CloudWatch Events を設定

Security Hub は、すべての結果をイベントとして自動的に CloudWatch Events に送信します。これでは、CIS AWS Foundations Benchmarkに準拠している状態でも非準拠の場合でも、全ての結果が CloudWatch Events に送信されてしまうので、そのうち 準拠から非準拠となった状態のイベントのみを受信して、 Amazon SNS に送信します。

Resources:
  CloudWatchEventsForSecurityHub:
    Type: AWS::Events::Rule
    Properties: 
      Description: CloudWatch Events about SecurityHub.
      EventPattern:
        source:
          - aws.securityhub
        detail-type: 
          - Security Hub Findings - Imported
        detail:
          findings:
            Compliance:
              Status:
                - PASSED
            RecordState:
              - ARCHIVED
      Name: AWS_Security_Hub
      State: ENABLED
      Targets:
        - Arn: !Ref SnsTopicARN
          Id: CloudWatchEventsForSecurityHub

Amazon Inspector

サービスにリンクされたロール と IAMロールの作成

Amazon Inspector で使用する Service-Linked RoleIAM Roleを作成します。

Resources:
  ServiceLinkedRoleForInspector:
    Type: AWS::IAM::ServiceLinkedRole
    DeletionPolicy: Retain
    Properties: 
      AWSServiceName: inspector.amazonaws.com
      Description: A service-linked role required for Amazon Inspector to access your resources.   
  IAMRoleForInspectorEvents:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: 'sts:AssumeRole'
      Description: A role required for CloudWatch Events to access Inspector.
      Policies:
        - PolicyName: !Sub 'DefaultSecuritySettings-AWSEventsInspectorPolicy-${AWS::Region}'
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 'inspector:StartAssessmentRun'
                Resource: '*'
      RoleName: !Sub 'DefaultSecuritySettings-InspectorEvents-${AWS::Region}'

Amazon Inspectorの有効化

Amazon InspectorAssessment TargetAssessment Template を作成します。

本テンプレートは、上記の4つのルールパッケージに対応します。なお、AWSが公開しているルールパッケージのURLがリージョンごとに異なることから、本テンプレートは、Amazon Inspector に対応しているリージョンのうち、一部のリージョンのみに対応していることにご注意ください。

Resources:
  InspectorAssessmentTarget:
    DependsOn:
      - ServiceLinkedRoleForInspector
    Type: AWS::Inspector::AssessmentTarget
    Properties:
      AssessmentTargetName: DefaultSecuritySettings-Assessment-Target-All-Instances-All-Rules
  InspectorAssessmentTemplate:
    Type: AWS::Inspector::AssessmentTemplate
    Properties:
      AssessmentTargetArn: !GetAtt InspectorAssessmentTarget.Arn
      DurationInSeconds: 3600
      AssessmentTemplateName: DefaultSecuritySettings-Assessment-Template-Default-All-Rules
      RulesPackageArns:
        # Asia Pacific (Tokyo)リージョンの場合
        - arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-gHP9oWNT
        - arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu
        - arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-YI95DVd7
        - arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-bBUQnxMq

CloudWatch Events を設定

Amazon Inspector は、CloudWatch Eventsを用いてAssessment Templateを定期実行することができます。本テンプレートでは毎週月曜日午前9時になると、CloudWatch EventsAmazon Inspectorを定期実行します。

Resources:
  CloudWatchEventsForInspector:
    Type: AWS::Events::Rule
    Properties: 
      Description: !Join
        - ''
        - - Scheduled Inspector Assessment for 
          - !GetAtt InspectorAssessmentTemplate.Arn
          - running every 7 day(s)
      Name: Amazon_Inspector_Assessment
      # Every Monday 9AM
      ScheduleExpression: cron(0 9 ? * 1 *)
      State: ENABLED
      Targets:
        - Arn: !GetAtt InspectorAssessmentTemplate.Arn
          Id: CloudWatchEventsForInspector
          RoleArn: !GetAtt IAMRoleForInspectorEvents.Arn

Amazon GuardDuty

サービスにリンクされたロール の作成

Amazon GuardDuty で使用する Service-Linked Role を作成します。

Resources:
  # Service-linked Role
  ServiceLinkedRoleForGuardDuty:
    Type: AWS::IAM::ServiceLinkedRole
    DeletionPolicy: Retain
    Properties: 
      AWSServiceName: guardduty.amazonaws.com
      Description: A service-linked role required for Amazon GuardDuty to access your resources.

Amazon GuardDuty を有効化

Amazon GuardDutyを有効化します。

Resources:
  GuardDutyDetector:
    DependsOn:
      - ServiceLinkedRoleForGuardDuty
    Type: AWS::GuardDuty::Detector
    Properties:
      Enable: true

AWS CloudTrail

IAMロールの作成

AWS CloudTrail で使用する IAM Roleを作成します。

Resources:
  IAMRoleForCloudTrail:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudtrail.amazonaws.com
            Action: 'sts:AssumeRole'
      Description: A role required for CloudTrail to access CloudWatch Logs.
      Policies:
        - PolicyName: !Sub 'DefaultSecuritySettings-AWSCloudTrailCloudWatchLogsPolicy-${AWS::Region}'
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:PutLogEvents'
                  - 'logs:CreateLogStream'
                Resource:
                  - !GetAtt CloudWatchLogsGroupForCloudTrail.Arn
      RoleName: !Sub 'DefaultSecuritySettings-CloudTrail-${AWS::Region}'

AWS CloudTrail を有効化

AWS CloudTrailを有効化します。

Resources:
  CloudTrail:
    DependsOn:
      - S3BucketPolicyForCloudTrail
    Condition: CreateCentralizedResources
    Type: AWS::CloudTrail::Trail
    Properties:
      CloudWatchLogsLogGroupArn: !GetAtt CloudWatchLogsGroupForCloudTrail.Arn
      CloudWatchLogsRoleArn: !GetAtt IAMRoleForCloudTrail.Arn
      EnableLogFileValidation: true
      EventSelectors:
        - DataResources: 
            # All S3 buckets
            - Type: AWS::S3::Object
              Values: 
                - arn:aws:s3
            # All Lambda functions.
            - Type: AWS::Lambda::Function
              Values: 
                - arn:aws:lambda
      IncludeGlobalServiceEvents: true
      IsLogging: true
      IsMultiRegionTrail: true
      S3BucketName: !Ref S3ForCloudTrail
      SnsTopicName: !Ref SnsTopicName
      TrailName: DefaultSecuritySettings

Amazon S3 バケットを作成

イベントログファイルを蓄積するために使用する、Amazon S3 バケットと、それに紐づくバケットポリシーを作成します。

Resources:
  S3ForCloudTrail:
    Type: 'AWS::S3::Bucket'
    DeletionPolicy: Retain
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration: 
          - ServerSideEncryptionByDefault: 
              SSEAlgorithm: aws:kms
      BucketName: !Sub defaultsecuritysettings-cloudtrail-${AWS::Region}-${AWS::AccountId}
      LifecycleConfiguration:
        Rules:
          - Id: ExpirationInDays
            ExpirationInDays: 60
            Status: Enabled
      LoggingConfiguration:
        DestinationBucketName: !Ref LogBacketName
        LogFilePrefix: CloudTrail/
      PublicAccessBlockConfiguration: 
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
  S3BucketPolicyForCloudTrail:
    Type: AWS::S3::BucketPolicy
    Properties: 
      Bucket: !Ref S3ForCloudTrail
      PolicyDocument:
        Version: 2012-10-17
        Id: !Ref S3ForCloudTrail
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudtrail.amazonaws.com
            Action:
              - 's3:GetBucketAcl'
            Resource:
              - !GetAtt S3ForCloudTrail.Arn
          - Effect: Allow
            Principal:
              Service: cloudtrail.amazonaws.com
            Action:
              - 's3:PutObject'
            Resource:
              - !Join
                - ''
                - - !GetAtt S3ForCloudTrail.Arn
                  - /AWSLogs/
                  - !Sub ${AWS::AccountId}
                  - /*
            Condition:
              StringEquals:
                s3:x-amz-acl: bucket-owner-full-control

CloudWatch Logs のロググループを作成

イベントログファイルを蓄積するために使用する、ロググループを作成します。

Resources:
  CloudWatchLogsGroupForCloudTrail:
    Type: 'AWS::Logs::LogGroup'
    Properties:
      LogGroupName: /aws/cloudtrail/DefaultSecuritySettings
      RetentionInDays: 365

AWS Config

サービスにリンクされたロール と IAMロールの作成

AWS Config で使用する Service-Linked RoleIAM Roleを作成します。

Resources:
  ServiceLinkedRoleForConfig:
    Type: AWS::IAM::ServiceLinkedRole
    DeletionPolicy: Retain
    Properties: 
      AWSServiceName: config.amazonaws.com
      Description: A service-linked role required for AWS Config to access your resources.
  ServiceLinkedRoleForConfigRemediation:
    Type: AWS::IAM::ServiceLinkedRole
    DeletionPolicy: Retain
    Properties: 
      AWSServiceName: remediation.config.amazonaws.com 
      Description: A service-linked role required for AWS Config Remediation to access your resources.
  IAMRoleForConfig:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: config.amazonaws.com
            Action: 'sts:AssumeRole'
      Description: A role required for Config to access CloudFormation and ReadOnlyAccess.
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AWSCloudFormationReadOnlyAccess
        - arn:aws:iam::aws:policy/ReadOnlyAccess
      Policies:
        - PolicyName: !Sub 'DefaultSecuritySettings-AWSConfigCloudFormationPolicy-${AWS::Region}'
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 'cloudformation:DetectStackDrift'
                  - 'cloudformation:DetectStackResourceDrift'
                Resource:
                  - '*'
      RoleName: !Sub 'DefaultSecuritySettings-Config-${AWS::Region}'

AWS Configの有効化

AWS ConfigDeliveryChannelConfigurationRecorder を作成します。

Resources:
  ConfigDeliveryChannel:
    Type: AWS::Config::DeliveryChannel
    Properties:
      Name: default
      S3BucketName: !Ref S3ForConfig
      SnsTopicARN: !Ref SnsTopicARN
  ConfigConfigurationRecorder:
    Type: AWS::Config::ConfigurationRecorder
    Properties:
      Name: default
      RecordingGroup:
        AllSupported: true
        IncludeGlobalResourceTypes: true
      RoleARN: !Sub arn:aws:iam::DefaultSecuritySettings:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig

Amazon S3 バケットを作成

設定情報 (履歴ファイルやスナップショット)するために使用する、Amazon S3 バケットと、それに紐づくバケットポリシーを作成します。

Resources:
  S3ForConfig:
    Type: 'AWS::S3::Bucket'
    DeletionPolicy: Retain
    Properties:
      BucketName: !Sub defaultsecuritysettings-config-${AWS::Region}-${AWS::AccountId}
      LifecycleConfiguration:
        Rules:
          - Id: ExpirationInDays
            ExpirationInDays: 60
            Status: Enabled
      PublicAccessBlockConfiguration: 
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
  S3BucketPolicyForConfig:
    Type: AWS::S3::BucketPolicy
    Properties: 
      Bucket: !Ref S3ForConfig
      PolicyDocument:
        Version: 2012-10-17
        Id: !Ref S3ForConfig
        Statement:
          - Effect: Allow
            Principal:
              Service: config.amazonaws.com
            Action:
              - 's3:GetBucketAcl'
              - 's3:ListBucket'
            Resource:
              - !GetAtt S3ForConfig.Arn
          - Effect: Allow
            Principal:
              Service: config.amazonaws.com
            Action:
              - 's3:PutObject'
            Resource:
              - !Join
                - ''
                - - !GetAtt S3ForConfig.Arn
                  - /AWSLogs/
                  - !Sub ${AWS::AccountId}
                  - /Config/*
            Condition:
              StringEquals:
                s3:x-amz-acl: bucket-owner-full-control

以上で、AWS Security Hub, Amazon Inspector, Amazon GuardDuty, AWS CloudTrail, AWS Config の5つのサービスを有効化することができました。次回は、CIS AWS Foundations Benchmarkの各項目へ準拠するための設定と、その設定を自動的に作成する CloudFormation テンプレートについて説明します。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away