【AWS】RDS PostgresへローカルPCからIAM認証で接続する

2020年11月1日

RDS PostgreSQLへのIAM認証による接続を試してみました。本記事ではIAM認証の検証としてローカルPCからRDSへIAM認証を用いて接続する手順を書いています。

データベースの作成

まずはAWSコンソールよりエンジンをPostgreSQLを選択しデータベースを作成します。動作検証のために手軽に接続したかったのでパブリックアクセス可能としています。

IAM認証を行うためにはデータベース作成時に下画像のようにデータベース認証で「パスワードとIAMデータベース認証」を選択します。

RDSでIAM認証を使用するよう設定する

データベースのセキュリティグループを設定

IAM認証によりローカルPCからRDSへ接続したかったのでセキュリティグループに自宅のIPアドレスからの接続を許可するように設定しました。

IAM認証用ユーザをデータベースへ作成

データベースを作成したときのマスターユーザでPostgreSQLへログインしIAM認証用のユーザを作成します。作成したユーザへrds_iamをgrantすることでIAM認証できるユーザとなります。

CREATE USER iam_user WITH LOGIN;
GRANT rds_iam TO iam_user;

次に作成したIAMユーザであるiam_userをを所有者とするデータベースを作成します。このときRDS PostgreSQLではマスターユーザはスーパーユーザ ではないため、iam_userを所有者とするデータベースを作成するためにはpostgreユーザをiam_userのグループのメンバーにする必要があります。

postgres=> \du+
                                                                      List of roles
    Role name    |                         Attributes                         |                          Member of                          | Description
-----------------+------------------------------------------------------------+-------------------------------------------------------------+-------------
 iam_user        |                                                            | {rds_iam}                                                   |
 postgres        | Create role, Create DB                                    +| {rds_superuser}                                             |

postgreユーザをiam_userのグループのメンバーでない状態でiam_user を所有者とするデータベースを作成するとエラーになります。

postgres=> create database test_db owner=iam_user;
ERROR:  must be member of role "iam_user"

以下のコマンドを実行することでpostgresユーザをiam_userのグループのメンバーとします。

# postgresをiam_userのメンバーとする
postgres=> grant iam_user to postgres;
GRANT ROLE

# 確認
postgres=> \du+
                                                                      List of roles
    Role name    |                         Attributes                         |                          Member of                          | Description
-----------------+------------------------------------------------------------+-------------------------------------------------------------+-------------
 iam_user        |                                                            | {rds_iam}                                                   |
 postgres        | Create role, Create DB                                    +| {rds_superuser,iam_user}                                    |

# データベースの作成に成功する
postgres=> create database test_db owner=iam_user;
CREATE DATABASE

postgresユーザをiam_userのメンバーとするとpostgresユーザもIAM認証を使用するユーザとなり、パスワード認証でのログインができなくなります。これはpostgresユーザをiam_userのメンバーとしたことでrds_iamが継承されるためです。

次に説明するIAM認証ポリシーにpostgresユーザを含めるか、iam_userのメンバーから外してください。メンバーから外すには以下のコマンドを実行します。

postgres=> revoke iam_user from postgres;
REVOKE ROLE
postgres=> \du+
                                                                      List of roles
    Role name    |                         Attributes                         |                          Member of                          | Description
-----------------+------------------------------------------------------------+-------------------------------------------------------------+-------------
 iam_user        |                                                            | {rds_iam}                                                   |
 postgres        | Create role, Create DB                                    +| {rds_superuser}                                             |

参考情報

IAMポリシーを作成する

作成したユーザに対してIAM認証の実行を許可するためのIAMポリシーを下記のように作成します。

本記事の例ではIAM認証したユーザ名には上記で作成した「iam_user」を指定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds-db:connect"
            ],
            "Resource": [
                "arn:aws:rds-db:{リージョン}:{AWSアカウントID}:dbuser:{DBリソースID}/{IAM認証したいデータベースユーザ名}"
            ]
        }
    ]
}

DBリソースIDはRDS PostgreSQLの場合下の画像のようにインスタンスの設定タブで確認できる「db-XXXXXX」の形式の文字列です。

ローカルPCからIAM認証でRDSへ接続する

AWS CLIで使用するユーザへ先ほど作成したIAMポリシーを割り当てます。

ローカルPCのターミナルで以下のコマンドを実行しトークンが取得できることを確認します。トークンは「{データベースエンドポイント:{ポート番号}/?Action=XXXXXXXXXX」の形式の長い文字列です。このトークンがIAM認証におけるパスワードとなります。

$ aws --region {リージョン名} rds generate-db-auth-token --hostname {データベースエンドポイント} --port {ポート番号} --username {IAM認証したいデータベースユーザ名} --profile {AWS CLIで使用するプロファイル名}

実際にRDSへ接続する際には下のようにトークンを環境変数PGPASSWORDへ入れておくと使いやすいです。

#取得したトークンを環境変数PGPASSWORDへ設定
$ export PGPASSWORD=$(aws --region ap-northeast-1 rds generate-db-auth-token --hostname xxxxxxxxxx.ap-northeast-1.rds.amazonaws.com --port 5432 --username iam_user --profile cli-user)

# PostgreSQLへ接続
$ psql "host=xxxxxxxxxx.ap-northeast-1.rds.amazonaws.com port=5432 sslrootcert=rds-combined-ca-bundle.pem sslmode=verify-full dbname=test_db user=iam_user"

注意点としては、IAM認証で接続する際にはSSLを使用しなければいけません。その際に中間証明書とルート証明書が必要ですのでhttps://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pemからダウンロードしローカルの適当な場所に配置します。

参考情報