「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ⑧S3バケットのサーバサイド暗号化

# はじめに

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

また、**AWS Security Hub** では、[**CIS AWS Foundations Standard**](https://docs.aws.amazon.com/ja_jp/securityhub/latest/userguide/securityhub-standards-cis.html) , [**Payment Card Industry Data Security Standard**](https://docs.aws.amazon.com/ja_jp/securityhub/latest/userguide/securityhub-standards-pcidss.html) , [**AWS Foundational Security Best Practices Standard**](https://docs.aws.amazon.com/ja_jp/securityhub/latest/userguide/securityhub-standards-fsbp.html) などのセキュリティ標準が公開されており、このガイドラインは、**AWSアカウントをセキュアに保つために必要なAWSのセキュリティ設定**を集めた**ベストプラクティス集**として活用できます。

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

+ [**aws-cloudformation-templates/security - GitHub**](https://github.com/eijikominami/aws-cloudformation-templates/blob/master/security/)

このCloudFormationテンプレートの実行はこちらから。

[![cloudformation-launch-stack](https://raw.githubusercontent.com/eijikominami/aws-cloudformation-templates/master/images/cloudformation-launch-stack.png)](https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/create/review?stackName=DefaultSecuritySettings&templateURL=https://eijikominami.s3-ap-northeast-1.amazonaws.com/aws-cloudformation-templates/security/template.yaml) 

![](https://raw.githubusercontent.com/eijikominami/aws-cloudformation-templates/master/images/architecture-default-security-settings.png)

# S3バケットのサーバサイド暗号化

``Amazon S3`` には、データ保管時にオブジェクトレベルで暗号化を行う **サーバサイド暗号化の機能が提供** されています。また、 ``Payment Card Industry Data Security Standard`` , ``AWS Foundational Security Best Practices Standard`` の各セキュリティ標準では、各S3バケットで この **サーバサイド暗号化を有効化** することを求めています。

| セキュリティ標準 | No. | 内容 |
| --- | --- | --- |
| Payment Card Industry Data Security Standard | PCI.S3.4 | **S3 バケットでは、サーバー側の暗号化を有効にする必要があります** |
| AWS Foundational Security Best Practices Standard | S3.4 | **S3 バケットでは、サーバー側の暗号化を有効にする必要があります** |

この規定に準拠するために、このCloudFormationテンプレートでは、以下の設定を行います。

1. **S3バケット** が上記のポリシーに準拠しているか **チェック** を行う
2. 非準拠であった場合には、`AWS Config` が `SSM Automation` を自動起動する
3. `SSM Automation` を用いて **S3 バケットのサーバーサイド暗号化を有効** にする

それぞれの設定について、順を追って説明します。

## 1. AWS Configの有効化

`AWS Config` を有効化する手順については、[過去の記事](https://qiita.com/eijikominami/items/53f3a1d83df31981ad86#aws-config) をご覧ください。

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

``AWS Config`` で使用する ``Service-Linked Role`` を作成します。この ``Service-Linked Role`` は、 **AWSリソースへの読み込み権限** と **S3への書き込み権限** を ``Config`` に、また、**IAMとSystemManagerへの書き込み権限** を ``Config Remediation`` にそれぞれ付与します。

```yaml
Resources:
  ServiceLinkedRoleForConfig:
    Type: AWS::IAM::ServiceLinkedRole
    UpdateReplacePolicy: Retain
    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
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Properties: 
      AWSServiceName: remediation.config.amazonaws.com 
      Description: A service-linked role required for AWS Config Remediation to access your resources.
```

### AWS Configの有効化

``AWS Config`` の ``DeliveryChannel`` と ``ConfigurationRecorder`` を作成します。

```yaml
Resources:
  ConfigDeliveryChannel:
    Type: AWS::Config::DeliveryChannel
    Properties:
      Name: default
      S3BucketName: !Ref S3ForConfig
  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`` **バケット**と、それに紐づく**バケットポリシー**を作成します。

```yaml
Resources:
  S3ForConfig:
    Type: 'AWS::S3::Bucket'
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration: 
          - ServerSideEncryptionByDefault: 
              SSEAlgorithm: AES256
      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
          - Effect: Deny
            Principal: '*'
            Action: 's3:*'
            Resource: 
              - !GetAtt S3ForConfig.Arn
              - !Join
                - ''
                - - !GetAtt S3ForConfig.Arn
                  - /*
            Condition:
              Bool: 
                aws:SecureTransport: false
```

## 2. AWS Configを用いたチェック

S3 バケットの設定でサーバーサイド暗号化が有効になっているかどうかの確認には、あらかじめ `AWS Config` に用意されている `S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED` マネージドルールを使用します。このマネージドルールのデフォルトのSSEアルゴリズムは、 [**AES256**](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/automation-aws-enableS3bucketencryption.html) です。また、 **[Origin Access Identity](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html) は、[SSE-S3（AES256）のみをサポート](https://aws.amazon.com/jp/blogs/networking-and-content-delivery/serving-sse-kms-encrypted-content-from-s3-using-cloudfront/) しています** 。このことから、 **S3バケットの暗号化方式は、SSE-S3（AES256）を選択しておくのが無難** です。

なお、この `Config Rule` を設定する前に `ConfigurationRecorder` を生成しておく必要があります。そこで、`DependsOn` 属性に `ConfigurationRecorder` リソースを設定しています。

```yaml
Resources:
  ConfigS3BucketServerSideEncryptionEnabled:
    DependsOn:
      - ConfigConfigurationRecorder
    Type: 'AWS::Config::ConfigRule'
    Properties:
      ConfigRuleName: s3-bucket-server-side-encryption-enabled
      Description: Amazon S3 バケットで Amazon S3 のデフォルトの暗号化が有効になっていること、または S3 バケットポリシーでサーバー側の暗号化なしの put-object リクエストを明示的に拒否することを確認します。 
      Source:
        Owner: AWS
        SourceIdentifier: S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED 
```

## 3. SSM Automation を用いた自動修復

``Systems Manager Automation`` は、``AWS Config`` で **直接指定できる、現時点で唯一の自動修復手段** となっています。そこで、S3バケットのサーバサイド暗号化を有効にする ``Systems Manager Automation`` **ドキュメント** を作成し、``AWS Config`` との紐付けを行います。

Systems Manager には、あらかじめ 定義済みの Automation ドキュメント が用意されており、``AWS-EnableS3BucketEncryption`` という名称の **定義済みドキュメント** を用いることで、 **S3バケットのサーバサイド暗号化を有効にする** ことができます。

また、この Automation ドキュメント の実行権限を指定する必要があるため、IAM Roleもあわせて作成しています。

```yaml
Resources:
  IAMRoleForSSM:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: ssm.amazonaws.com
            Action: 'sts:AssumeRole'
      Description: A role required for SSM to access IAM.
      Policies:
        - PolicyName: !Sub 'DefaultSecuritySettings-AWSSystemManagerIAMRole-${AWS::Region}'
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 's3:PutBucketEncryption'
                  - 's3:PutEncryptionConfiguration'
                Resource:
                  - '*'
      RoleName: !Sub 'DefaultSecuritySettings-SSM-${AWS::Region}'
  ConfigS3BucketServerSideEncryptionEnabledRemediationConfiguration:
    Condition: CreateRemediationResources
    Type: 'AWS::Config::RemediationConfiguration'
    Properties:
      Automatic: true
      ConfigRuleName: !Ref ConfigS3BucketServerSideEncryptionEnabled
      MaximumAutomaticAttempts: 1
      Parameters:
        AutomationAssumeRole:
          StaticValue:
            Values:
              - !GetAtt IAMRoleForSSM.Arn
        BucketName:
          ResourceValue:
            Value: RESOURCE_ID
      RetryAttemptSeconds: 30
      TargetId: AWS-EnableS3BucketEncryption
      TargetType: SSM_DOCUMENT
```

以上で、**AWSアカウントが所有する全てのS3バケットに対して** 、サーバサイド暗号化を有効にすることができました。

# 関連リンク
1. [**サービスの有効化** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/53f3a1d83df31981ad86)
2. [**パスワードポリシーの自動修復** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/85acced082d0dc8d9901)
3. [**モニタリングと通知の設定** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/1887d19ce3bb33f716ba)
4. [**アクセスキーのローテーションと削除** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/eba16015e8e27e42fc36)
5. [**全てのVPCでフローログを有効化する** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/e5f7fcc7fd91fc4355be)
6. [**SSHとRDPのアクセスを制限する** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/936912ee715079606e55)
7. [**デフォルトセキュリティグループを無効化する** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/2fa109f00b5c63686c42)
8. **S3バケットのサーバサイド暗号化** - セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート