Lambda で Aurora Serverless の Data API 使えました!そう、Lambda Layer があればね

Lambda Layer で最新の SDK を使い、Lambda 関数から Data API を利用する方法を紹介します!
2019.06.02

前回のエントリーで、Lambda の実行基盤の SDK がまだ古く Data API(rds-data) に対応していませんでした、と書きました。

[アップデート] Aurora Serverless の Data API が東京リージョンでもサポートされました

一晩寝てアタマがスッキリしました。

「そうだ。ぼくたちには Lambda Layer があるじゃないか」

ということで、Lambda Layer を使って最新の SDK を準備し、Lambda から Data API を叩けるところまで確認してみました。

Lambda Layer って何よ?

Lambda Layer は re:Invent 2018 でリリースされました。Lambda Layer は、複数の Lambda 関数でライブラリを共有させたり、カスタムランタイムの利用、その他の依存関係を解決するための zip アーカイブです。従来は、各 Lambda 関数に共通ライブラリを含めて zip していましたが、Lambda Layer は関連付けするだけで、Lambda 関数から共通ライブラリを使用することが出来ます。

Lambda Layerの基本的な仕組みを確認する #reinvent

Lambda Layer の登録

boto3 の zip アーカイブ作成

Lambda Layer に登録する boto3 の zip アーカイブを作成します。

$ python --version
Python 3.7.3

$ mkdir python
$ pip install -t ./python boto3
$ zip -r boto3-1.9.59.zip python

Lambda Layer 作成

Lambda 管理コンソールを開き、左ペインから 「Layer」をクリック。「レイヤーの作成」をクリックします。

レイヤーの作成画面が表示されますので、下記のように登録しました。互換性のあるランタイムとして Python 2.7,Python 3.6,Python 3.7 を指定しています。

これで Lambda Layer の準備は完了です。

Lambda 関数の設定

前回作成した、以下の Lambda 関数を使用します。

  • 東京リージョン
  • Python 3.7
  • IAM ロールに AmazonRDSDataFullAccess ポリシーを追加
    • (のちほど記載しますが、執筆時点ではこれだけではダメかもしれません、、、)

バージョンを確認したいので、print(boto3.__version__) を追加しました。

lambda_function.py

def lambda_handler(event, context):
  
    rdsData = boto3.client('rds-data')
    
    print(boto3.__version__)
  
    cluster_arn = 'arn:aws:rds:ap-northeast-1:xxxxxxxx:cluster:aurora-sl'
    secret_arn = 'arn:aws:secretsmanager:ap-northeast-1:xxxxxxxx:secret:aurora-sl-password-0wKK8u'
   
    response1 = rdsData.execute_statement(
                resourceArn = cluster_arn, 
                secretArn = secret_arn, 
                database = 'mydb', 
                sql = 'select * from sample_table')
  
    print (response1['records'])

Lambda Layer のアタッチ

Lamda 関数のダッシュボードから 「Layer」 をクリックし、画面下部の「レイヤーの追加」をクリックします。

「ランタイムと互換性のあるレイヤーのリストから選択」をえらび、先ほど登録した latest-boto3 を選択し「追加」をクリックします。

レイヤーが追加されたことを確認し、「保存」します。

実行してみる

特に入力イベントは不要なので、適当なテストイベントを作成して「テスト」します。

AmazonRDSDataFullAccess なのに権限がない?

Lambda の実行ロールには AmazonRDSDataFullAccess ポリシーをアタッチしているのですが、以下のエラーメッセージが出てしまいました。なぜか secretsmanager:GetSecretValue の権限がなく、認証情報が取得できていないようです。

[ERROR] ClientError: An error occurred (AccessDeniedException) when calling the ExecuteStatement operation: User: arn:aws:sts::xxxxxxxx:assumed-role/lambda_basic_execution/aurora-sl is not authorized to perform: secretsmanager:GetSecretValue on resource: arn:aws:secretsmanager:ap-northeast-1:xxxxxxxx:secret:aurora-sl-password-0wKK8u

執筆時点ではポリシー内の "Resource": "arn:aws:secretsmanager:*:*:secret:rds-db-credentials/*" が正しく機能していないのかもしれませんね。。

暫定の回避策として、同じようなポリシーを作成して、該当シークレットマネージャの ARN を指定するようにしました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "SecretsManagerDbCredentialsAccess",
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue",
                "secretsmanager:PutResourcePolicy",
                "secretsmanager:PutSecretValue",
                "secretsmanager:DeleteSecret",
                "secretsmanager:DescribeSecret",
                "secretsmanager:TagResource"
            ],
            "Resource": [
                "arn:aws:secretsmanager:*:*:secret:rds-db-credentials/*",
                "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxx:secret:aurora-sl-password-0wKK8u"
            ]
        },
        {
            "Sid": "RDSDataServiceAccess",
            "Effect": "Allow",
            "Action": [
                "dbqms:CreateFavoriteQuery",
                "dbqms:DescribeFavoriteQueries",
                "dbqms:UpdateFavoriteQuery",
                "dbqms:DeleteFavoriteQueries",
                "dbqms:GetQueryString",
                "dbqms:CreateQueryHistory",
                "dbqms:DescribeQueryHistory",
                "dbqms:UpdateQueryHistory",
                "dbqms:DeleteQueryHistory",
                "dbqms:DescribeQueryHistory",
                "rds-data:ExecuteSql",
                "rds-data:ExecuteStatement",
                "rds-data:BatchExecuteStatement",
                "rds-data:BeginTransaction",
                "rds-data:CommitTransaction",
                "rds-data:RollbackTransaction",
                "secretsmanager:CreateSecret",
                "secretsmanager:ListSecrets",
                "secretsmanager:GetRandomPassword",
                "tag:GetResources"
            ],
            "Resource": "*"
        }
    ]
}

あらためて実行!

Lambda ロールに上記のポリシーを追加し、再実行します。

START RequestId: 4c819494-e67c-xxxx-xxxx-xxxxxxxxxxxx Version: $LATEST
1.9.159
[[{'longValue': 1}, {'stringValue': 'TEST'}, {'stringValue': '2019-06-01 04:15:10.0'}], [{'longValue': 2}, {'stringValue': 'COMMIT'}, {'stringValue': '2019-06-01 04:41:47.0'}], [{'longValue': 11}, {'stringValue': 'BBB'}, {'stringValue': '2019-06-01 08:51:02.0'}]]
END RequestId: 4c819494-e67c-xxxx-xxxx-xxxxxxxxxxxx
REPORT RequestId: 4c819494-e67c-xxxx-xxxx-xxxxxxxxxxxx	Duration: 351.83 ms	Billed Duration: 400 ms 	Memory Size: 128 MB	Max Memory Used: 73 MB	

実行できましたー!バージョンも 1.9.159 と表示されていますね!

さいごに

Lambda Layer を使って、Aurora Serverless の Data API(rds-data) を利用することが確認できました。Lambda 実行基盤の SDK バージョンが update されるまでの暫定対応として使えるかと思いますので、早く検証したい方は是非ご活用ください!

以上!大阪オフィスの丸毛(@marumo1981)でした!