セキュリティリスク回避のためのRDS(PostgreSQL)へのIAM認証導入

はじめに

先日、RDS(MySQL)へのIAM認証を導入したことをブログに書きました。

miyohide.hatenablog.com

今回は、RDS(PostgreSQL)へのIAM認証を導入してみます。

また、この検証をするためにCDKも実装してみたのでそれも紹介します。

公式ドキュメントの確認

公式ドキュメントは以下で公開されているのでそれをもとに作業を進めます。

docs.aws.amazon.com

CDKでの実装

IAMポリシー作成

まずはIAMポリシーを作成します。公式ドキュメントは以下のもの。

docs.aws.amazon.com

CDKでは以下のように実装しました。

    // IAMロールを作成
    const role = new Role(this, 'Role', {
      roleName: 'EC2RoleForRDSIAMAuth',
      assumedBy: new ServicePrincipal("ec2.amazonaws.com"),
    });

    // RDSへのIAM認証に必要なポリシーをアタッチ
    role.addToPolicy(new PolicyStatement({
      effect: Effect.ALLOW,
      actions: ["rds-db:connect"],
      resources: ["*"]
    }));

対象のresources['*']としていますが、ここは改善したいところ。

EC2作成

RDS(PostgreSQL)に接続するEC2を作成します。クライアントとしてpostgresql15をインストールする処理をユーザーデータに指定しておき、先ほど作成したIAMポリシーも指定しておきます。

    const userData = UserData.forLinux({
      shebang: '#!/bin/bash',
    });
    userData.addCommands(
      'dnf install -y mariadb105',
      'dnf install -y postgresql15'
    );

    // EC2インスタンスを作成する
    const ec2Instance = new Instance(this, 'EC2Instance', {
      vpc: vpc,
      vpcSubnets: { subnetType: SubnetType.PRIVATE_WITH_EGRESS },
      securityGroup: ec2Sg,
      instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.MICRO),
      machineImage: new AmazonLinuxImage({
        generation: AmazonLinuxGeneration.AMAZON_LINUX_2023,
      }),
      userData: userData,
      role: role,
    });

RDS(PostgreSQL)の操作

作成しているRDS(PostgreSQL)にIAM認証を導入します。まずはIAM認証を有効化することを忘れずに。

docs.aws.amazon.com

また、データベースアカウントを作成します。公式ドキュメントは以下。

docs.aws.amazon.com

特段難しいことはなく、CREATE USER ユーザー名;を実行後、GRANT rds_iam TO ユーザー名;でユーザーにrds_iamロールを付与すればOKです。これだけだとちょっと不便なのでALTER ROLE ユーザー名 CREATEDB;を実行してデータベースを作れるようにしておくと良いかなと思います。\duを実行してロールを確認しておくと良いかなと思います。

データベース名=> \du
                                                                                                                 List of roles
    Role name    |                         Attributes                         |                                                                            Memb
er of                                                                            
-----------------+------------------------------------------------------------+--------------------------------------------------------------------------------
---------------------------------------------------------------------------------
 ユーザー名        | Create DB                                                  | {rds_iam}
 postgres        | Create role, Create DB                                    +| {rds_superuser}
                 | Password valid until infinity                              | 
 rds_ad          | Cannot login                                               | {}
 rds_iam         | Cannot login                                               | {}
 rds_password    | Cannot login                                               | {}
 rds_replication | Cannot login                                               | {}
 rds_superuser   | Cannot login                                               | {pg_read_all_data,pg_write_all_data,pg_monitor,pg_signal_backend,pg_checkpoint,
pg_use_reserved_connections,pg_create_subscription,rds_replication,rds_password}
 rdsadmin        | Superuser, Create role, Create DB, Replication, Bypass RLS+| {}
                 | Password valid until infinity                              | 
 rdsrepladmin    | No inheritance, Cannot login, Replication                  | {}
 rdstopmgr       |                                                            | {pg_monitor,pg_checkpoint}

データベース名=>

以上で設定は終了です。

IAM認証で接続する

環境変数に接続先とアクセストークンを格納しておきます。

$ export RDSHOST="RDSのエンドポイント"
$ export PGPASSWORD="$(aws rds generate-db-auth-token --hostname $RDSHOST --port 5432 --region リージョン --username ユーザー名)"

以下のコマンドで接続します。

$ psql "host=$RDSHOST port=5432 dbname=データベース名 user=ユーザー名 password=$PGPASSWORD"
psql (15.6, server 16.1)
WARNING: psql major version 15, server major version 16.
         Some psql features might not work.
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

データベース名=>

無事接続できました。

考察

今回はPostgreSQLに対してIAM認証を導入してみました。細かいコマンドは違いますが、ほぼほぼMySQLと同じ感じです。

今回は手作業を解消するためにCDKを導入しました。先日手作業で実施したところがミスなく環境を構築することができました。CDKの実装にはそこそこ時間がかかりますが、Web上でいろんな画面を行ったり来たりするよりも格段に楽なので、CDKでの実装しておくと良いかなと考えています。

今後は、実際のアプリでIAM認証を導入していくことをやっていきます。