【AWS】LambdaからRDS Proxy経由でPostgreSQLへ接続する

LambdaからRDS Proxy経由でPostgreSQLへ接続する

この記事ではLambdaからRDS Proxy経由でRDS PostgreSQLへ接続する方法際の設定方法について書いています。

RDSの設定

インスタンス作成後認証方式とセキュリティグループの設定を行います。

認証方式設定

RDS ProxyとRDS間はID/パスワードによる認証となるのでRDSのIAM認証を無効にしています。

RDS PostgreSQLの認証方法の設定

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

RDSのセキュリティグループのインバウンド通信には後で作成するRDS Proxyからの通信を許可します。ここでは検証のためローカルPCのIPアドレスからの通信も許可する設定にしています。

RDS PostgreSQLのセキュリティグループの設定

検証用データベースとユーザの作成

マスターユーザでRDSインスタンスへ接続し、RDS Proxy経由で接続する際に使用するユーザと検証用のデータベース、テーブルを作成します。

# ユーザ作成
$ create user test_user with password 'xxxxx';

# test_userを所有者とするデータベースを作成するためにマスターユーザをグループへ追加する
$ grant test_user to postgres;

# データベースとテーブル作成
$ create database test_db2 owner=test_user;
$ create table employee(id serial primary key, name text);
$ insert into employee(name) values ('hoge'),('hogehoge'),('hogehogehoge');

Lambdaの作成

ロール設定

LambdaからRDS ProxyやRDSのようにVPC内のサービスにアクセスするためには、LambdaをVPC内に作成する必要があります。このときLambdaはネットワークインターフェイスの作成などを行える権限を設定する必要があります。このために「AWSLambdaVPCAccessExecutionRole」というAWS管理ポリシーが用意されていますので、これをLambdaに割り当てます。

VPC設定

RDS Proxyと通信可能なVPCとサブネットをLambdaに割り当てます。ここではLambda, RDS Proxy, RDSは全て同じVPC, 同じSubnetに割り当てています。

LambdaへのVPCの割り当て

RDS Proxy

RDSのコンソールからProxiesを選び「プロキシを作成」をクリックしてRDS Proxyの作成を開始します。

RDS Proxyの作成

作成するRDS Proxyの名前、接続先のRDSのエンジンを選択します。今回はLambdaとRDS Proxy間でIAM認証を行うために「Transport Layer Securityが必要」にチェックを入れます。

ターゲットグループ の設定で接続先のRDSを選択します。PostgreSQLの場合12系はRDS Proxyに対応していません。12系で作成するとドロップダウンに表示されないため注意してください。

RDS Proxyの設定

RDS Proxy用のロールを新規作成するため「IAMロールを作成」を選択します。また、IAM認証を行うためにIAM認証は「必須」とします。

そして、RDS ProxyがRDSへ接続する際に使用するID/Passwordを保存するためにSecrets Managerのシークレットを作成します。新規作成する場合は「新しいシークレットを作成する」をクリックします。

RDS Proxyの接続方法設定

Secrets Manager

RDS Proxyが使用するシークレットを新たに作成します。シークレットの種類を「RDSデータベースの認証情報」を選択します。そして、シークレットに保存するユーザ名、パスワードはRDS接続に使用するものを入力します。この記事の例ではあらかじめ作成しておいた「test_user」とそのパスワードを入力します。

そして、接続先のRDSインスタンスを選択します。

Secrets Managerの作成

次へをクリックしシークレットの名前と説明を入力して次へ進みます。

今回はパスワードのローテーションは行わない設定で作成しました。最後に確認画面で入力内容を確認しシークレットを作成します。

LambdaからRDS Proxyへの接続

Lambda関数からRDS Proxyへ接続するためのコードを記述します。この例ではLambdaの言語をPython3.8としています。

レイヤーの追加

psycopg2を使用してPostgreSQLに接続します。psycopg2を簡単に使用するためにLambdaでPostgreSQLを使う(Python + psycopg2)で紹介されているようにレイヤーの追加を行います。

Lambdaへのレイヤー追加

「ARNを指定を指定」を選択し、ARNへ「arn:aws:lambda:ap-northeast-1:898466741470:layer:psycopg2-py38:1」と入力し「追加」をクリックします。

LambdaへARNを指定してレイヤーを追加する

RDS Proxyへの接続しSQLを実行するコード

以下のようなコードを記述してRDS ProxyへIAM認証で接続します。コードとしては接続先のエンドポイントがRDS Proxyにすればいいだけです。

この例ではあらかじめ作成しておいたemployeeテーブルのデータをコンソールに出力しているだけです。

import json
import os
import sys
import boto3
import psycopg2

def lambda_handler(event, context):
    
    ENDPOINT="rds-proxy-xxxxx.proxy-xxxxxx.ap-northeast-1.rds.amazonaws.com"
    PORT="5432"
    USR="test_user"
    REGION="ap-northeast-1"

    client = boto3.client('rds')

    # IAM認証を行いトークンを取得
    token = client.generate_db_auth_token(DBHostname=ENDPOINT, Port=PORT, DBUsername=USR, Region=REGION)

    # 取得したトークンをパスワードとしてデータベースへ接続
    connection = psycopg2.connect(host=ENDPOINT, database="test_db2", user=USR,password=token, sslmode='require')
    
    # SQLを実行
    cur = connection.cursor()
    cur.execute('SELECT * FROM employee')
    results = cur.fetchall()
    
    # コンソールへ出力
    for r in results:
        print(r)
    
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

作成した関数をテスト実行してみると以下のようにemployeeテーブルのデータが取得できています。

Lambdaをテスト実行する