見出し画像

AWS_IAM 認証付き Lambda Function URL を curl で呼び出す

Solution Architect の t_maru です。

今回は AWS の Lambda Functions URL の設定で IAM 認証を設定している状態で動作確認などのため手動で Function を呼び出す方法についてご紹介します。


Lambda Function URLs と認証モデル

まず Lambda の Function URLs という機能についてですが、これは Lambda 関数に追加の設定をすることで Lambda 関数に https の URL が生成され (エンドポイントが設定され)、直接インターネット上から Lambda 関数を呼び出すことができるようになるという機能です。

この機能がリリースされるまではインターネットから API として処理を呼び出すために API Gateway などと組み合わせて利用するなど、単機能の簡単な処理の API を作りたいときでも Lambda 以外に API Gateway の学習が必要だったりという状況でした。

この Lambda Function URLs ですが、呼び出しの認証タイプを以下の 2 種類から選択することができます。

  • AWS_IAM 認証

    • AWS の IAM で `lambda:InvokeFunctionUrl` のアクセス許可がされているユーザ/Role からの呼び出しを許可

  • NONE

    • 基本的にパブリックアクセスになるので、インターネット上から自由に呼び出しできるようになる

不特定多数から呼び出される Web API を公開するのであれば、あえて NONE を設定するという場合もありますが、そうでない場合は認証を設定しておくほうが安全です。

そこでもう一方の AWS_IAM 認証を使うわけですが、この方法を設定すると Lambda を呼び出す際に認証情報を含めて API call する必要が出るため、Local で開発したものをデプロイして Local PC 上から手動でリクエストを送信して動作確認しようとした場合に少し面倒が生じます。

AWS_IAM 認証を指定した場合の Lambda の呼び出し

AWS_IAM が設定されている場合、Lambda を呼び出す HTTP のリクエストには AWS Signature Version 4 と呼ばれる方法で署名したリクエストである必要があります。

詳細については下記の公式ドキュメントを参照ください。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/urls-invocation.html#urls-invocation-basics

この署名のプロセスについて明確に手順の記載があるためすべて自作することもできますし、aws-sdk にも署名に必要なパッケージが含まれているためそれほど難易度の高い実装が必要になるわけではありませんが、追加でやるべき作業が増えるので面倒といえば面倒です。

そこで AWS の署名機能に対応しているツールを活用します。今回は curl を用いた例を紹介しますが、公式ドキュメントにもいくつかツールの案内があるのでそちらのツールを活用していただいても問題ありません。

curl での呼び出し時に自動的に AWS のリクエスト署名を行う

まず結論からですが、curl で呼び出す際に以下のように `--aws-sigv4` と `--user` という option を指定することで自動的に署名を付与することができます。

curl "関数の URL" --aws-sigv4 "aws:amz:${AWS_REGION}:lambda" --user "${ACCESS_KEY}:${SECRET_ACCESS_KEY}"

`${ }` で囲われている大文字の変数は使用する AWS リージョンや API call する AWS IAM ユーザまたは Role の認証情報です。

shell スクリプトなどを組んで実行する際には上記の変数に適切なものを設定いただければと実行できますが、PC などのコマンドラインで直接実行する場合は AWS CLI の実行結果を以下のように実行することもできます。

curl "関数の URL" \
  --aws-sigv4 "aws:amz:$(aws configure get region):lambda" \
  --user "$(aws configure get aws_access_key_id):$(aws configure get aws_secret_access_key)"

※ 上記は Mac OS でのコマンド例です。また curl は version 7.75.0 以上の使用を想定しています。

また、CodeBuild など AWS 環境上で動作しており、適切な IAM Role が割り当てられている場合は以下のような処理を設定することで署名付きリクエストを送信することもできますので、参考にしていただければと思います。

CodeBuild を使ってリクエストを送るサンプル (buildspec.yml)

version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 18
    commands:
      - echo Install started on `date`

  pre_build:
    commands:
      - echo Pre Build started on `date`

  build:
    commands:
      - echo Build started on `date`
      - CRED=$(curl 169.254.170.2${AWS_CONTAINER_CREDENTIALS_RELATIVE_URI})
      - ACCESS_KEY=$(echo ${CRED} | jq -r .AccessKeyId)
      - SECRET_ACCESS_KEY=$(echo ${CRED} | jq -r .SecretAccessKey)
      - SESSION_TOKEN=$(echo ${CRED} | jq -r .Token)
      - |
        curl -vf "関数の URL" \
          -H "content-type: application/json" \
          -H "X-Amz-Security-Token: ${SESSION_TOKEN}" \
          --aws-sigv4 "aws:amz:${AWS_REGION}:lambda" \
          --user "${ACCESS_KEY}:${SECRET_ACCESS_KEY}"

  post_build:
    commands:
      - echo Post Build started on `date`

上記の buildspec を実際に活用している例は以下にソースコードサンプルがありますので活用いただければと思います。

https://github.com/t-maru078/code-pipeline-github-webhook-cdk

まとめ

今回は Lambda Function URL の認証タイプを AWS_IAM に設定している場合の呼び出し時の注意事項と curl を使って呼び出す場合の例をご紹介しました。

ある程度 AWS や開発の知識があると、とりあえず作るかという思考になりがちだったりしますが curl のようにツールによってはデフォルトで AWS の署名リクエストに対応しているものもありますので、自作する前にまず使えるものがないか調査するとことをおすすめします。