NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

[新機能] AWS Lambda Function URLで簡単にLambda関数を実行する

こんにちは、上野です。

Lambda関数をワンクリックでURL公開できる機能が出ました!

aws.amazon.com

今までのLambda

Lambda関数を(AWS認証無しの)HTTPS経由で実行するには、Lambdaの前段にAmazon API Gatewayを設置する必要がありました。 API Gatewayは便利で高機能なのですが、設定項目も多く、初めて触る方には難しい部分もあるかと思います。

f:id:fu3ak1:20220408110533p:plain

今回の機能で、Lambdaのメニューから機能をONにするだけHTTPS公開できるようになりました。

f:id:fu3ak1:20220408110835p:plain

やってみる

Lambdaの作成画面に、「関数URLを有効化」のメニューが追加されているので、これをONにします。

f:id:fu3ak1:20220407144448p:plain

f:id:fu3ak1:20220407144327p:plain

初期状態では認証が必要なAWS_IAMが選択されていますが、今回はまずどれだけ簡単に公開できるかを試すため、NONEを選択します。

※画面のとおり、URLを使用して全世界からLambdaをURL経由で実行できるようになるため、設定時は注意が必要です。

f:id:fu3ak1:20220407144637p:plain

コードは以下のとおり初期状態からテキスト文言を変えただけです。

f:id:fu3ak1:20220407164328p:plain

import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': json.dumps('This is Public URL Lambda!')
    }

この状態で関数URLにアクセスすると、

f:id:fu3ak1:20220407164544p:plain

以下のようにコードに書いた内容がブラウザで返ってきます。爆速でLambdaをURLとして公開できましたね。

f:id:fu3ak1:20220407164712p:plain

他の機能も試していきます。

IAM認証

IAM認証をONにして、認証を使用したアクセスを試してみます。

f:id:fu3ak1:20220407224125p:plain

ONの状態でURLにアクセスすると、以下のようにエラーとなります。

f:id:fu3ak1:20220407224303p:plain

ドキュメントには、AWS Signature Version 4 (SigV4)を使用してアクセスしましょうと説明があります。今回はPostmanを使用して試してみます。

Authorizationの設定で、TypeにAWS Signatureを選択すると、AWSの認証情報入力欄が表示されます。IAMユーザーのアクセスキー、AWS SSOの一時認証情報、IAMロールを使用した一時キー(参考)いずれかを取得してその内容を入力します。

f:id:fu3ak1:20220407234657p:plain

この状態でLambdaのURLへアクセスすると、いかのように結果が表示されます。認証できていることがわかりますね。

f:id:fu3ak1:20220407235122p:plain

どんな情報がLambdaに渡るの?

以下のようにLambdaのコードを修正して、実際にLambdaに渡されるデータeventを表示してみます。

import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': json.dumps(event, indent=2)
    }

まずは以下のようにURLのクエリストリングにパラメータを渡してみます。(hogehogeの部分にURLのIDが入ります)

curl https://hogehoge.lambda-url.ap-northeast-1.on.aws/?param1=hoge
 {
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/",
  "rawQueryString": "param1=hoge",
  "headers": {
    "x-amzn-trace-id": "Root=1-624efbbc-13cb25d619ceadfe0cb469bc",
    "x-forwarded-proto": "https",
    "host": "hogehoge.lambda-url.ap-northeast-1.on.aws",
    "x-forwarded-port": "443",
    "x-forwarded-for": "1.2.3.4",
    "accept": "*/*",
    "user-agent": "curl/7.68.0"
  },
  "queryStringParameters": {
    "param1": "hoge"
  },
  "requestContext": {
    "accountId": "anonymous",
    "apiId": "hogehoge",
    "domainName": "hogehoge.lambda-url.ap-northeast-1.on.aws",
    "domainPrefix": "hogehoge",
    "http": {
      "method": "GET",
      "path": "/",
      "protocol": "HTTP/1.1",
      "sourceIp": "1.2.3.4",
      "userAgent": "curl/7.68.0"
    },
    "requestId": "21e5f8ee-bf99-4643-8f19-386978967955",
    "routeKey": "$default",
    "stage": "$default",
    "time": "07/Apr/2022:14:57:00 +0000",
    "timeEpoch": 1649343420924
  },
  "isBase64Encoded": false
} 

headers情報等、リクエスト関連の情報とともに、クエリストリングのデータはqueryStringParametersに入っていました。

続いてPOSTでJSONのデータを送信。

curl -X POST \
      'https://hogehoge.lambda-url.ap-northeast-1.on.aws/' \
      -H 'content-type: application/json' \
      -d '{ "example": "test" }'
{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/",
  "rawQueryString": "",
  "headers": {
    "x-amzn-trace-id": "Root=1-624efdf3-13cc447566739b4c555c2b54",
    "x-forwarded-proto": "https",
    "host": "hogehoge.lambda-url.ap-northeast-1.on.aws",
    "x-forwarded-port": "443",
    "content-type": "application/json",
    "x-forwarded-for": "1.2.3.4",
    "accept": "*/*",
    "user-agent": "curl/7.68.0"
  },
  "requestContext": {
    "accountId": "anonymous",
    "apiId": "hogehoge",
    "domainName": "hogehoge.lambda-url.ap-northeast-1.on.aws",
    "domainPrefix": "hogehoge",
    "http": {
      "method": "POST",
      "path": "/",
      "protocol": "HTTP/1.1",
      "sourceIp": "1.2.3.4",
      "userAgent": "curl/7.68.0"
    },
    "requestId": "ee55df23-4c65-4bcf-b161-7a6b7f78d291",
    "routeKey": "$default",
    "stage": "$default",
    "time": "07/Apr/2022:15:06:27 +0000",
    "timeEpoch": 1649343987925
  },
  "body": "{ \"example\": \"test\" }",
  "isBase64Encoded": false
}

POSTしたデータはbodyに入っていました。 送られてきたデータをLambdaで処理、という実装も簡単にできそうです。

CORS

デフォルト状態ではCORSが無効のため、S3WEBホスティング等に格納したJavascriptコンテンツから、Lambda URLを呼び出すとエラーになります。ここもLambda URLの設定で簡単に解決できるので、試してみます。

以下のようにhtml上のボタンを押下すると、Lambda URLを呼び出すHTML(+Javascript)をS3のWEBホスティング上に格納します。

<head>
    <title></title>
    <script language="javascript" type="text/javascript">
        function execLambda() {
            const xhr = new XMLHttpRequest();
            const url = 'https://hogehoge.lambda-url.ap-northeast-1.on.aws/';

            xhr.open('GET', url);
            xhr.send();
        }
    </script>
</head>
<body>
    <input type="button" value="Exec" onclick="execLambda();"/><br />
    <br />
    <div id="output"></div>
</body>
</html>

ボタンを押下すると、以下のようにCORSエラーとなります。

f:id:fu3ak1:20220408002325p:plain

これをCORSを有効にすると・・(今回はONにするだけで各設定は変更しません)

f:id:fu3ak1:20220408002605p:plain

以下のようにLambdaから正常に応答が返ってきます。

f:id:fu3ak1:20220408002931p:plain

API Gatewayとの比較

公式アナウンスブログにも書かれていますが、API Gatewayには以下のような機能があるのでこれを使いたい場合はAPI Gateway+Lambdaで実装したほうが良さそうです。

  • リクエスト検証機能
  • API Keyによる認証
  • 使用量プランによる流量制御
  • AWS WAFの使用
  • カスタムドメイン

料金について

Lambda function URLsの料金はかからず、Lambdaの実行料金に含まれます。つまり(URLの追加設定分は)無料。嬉しいですね。

まとめ

かなり嬉しい&大きなアップデートだと思います。自分は最近Slack APIのEvent Subscriptionsを使用してAPI Gateway経由でLambdaを使用していたのですが、そういったレベルであればLambda function URLsで充分かと思います。 AWS SAMやCDK等のIaCツールを使用すればそれなりに簡単にAPI Gatewayも設定できるのですが、設定項目も多く、やりたいことに対して少しtoo muchな感じがあったので、サクッと処理を作りたいときにこの機能が役立ちそうです。

私はLambdaの紹介記事も書いたことがあり、そこでは「Lambdaは基本他のサービスと組み合わせて使います」と紹介していましたが、Lambda単体で使えるアップデートが来ちゃいました。

それではまた!

f:id:fu3ak1:20210325095452j:plain

執筆者上野史瑛

Japan APN Ambassador 2020
AWSを中心としたクラウドの導入、最適化を専門に行っています。