「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ⑥SSHとRDPのアクセスを制限する

# はじめに

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)

# SSHとRDPからのアクセスを制限する

外部から `EC2` インスタンスへは、一般的に `SSH` や `Remote Desktop Protocol(RDP)` などの **リモートコンソールサービス** を用います。言い換えれば、これらのサービスに対して適切なアクセス制限を課していない場合、 **悪意のある第三者が不正にインスタンスへ接続する恐れ** があります。

そこで、 **CIS AWS Foundations Benchmark** では、

+ 4.1 **どのセキュリティグループでも 0.0.0.0/0 からポート 22 への入力を許可しないようにします**
+ 4.2 **どのセキュリティグループでも 0.0.0.0/0 からポート 3389 への入力を許可しないようにします**

という項目によって、これらのリモートコントロールサービスからの **無制限の接続を許可しない** ことを求めています。この規定に準拠するために、このCloudFormationテンプレートでは、以下の設定を行います。

1. **セキュリティグループ** が上記のポリシーに準拠しているか **チェック** を行う
2. 非準拠であった場合には、`AWS Config` が `SSM Automation` を自動起動する
3. `SSM Automation` を用いて **当該ポートの開放を無効化** する

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

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

当該ポートが閉じているかどうかの確認には、あらかじめ `AWS Config` に用意されている `VPC_SG_OPEN_ONLY_TO_AUTHORIZED_PORTS` マネージドルールを使用します。これは、**指定したポート以外のポートが開放されていることを検出するルール** で、SSHとRDPで通常使用される**22番ポート** および **3389番ポート** 「**以外**」のポートを、 **開放を許可するポートに指定** します。なお、この `Config Rule` を設定する前に `ConfigurationRecorder` を生成しておく必要があります。そこで、`DependsOn` 属性に `ConfigurationRecorder` リソースを設定しています。

```yaml
Resources:
  ConfigSVpcSgOpenOnlyToAuthorizedPorts:
    DependsOn:
      - ConfigConfigurationRecorder
    Type: 'AWS::Config::ConfigRule'
    Properties:
      ConfigRuleName: vpc-sg-open-only-to-authorized-ports
      Description: いずれかの 0.0.0.0/0 Amazon Virtual Private Cloud (Amazon VPC) を持つセキュリティグループで、特定のインバウンド TCP または UDP トラフィックのみが許可されるかどうかを確認します。
      InputParameters:
        authorizedTcpPorts: 1-21,23-3388,3390-65535
        authorizedUdpPorts: 1-21,23-3388,3390-65535
      Source:
        Owner: AWS
        SourceIdentifier: VPC_SG_OPEN_ONLY_TO_AUTHORIZED_PORTS  
```

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

``Systems Manager Automation`` は、``AWS Config`` で **直接指定できる、現時点で唯一の自動修復手段** となっています。そこで、無制限に公開されている **22番ポート** および **3389番ポート** を持つセキュリティグループが検出された場合に、当該ポートの開放設定を **自動で無効化** する ``Systems Manager Automation`` ドキュメントを指定します。

Systems Manager には、あらかじめ **定義済みの Automation ドキュメント** が用意されており、`AWS-DisablePublicAccessForSecurityGroup` という名称の定義済みドキュメントを用いることで、**すべての IP アドレスに対して開かれている** デフォルトの **SSH および RDP ポートを無効にできる** ため、本テンプレートではこのドキュメントを使用しています。

また、この 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:
                  - 'ec2:RevokeSecurityGroupIngress'
                  - 'ec2:RevokeSecurityGroupEgress'
                  - 'ec2:DescribeSecurityGroups'
                Resource:
                  - '*'
      RoleName: !Sub 'DefaultSecuritySettings-SSM-${AWS::Region}'
  ConfigVpcSgOpenOnlyToAuthorizedPortsRemediationConfiguration:
    Type: 'AWS::Config::RemediationConfiguration'
    Properties:
      Automatic: true
      ConfigRuleName: !Ref ConfigSVpcSgOpenOnlyToAuthorizedPorts
      MaximumAutomaticAttempts: 1
      Parameters:
        AutomationAssumeRole:
          StaticValue:
            Values:
              - !GetAtt IAMRoleForSSM.Arn
        GroupId:
          ResourceValue:
            Value: RESOURCE_ID
      RetryAttemptSeconds: 30
      TargetId: AWS-DisablePublicAccessForSecurityGroup
      TargetType: SSM_DOCUMENT
```

以上で、**無制限に開放** されている **22番ポート** および **3389番ポート** の設定をセキュリティグループ上で **無効化** することができました。

# 関連リンク
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テンプレート
7. [**デフォルトセキュリティグループを無効化する** - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/2fa109f00b5c63686c42)
8. [**S3バケットのサーバサイド暗号化** - セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート](https://qiita.com/eijikominami/items/581a8e0e424117322125)