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

注目のタグ

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

    こんにちは、上野です。

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

    aws.amazon.com

    今までのLambda

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

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

    やってみる

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

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

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

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

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

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

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

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

    IAM認証

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

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

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

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

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

    どんな情報が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エラーとなります。

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

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

    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単体で使えるアップデートが来ちゃいました。

    それではまた!

    執筆者上野史瑛

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