「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ②パスワードポリシーの自動修復

# はじめに

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)

# IAMパスワードポリシーの自動修復

``CIS AWS Foundations Benchmark``では、IAMユーザ用のパスワードポリシーについて、以下の設定とすることが奨励されています。

+ **1.5 IAM パスワードポリシーには少なくとも 1 つの大文字が必要です**
+ **1.6 IAM パスワードポリシーには少なくとも 1 つの小文字が必要です**
+ **1.7 IAM パスワードポリシーには少なくとも 1 つの記号が必要です**
+ **1.8 IAM パスワードポリシーには少なくとも 1 つの数字が必要です**
+ **1.9 IAM パスワードポリシーは 14 文字以上の長さが必要です**
+ **1.10 IAM パスワードポリシーはパスワードの再使用を禁止しています**

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

1. 上記のポリシーに準拠しているか ``AWS Config`` を用いて**定期的にチェック**を行う
2. 非準拠であった場合には、``AWS Config`` が ``SSM Automation``を**自動起動**する
3. ``SSM Automation`` が**正しいIAMパスワードポリシー**となるように設定を**自動修復**する

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

## 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:
      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を用いた定期チェック

IAM パスワードポリシー設定のチェックには、あらかじめ``AWS Config``に用意されている　``IAM_PASSWORD_POLICY`` マネージドルールを使用します。``CIS AWS Foundations Benchmark`` で奨励されているパスワードポリシーの値は、マネージドルール内の **InputParameters** で設定します。IAM パスワードポリシーがこの条件を満たしていなかった場合、このリソースはルールに **非準拠（NON_COMPLIANT）** であると判定されます。

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

```yaml
Resources:
  ConfigIamPasswordPolicy:
    DependsOn:
      - ConfigConfigurationRecorder
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: iam-password-policy
      Description: IAM ユーザーのアカウントパスワードポリシーが、指定した要件を満たしているかどうかを確認します。
      InputParameters:
        RequireUppercaseCharacters: true
        RequireLowercaseCharacters: true
        RequireSymbols: true
        RequireNumbers: true
        MinimumPasswordLength: 14
        PasswordReusePrevention: 24
      Source:
        Owner: AWS
        SourceIdentifier: IAM_PASSWORD_POLICY
```

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

``Systems Manager Automation`` は、``AWS Config`` で **直接指定できる、現時点で唯一の自動修復手段** となっています。そこで、IAM パスワードポリシー を修復する ``Systems Manager Automation`` **ドキュメント** を作成し、``AWS Config`` との紐付けを行います。

下の``Systems Manager Automation`` ドキュメントは、``IAM`` の ``UpdateAccountPasswordPolicy`` を実行して、IAM パスワードポリシーの設定を自動修復します。

```yaml
Resources:
  SSMAutomationUpdateAccountPasswordPolicy:
    Type: AWS::SSM::Document
    Properties: 
      Content:
        schemaVersion: "0.3"
        assumeRole: "{{ AutomationAssumeRole }}"
        description: Update account password policy.
        mainSteps:
          - name: UpdateAccountPasswordPolicy
            action: aws:executeAwsApi
            inputs:
              Service: iam
              Api: UpdateAccountPasswordPolicy
              AllowUsersToChangePassword: true
              HardExpiry: false
              MinimumPasswordLength: 14
              PasswordReusePrevention: 24
              RequireLowercaseCharacters: true
              RequireNumbers: true
              RequireSymbols: true
              RequireUppercaseCharacters: true
        parameters:
          AutomationAssumeRole:
            type: String
            description: Automation Assume Role Arn
      DocumentType: Automation
```

## 4. AWS Config と SSM Automation の紐付け

``Systems Manager Automation`` ドキュメントは、上述の通り ``IAM`` の ``UpdateAccountPasswordPolicy`` を実行する必要があるため、このAWS API アクションを ``Systems Manager 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:
                  - 'iam:UpdateAccountPasswordPolicy'
                Resource:
                  - '*'
      RoleName: !Sub 'DefaultSecuritySettings-SSM-${AWS::Region}'
```

このIAM RoleのARNは、``AWS Config`` から ``Systems Manager Automation`` へ渡されるパラメータの1つとして規定されます。 ``AWS::Config::RemediationConfiguration`` は、**非準拠（NON_COMPLIANT）と判定された場合の自動修復方法を規定**し、``Config Rule`` と ``Systems Manager Automation`` との紐付けや、受け渡されるパラメータの規定を行います。自動修復を行う場合は、**AutomationAssumeRole, MaximumAutomaticAttempts, RetryAttemptSeconds** の各パラメータの入力が必須です。

```yaml
Resources:
  ConfigIamPasswordPolicyRemediationConfiguration:
    Type: AWS::Config::RemediationConfiguration
    Properties:
      Automatic: true
      ConfigRuleName: !Ref ConfigIamPasswordPolicy
      MaximumAutomaticAttempts: 1
      Parameters:
        AutomationAssumeRole:
          StaticValue:
            Values:
              - !GetAtt IAMRoleForSSM.Arn
      RetryAttemptSeconds: 60
      TargetId: !Ref SSMAutomationUpdateAccountPasswordPolicy
      TargetType: SSM_DOCUMENT
```

以上で、``CIS AWS Foundations Benchmark`` に準拠したIAM パスワードポリシーへと、**自動で修復**することができました。[**次回**](https://qiita.com/eijikominami/items/1887d19ce3bb33f716ba)も引き続き、CIS AWS Foundations Benchmarkの各項目へ準拠するための設定と、その設定を自動的に作成する CloudFormation テンプレートについて説明します。

# 関連リンク
1. [**サービスの有効化** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/53f3a1d83df31981ad86)
2. **パスワードポリシーの自動修復** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
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テンプレート](https://qiita.com/eijikominami/items/581a8e0e424117322125)