【AWS】AWS Secrets Managerを使って、RDSのパスワードをローテーションさせてみました

#はじめに
AWS Secrets Managerは皆さん使っていますでしょうか。
AWS上のRDSをより安全でセキュアに使っていくにあたって、このサービスが大いに役に立ちます。
簡単によくある使い道を説明すると、RDSへの接続は、直接パスワードやRDSエンドポイント等の情報をそのままコードに埋め込むではなく、Secrets Managerを経由して必要な情報を取得し、接続していくパターンになります。
さらに、AWS Secrets Managerは、Lambda経由してパスワードをローテーションさせることができるので、パスワード管理などは大変便利になります。
早速、個人が使い方をまとめましたので、当手順を公開していきます。

#構成図
全体構成図は下記になります。ポイントをざっくり解説します。
・EC2にSecrets Managerをアクセスできるように、適切なロールを付与します。
・Secrets Managerにシークレット情報を暗号化するために、KMSで暗号化をかけています。
・VPC内にLmabdaがあり、Secrets Managerと通信できるように、VPCエンドポイントを作成しています。
・Secrets ManagerでRDS等の接続情報を管理しており、Lambda経由でRDS接続用のパスワードを定期的にローテーションさせる役割を果たしています。

![AWS Secret Manager 構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/db7f9836-9f70-b309-8dca-76fff450ad43.png)

#１．EC2の設定
今回私が使っているEC2は Amazon Linux 2になります。
あらかじめ下記のミドルウェア等をインストールしておきましょう。
①EPEL リポジトリ

```
$ sudo amazon-linux-extras install epel -y
```
参考URL：

https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-enable-epel/

②AWS CLI

```
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
```
参考URL：

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html#cliv2-linux-install

③jq

```
$ sudo yum install jq -y
```
④postgresql

```
$ sudo yum install postgresql -y
```

⑤EC2にIAMロールを付与
・SecretsManagerReadWrite
・AmazonEC2RoleforSSM
なお、SSMロールは個人的にSSM Agentを利用するため付与したロールです。
実際Secrets Managerだけを使うのであれば、「SecretsManagerReadWrite」だけで十分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/a9016130-490b-29e2-0387-b6eae012c30f.png)

#２．RDSの作成
今回私が作成したRDSはPostgreSQLです。
RDS作成手順はここで割愛させていただきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/b13faee7-1596-a5bd-e0d9-e5c67250c42e.png)

#３．Secrets Managerの作成
上記「２．RDSの作成」で作成されたRDSの「ユーザー名」と「パスワード」を入力します。
暗号化キーは今回「DefaultEncryptionKey」を選択します。
※なお、暗号化キーにKMSカスタマーキーも設定できるが、今回はデフォルを選択します。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/f0ae8c4c-1089-30ab-dc35-9b5094061382.png)

上記「２．RDSの作成」で作成されたRDSを選択します。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/2a89b8ed-0b7a-aaed-8ced-6aa9d15409ff.png)

シートレットの名前を入力します。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/5ad5b1df-ac89-71e1-1fcd-12a989378c8b.png)

「自動ローテーションを有効にする」を選択します。
私は今回ローテーション間隔は30日間と設定します。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/2b0b40f6-5ca1-2905-af92-5a8e8550a3bf.png)

「ローテーションを実行するための新しいLambda関数を作成します」を選択します。
「新しいAWS Lambda関数名」に関数名を入れておきます。
「ローテーションの実行に使用するシークレットを選択してください」に「このシークレットを使う」を選択します。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/a90ed5e8-8f52-7263-8bf5-d54f6c04b9ea.png)

最後はレビューでもう一回チェックをし、問題がなければ作成ボタンを押していきます。
作成後に、合わせてAWSがLambda関数を作成してくれるので、Lambdaで確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/6af57d25-6815-c96e-d6b5-88f67d46ded1.png)


#４．セキュリティグループの設定
EC2用のセキュリティグループとほかに、以下三つのセキュリティグループを作成または編集する必要があります。
・Secret Manager VPCエンドポイント用セキュリティグループ
・RDS用セキュリティグループ
・Lmabda用セキュリティグループ
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/071a4631-2f51-9484-2117-7a891337f3b1.png)

①Secret Manager VPCエンドポイント用セキュリティグループ、VPC CIDR でTCP 443ポートを許可します。今回私が使っている VPC CIDR は 10.0.0.0/16 なので、10.0.0.0/16を開放します。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/f03fa72f-653c-ca25-fb8d-9af4c681f0fc.png)

②Lmabda用セキュリティグループに、Secret Manager エンドポイント用セキュリティグループを追加します。ポートは TCP 443 です。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/f0fe70db-5ffe-db2b-1b1d-9c00ce723074.png)

③RDS用セキュリティグループに、Lmabda用セキュリティグループを追加します。ポートは TCP 5432です。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/42ab0a49-9f40-fb9b-3acb-9eaf4d8b1fae.png)

④上記「３．Secrets Managerの作成」で作成されたLambda関数のセキュリティグループを編集します。
自動作成されたLambda関数では、デフォルセキュリティグループを使用します。
デフォルセキュリティグループを、Lambda用のセキュリティグループに置き換えていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/6af57d25-6815-c96e-d6b5-88f67d46ded1.png)
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/5d3cf88e-24d7-93bf-fec2-0d25e7cb6035.png)

#５．Secrets Manager 用 VPC エンドポイント作成
VPC→エンドポイントで、Secrets Manager 用 VPC エンドポイント作成していきます。
エンドポイントサービス名：com.amazonaws.ap-northeast-1.secretsmanager
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/d3481c7e-5f5c-4b07-3b76-5d2c9d7cc4cc.png)

VPCとサブネットを選択します。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/6ed9c7fc-dc76-efda-a233-677ab4871625.png)

セキュリティグループに、上記設定した Secret Manager VPCエンドポイント用セキュリティグループを選択します。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/fee6a4c7-f269-3414-8f2c-2cdcc14d5ead.png)

ポリシー欄は一旦このままでよいので、作成後に編集していきます。
エンドポイントの作成を押してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/279efd09-e5e3-72ab-e970-6bf95a73c794.png)

エンドポイント作成後に、必ずエンドポイントのポリシーを変更してください。
下記のようなポリシーを使用するには、AWS アカウント ID と VPC エンドポイント ID のプレースホルダーを、ご自身の有効な値で置き換えます。
このエンドポイントのポリシーの意味は下記となります：
>ユーザーがSecrets Manager にリクエストを送信すると、Secrets Manager はリクエストの VPC エンドポイント ID をaws:sourceVpce条件キーの値を指定します。これらが一致しない場合、Secrets Manager はリクエストを拒否します。

参考URL：

https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/vpc-endpoint-overview.html


```
{
    "Id": "example-policy-1",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "EnableSecretsManagerpermissions",
            "Effect": "Allow",
            "Principal": {"AWS":["XXXXXXXXXXX"]},
            "Action": ["secretsmanager:*"],
            "Resource": "*"
        },
        {
            "Sid": "RestrictGetSecretValueoperation",
            "Effect": "Deny",
            "Principal": "*",
            "Action": ["secretsmanager:GetSecretValue"],
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpce": "vpce-XXXXXXXXXXXXXX"
                }
            }
        }

    ]
}
```
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/56f3e318-e125-cc38-8ff9-41f86dc24fdb.png)

#５．パスワードをローテーションさせる
パスワード変更前：

```
sh-4.2$ aws secretsmanager get-secret-value --secret-id a-test-postgresql-key --region ap-northeast-1 | jq .SecretString | jq fromjson
{
  "username": "admindadada",
  "password": "tX9Vbx5A",
  "engine": "postgres",
  "host": "secret-manager-test.XXXXXXXXXXXXX.ap-northeast-1.rds.amazonaws.com",
  "port": 5432,
  "dbname": "dadada",
  "dbInstanceIdentifier": "secret-manager-test"
}
```

Secrets Managerで、「すぐにシークレットをローテーションさせる」押してください。
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/8f886f6e-7b9a-3aa7-0aa1-857b44d2ed2c.png)

すると、パスワードが変更されたことを確認できました。

```
sh-4.2$ aws secretsmanager get-secret-value --secret-id a-test-postgresql-key --region ap-northeast-1 | jq .SecretString | jq fromjson
{
  "username": "admindadada",
  "password": "_DDFpe$EFcby>ZS(3Q-]jGhbb!x]zbkz",
  "engine": "postgres",
  "host": "secret-manager-test.XXXXXXXXXXXXX.ap-northeast-1.rds.amazonaws.com",
  "port": 5432,
  "dbname": "dadada",
  "dbInstanceIdentifier": "secret-manager-test"
}
```

#６．まとめ
このように、AWS Secrets Managerを使うことによって、コード内に直接RDSのエンドポイントやパスワード等の情報を埋め込まずに済みました。
さらにLambdaでローテーションさせることで、安全性を一層高めることが出来ます。
ちなみに、jqを使って、RDSの諸情報をフィルターできます。

下記フィルターの例になります。
RDSのユーザー：

```
aws secretsmanager get-secret-value --secret-id XXXXXXXXXXX --region ap-northeast-1 | jq .SecretString | jq fromjson | jq -r .username
```

RDSのパスワード：

```
aws secretsmanager get-secret-value --secret-id XXXXXXXXXXX --region ap-northeast-1 | jq .SecretString | jq fromjson | jq -r .password
```

RDSのエンドポイント：

```
aws secretsmanager get-secret-value --secret-id XXXXXXXXXXX --region ap-northeast-1 | jq .SecretString | jq fromjson | jq -r .host
```


RDSのポート：

```
aws secretsmanager get-secret-value --secret-id XXXXXXXXXXX --region ap-northeast-1 | jq .SecretString | jq fromjson | jq -r .port
```


今回クラスメソッドさんの記事が大変参考になりました。



参考資料：

https://dev.classmethod.jp/articles/secrets-manager-tutorials/

https://aws.amazon.com/jp/premiumsupport/knowledge-center/rotate-secrets-manager-secret-vpc/