LoginSignup
5
4

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-06-29

はじめに

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

1.EC2の設定

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

$ sudo amazon-linux-extras install epel -y

参考URL:

②AWS CLI

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

参考URL:

③jq

$ sudo yum install jq -y

④postgresql

$ sudo yum install postgresql -y

⑤EC2にIAMロールを付与
・SecretsManagerReadWrite
・AmazonEC2RoleforSSM
なお、SSMロールは個人的にSSM Agentを利用するため付与したロールです。
実際Secrets Managerだけを使うのであれば、「SecretsManagerReadWrite」だけで十分です。
image.png

2.RDSの作成

今回私が作成したRDSはPostgreSQLです。
RDS作成手順はここで割愛させていただきます。
image.png

3.Secrets Managerの作成

上記「2.RDSの作成」で作成されたRDSの「ユーザー名」と「パスワード」を入力します。
暗号化キーは今回「DefaultEncryptionKey」を選択します。
※なお、暗号化キーにKMSカスタマーキーも設定できるが、今回はデフォルを選択します。
111.png

上記「2.RDSの作成」で作成されたRDSを選択します。
111.png

シートレットの名前を入力します。
111.png

「自動ローテーションを有効にする」を選択します。
私は今回ローテーション間隔は30日間と設定します。
111.png

「ローテーションを実行するための新しいLambda関数を作成します」を選択します。
「新しいAWS Lambda関数名」に関数名を入れておきます。
「ローテーションの実行に使用するシークレットを選択してください」に「このシークレットを使う」を選択します。
111.png

最後はレビューでもう一回チェックをし、問題がなければ作成ボタンを押していきます。
作成後に、合わせてAWSがLambda関数を作成してくれるので、Lambdaで確認できます。
image.png

4.セキュリティグループの設定

EC2用のセキュリティグループとほかに、以下三つのセキュリティグループを作成または編集する必要があります。
・Secret Manager VPCエンドポイント用セキュリティグループ
・RDS用セキュリティグループ
・Lmabda用セキュリティグループ
111.png

①Secret Manager VPCエンドポイント用セキュリティグループ、VPC CIDR でTCP 443ポートを許可します。今回私が使っている VPC CIDR は 10.0.0.0/16 なので、10.0.0.0/16を開放します。
111.png

②Lmabda用セキュリティグループに、Secret Manager エンドポイント用セキュリティグループを追加します。ポートは TCP 443 です。
111.png

③RDS用セキュリティグループに、Lmabda用セキュリティグループを追加します。ポートは TCP 5432です。
111.png

④上記「3.Secrets Managerの作成」で作成されたLambda関数のセキュリティグループを編集します。
自動作成されたLambda関数では、デフォルセキュリティグループを使用します。
デフォルセキュリティグループを、Lambda用のセキュリティグループに置き換えていきます。
image.png
111.png

5.Secrets Manager 用 VPC エンドポイント作成

VPC→エンドポイントで、Secrets Manager 用 VPC エンドポイント作成していきます。
エンドポイントサービス名:com.amazonaws.ap-northeast-1.secretsmanager
111.png

VPCとサブネットを選択します。
111.png

セキュリティグループに、上記設定した Secret Manager VPCエンドポイント用セキュリティグループを選択します。
111.png

ポリシー欄は一旦このままでよいので、作成後に編集していきます。
エンドポイントの作成を押してください。
image.png

エンドポイント作成後に、必ずエンドポイントのポリシーを変更してください。
下記のようなポリシーを使用するには、AWS アカウント ID と VPC エンドポイント ID のプレースホルダーを、ご自身の有効な値で置き換えます。
このエンドポイントのポリシーの意味は下記となります:

ユーザーがSecrets Manager にリクエストを送信すると、Secrets Manager はリクエストの VPC エンドポイント ID をaws:sourceVpce条件キーの値を指定します。これらが一致しない場合、Secrets Manager はリクエストを拒否します。

参考URL:

{
    "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

5.パスワードをローテーションさせる

パスワード変更前:

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

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

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"
}

6.まとめ

このように、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

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

参考資料:

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4