Amazon RDS for MySQL の暗号化の罠

# RDSのストレージを暗号化する

- 既に動いているRDSを暗号化する際の注意点
- CloudFormationを使うと地味にハマる罠

## 方法
- ストレージ暗号化はRDSの「変更」では変えられないため、原則再構築が必要になる
- CloudFormationで更新も出来ないので、やっぱり再構築が必要

## CloudFormation でストレージ暗号化されたRDSを構築する

- まず元のテンプレ
```
AWSTemplateFormatVersion: "2010-09-09"

Resources:
  DBInstance:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Snapshot
    Properties:
      AllocatedStorage: '100'
      AllowMajorVersionUpgrade: false
      AutoMinorVersionUpgrade: false
      DBInstanceClass: db.t3.small
      DBInstanceIdentifier: test-db
      DBParameterGroupName: !Ref DBParameterGroup
      DBSubnetGroupName: !Ref DBSubnetGroup
      Engine: MySQL
      EngineVersion: 8.0.36
      MasterUsername: root
      MasterUserPassword: passsssssssswd
      MaxAllocatedStorage: 1000
      MultiAZ: true
      PreferredBackupWindow: 19:00-19:30
      PreferredMaintenanceWindow: tue:20:00-tue:20:30
      StorageType: gp2
      DBSecurityGroups:
      - Ref: DBSecurityGroup

  DBSecurityGroup:
    Type: AWS::RDS::DBSecurityGroup
    Properties: 
      GroupDescription: test-db-sg
      DBSecurityGroupIngress: 
        - EC2SecurityGroupId: sg-067c0fc45472fbfba
      EC2VpcId: vpc-031268778700e7b2a
      Tags: 
        - 
          Key: "Name"
          Value: "test-db-sg"

  DBSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupDescription: custom subnet group
      DBSubnetGroupName: test-dbsubnet
      SubnetIds:
        - subnet-11111111111111111
        - subnet-22222222222222222

  DBParameterGroup:
    Type: AWS::RDS::DBParameterGroup
    Properties:
      DBParameterGroupName: test-db-group
      Description: "DB parameter group for test-db"
      Family: MySQL8.0
      Parameters:
        log_output: FILE
        long_query_time: 1
        slow_query_log: 1
        time_zone: Asia/Tokyo
```

これの Type: AWS::RDS::DBInstance の Properties: に、「KmsKeyId」と「StorageEncrypted」を追加する
  ```
  Resources:
    DBInstance:
      Type: AWS::RDS::DBInstance
      DeletionPolicy: Snapshot
      Properties:
      ---- 省略 ----
        DBSecurityGroups:
        - Ref: DBSecurityGroup
        KmsKeyId: 11111111-2222-3333-4444-5555555555555　←　ここと
        StorageEncrypted: true　←　これ
  ```
- このテンプレを下に、Cloudformation でRDSを起動
  特にエラーなしで問題なく起動するも、ストレージの暗号化がされていない:sob:
  ![rds_not_encripted.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233507/2a12d934-ca52-8008-d90c-7633649428e1.png)

- 公式ページを隅々まで確認してみる
  ![スクリーンショット 2024-03-22 170850.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233507/22f28766-756f-5992-f0b3-84a70ea3b9e0.png)
  >その他のプロパティは無視されます。StorageType、StorageEncrypted、KmsKeyId などの他のプロパティをサブミットする場合は、仮想プライベート・クラウド（VPC）セキュリティ・グループを指定します。すでに DBSecurityGroups プロパティを使用している場合、VPC セキュリティ・グループを使用するように DB インスタンスを更新しても、これらの他のプロパティを使用することはできません。DB インスタンスを再作成する必要があります。

  **StorageType、StorageEncrypted、KmsKeyId などの他のプロパティをサブミットする場合は、仮想プライベート・クラウド（VPC）セキュリティ・グループを指定します。**

---
- 修正
事前に別のテンプレートや手動でVPCセキュリティグループをつくっておく
→ sg-rrrrrrrrrrrrrrrrr
  ```
  AWSTemplateFormatVersion: "2010-09-09"
  
  Resources:
    DBInstance:
      Type: AWS::RDS::DBInstance
      DeletionPolicy: Snapshot
      Properties:
        AllocatedStorage: '100'
        AllowMajorVersionUpgrade: true
        AutoMinorVersionUpgrade: false
        DBInstanceClass: db.m5.large
        DBInstanceIdentifier: dthrow101
        DBParameterGroupName: !Ref DBParameterGroup
        DBSubnetGroupName: !Ref DBSubnetGroup
        Engine: MySQL
        EngineVersion: 8.0.36
        MasterUsername: root
        MasterUserPassword: passsssssssssssswd
        MaxAllocatedStorage: 1000
        MultiAZ: true
        PreferredBackupWindow: 19:00-19:30
        PreferredMaintenanceWindow: tue:20:00-tue:20:30
        StorageType: gp2
        VPCSecurityGroups:      ←　DBサブネットグループをクビにしてこいつを入れる
        - sg-rrrrrrrrrrrrrrrrr  ←  さっきつくったVPCセキュリティグループID
        KmsKeyId: 11111111-2222-3333-4444-5555555555555
        StorageEncrypted: true
        EnableCloudwatchLogsExports:
        - general
        - error
        - slowquery
        - audit

    <-- ここにあったDBSecurityGroupセクションはリストラ -->

    DBSubnetGroup:
      Type: AWS::RDS::DBSubnetGroup
      Properties:
        DBSubnetGroupDescription: custom subnet group
        DBSubnetGroupName: test-dbsubnet
        SubnetIds:
          - subnet-11111111111111111
          - subnet-22222222222222222

    DBParameterGroup:
      Type: AWS::RDS::DBParameterGroup
      Properties:
        DBParameterGroupName: test-db-group
        Description: "DB parameter group for test-db"
        Family: MySQL8.0
        Parameters:
          log_output: FILE
          long_query_time: 1
          slow_query_log: 1
          time_zone: Asia/Tokyo
  ```

- このテンプレを下に、Cloudformation でRDSを起動
  エラーなく起動し・・・
  ![rds_encripted.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233507/8aa28e68-1913-b350-e60d-739c6e39c46c.png)

- 無事有効化:blush:

## まとめ
- Cloudformation でストレージ暗号化されたDBを作るときは、セキュリティグループに注意
- エラーもなくしれっと無効のまま立ち上がるので、エラーなしでよきよきとか思っていると寝首をかかれます