LambdaでRDS Proxy経由でAurora(MySQL)に接続する(IAM認証)


待ち望んでいたRDS Proxyが東京リージョンでGAされました。
https://aws.amazon.com/jp/blogs/aws/amazon-rds-proxy-now-generally-available/

早速、Lambdaから利用する機会があったのでメモしておきます。
今回は、セキュアに接続するため、TLS+IAM認証で接続します。
上記で接続すると、Lambdaに認証情報(具体的にはDBのパスワード)の取得コードを記載しなくて良いのがかなり良い感じです。

前提

Aurora(MySQL)は存在していること

手順

  1. Secrets Manager設定
  2. RDS Proxy作成
  3. Lambdaから接続

Secrets Manager設定

マネジメントコンソールからSecrets Managerに移動して、認証情報を入力し、シークレットを作成します。

RDS Proxy作成

マネジメントコンソールからRDSに移動しメニューからProxies ->「プロキシを作成」ボタンクリックでRDS Proxyを作成していきます。

TLSを有効にし、

IAM認証を必須に設定します。

Proxyのエンドポイントは後で利用するので、メモっておきます。

Lambdaから接続

Node.jsでデフォルト設定で作成していきます。

LambdaVPCリソースのAuroraにアクセスするため、VPCのアタッチが必要になります。
なので、まずLambdaにロールを付与する必要があります。
ここでは、EC2FullAccessを付与しています。

次に接続したいAuroraが存在するVPCLambdaにアタッチします。

次に、Lambdaに作成したRDS ProxyLambdaに追加します。

プログラム

上記で全ての設定が完了したので、プログラムを記載していきます。

※ サンプルコード全量
https://github.com/Thirosue/aws-lambda-sample/blob/master/rds_proxy/index.js

MySQL clientが必要なので、npmパッケージを含めて、zipでアップロードしてください。
手っ取り早く試したい方は以下コマンドでzipを作成し、アップロードしてください。 ※ yarnかnpmがインストールされている前提です。

$ git clone [email protected]:Thirosue/aws-lambda-sample.git # サンプルコードをclone
$ cd aws-lambda-sample/rds_proxy/ # 対象ディレクトリに移動
$ yarn # もしくは npm install
$ zip -r src.zip index.js node_modules/ # アップロード用のzip作成
node.js
let AWS = require('aws-sdk');
const mysql2 = require('mysql2/promise');

let connection;
const username = 'admin'; // 接続ユーザを設定してください。

exports.handler = async(event) => {
    console.log("Starting query ...\n");
    console.log("Running iam auth ...\n");

    const signer = new AWS.RDS.Signer({
        region: 'ap-northeast-1',
        hostname: process.env['proxy_endpoint'], // メモしておいたプロキシエンドポイントを設定します。ここでは環境変数から取得しています。
        port: 3306,
        username
    });

    const token = signer.getAuthToken({
      username
    });
    console.log(token);
    console.log ("IAM Token obtained\n");

    const connectionConfig = {
      host: process.env['proxy_endpoint'], // メモしておいたプロキシエンドポイントを設定します。
      user: username,
      database: 'mysql', // データベース名を設定してください。
      ssl: 'Amazon RDS',
      password: token,
      authPlugins: { mysql_clear_password: () => () => signer.getAuthToken() }
    };

    connection = await mysql2.createConnection(connectionConfig);   
    const [rows, fields] = await connection.query("SELECT 1");
    console.log(rows);
};

アップロード後、テストイベントを作成して、コンソールからテストすると正常に接続できていることが確認できます。

参考リンク