Lambda から IAM 認証が有効な API Gateway にアクセスしてみた

AWS ナレッジセンターの内容をやってみました
2023.02.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

アノテーション株式会社の hato です。

API Gateway で IAM 認証を有効にすると、必要な権限(execute-api:Invoke)をもった IAM 認証情報が含まれるリクエストのみにアクセスを限定することができます。

IAM 認証が有効な API Gatewayを作成する方法は AWS ナレッジセンターにて公開されていますが、実際に構築したことはなかったのと、お問い合わせ頂いた際に備えて画面キャプチャを取得するため、やってみました。

なお、今回はリクエストの送信元(クライアント)に Lambda 関数を使用しています。

やってみた

前提

API Gateway には次の固定値を返却する Mock エンドポイントをデプロイ済み(IAM 認証は無効な状態)

{
    "statusCode": 200,
    "message": "Hello, world!"
}

構成イメージ

手順

  1. IAM 認証の有効化
  2. Lambda 関数のコード作成
  3. Lambda 関数の作成
  4. テスト

1. IAM 認証の有効化

API Gateway コンソールの「リソース」ペインから、IAM 認証を有効にするメソッドを選択します。

「メソッドリクエスト」を選択します。

「認可」の鉛筆マークを選択します。

「AWS IAM」を選択してチェックマークを選択します。

「アクション」 -> 「API のデプロイ」を選択します。

「デプロイ」を選択します。

呼び出し URL は後ほどクライアントに設定するため、書き留めます。

2. Lambda 関数のコード作成

API Gateway に AWS の署名バージョン 4 で署名したリクエストを送信するサンプルコードを作成します。
署名バージョン 4 の署名には requests-aws4auth を使用しています。

作業用のディレクトリを作成します。

$ mkdir my-sourcecode-function
$ cd my-sourcecode-function

エディタで次のサンプルコードを作成します。
※6行目は「呼び出し URL」に修正してください。

lambda_function.py

import boto3
import requests
from requests_aws4auth import AWS4Auth

def lambda_handler(event, context): 
    url = "<API_GATEWAY_URL>"
    credentials = boto3.Session().get_credentials()
    region = 'ap-northeast-1'
    service = 'execute-api'
    
    auth = AWS4Auth(
        credentials.access_key,
        credentials.secret_key,
        region,
        service,
        session_token=credentials.token,
    )
    response = requests.get(url, auth=auth)
    return(response.json())

pipで周辺モジュールをインストールして、ZIP圧縮します。

$ pip install --target ./package requests requests_aws4auth
...(中略)...
Successfully installed certifi-2022.12.7 charset-normalizer-3.0.1 idna-3.4 requests-2.28.2 requests-aws4auth-1.1.2 six-1.16.0 urllib3-1.26.14

$ cd package
$ zip -r ../my-deployment-package.zip .
...(中略)...
  adding: bin/ (stored 0%)
  adding: bin/normalizer (deflated 27%)

$ cd ..
$ zip -g my-deployment-package.zip lambda_function.py
  adding: lambda_function.py (deflated 47%)

3. Lambda 関数の作成

クライアントとなる Lambda 関数を作成します。

Lambda コンソールを開き、関数から「関数の作成」をクリックします。

次の値を指定して「関数の作成」を選択します。

  • 関数名:任意の名前(例:hato-client-lambda
  • ランタイム:Python 3.9

Lambda の作成後、API Gateway のアクセスに必要な権限を設定します。
「設定」タブの「アクセス権限」を選択します。

ロール名のリンクをクリックします。

「許可の追加」から「ポリシーのアタッチ」を選択します。

許可ポリシーから「AmazonAPIGatewayInvokeFullAccess」ポリシーを選択して、「ポリシーをアタッチ」をクリックします。
※すべての API Gateway の呼び出し権限が付与されるため、AWS 公式ドキュメントを参考に最小権限を付与することを推奨します。

IAM ロールが正常に更新されたことを確認します。

作成したサンプルコードを設定します。 「アップロード元」から「.zipファイル」を選択

手順2で作成したサンプルコード(ZIP)を選択します。

Lambda 関数が正常に更新されたことを確認します。

テスト

「テスト」タブを選択します。

「テスト」を選択します。

API Gateway に設定した固定値が取得できました。

{
    "statusCode": 200,
    "message": "Hello, world!"
}

なお、リクエストに認証情報がない場合はMissing Authentication Tokenが返却されます。

{
    "message": "Missing Authentication Token"
}

認証情報はあるが権限が足りない場合は、次のような値となります。

{
  "Message": "User: arn:aws:sts::123456789012:assumed-role/hato-client-lambda-role-kopdzhfl/hato-client-lambda is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:********9012:abcdef123/dev/GET/"
}

最後に

この記事が誰かのお役にたてば幸いです。

参考資料

アノテーション株式会社について

アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。