Python

AWSのS3のファイルを表示するLambda関数を作ってAPIGatewayから実行するまでをChatGPT先生に教えてもらった

ChatGPT先生に教えてもらう第二弾はLambdaとAPIGatewayです。

Lambda関数はPythonを使いたいと思います。

やりたいこと

APIのパスパラメーターで指定したIDをファイル名に持つテキストファイルを、S3の特定のディレクトリから読み込んで、そのまま返却するだけのAPIを作りたいんじゃっ

早速先生に手順を聞いてみる

挨拶は人間として基本です。先生はいつもニコニコ機嫌がよくて優しい。

長いので省略しますが以下のような手順だそうです。

  1. Lambda関数の作成
  2. API Gatewayの作成
  3. リソースとメソッドの設定
  4. リソースのデプロイ
  5. APIのテスト
  6. APIのカスタムドメインの設定(オプション)
  7. セキュリティの設定(オプション)
  8. APIのデプロイ

④のリソースのデプロイってのがちょっと意味不明でしたが流れとかキーワードなどがざっくり把握できます。

とりあえずサンプルプログラムをください!

まだAWSコンソールにログインすらしていませんが、とりあえず貰えるものを先にもらいたい性分なのでプログラムを書いてもらいました。

①Lambda関数の作成で、pyhtonを使用して、S3からjsonファイルを読み込んでそのままレスポンスボディとして返却するプログラムを見せてもらえませんか?/get/{id}/ のようなURLのエンドポイントで、{id}を受け取って{id}.jsonのファイルを取得するコードサンプルを見せてください。
import json
import boto3

s3 = boto3.client('s3')

def lambda_handler(event, context):
    # URLのパラメータから{id}を取得
    id = event['pathParameters']['id']

    # S3バケットとオブジェクトキーを指定
    bucket_name = 'your-s3-bucket'
    object_key = f'{id}.json'

    try:
        # S3からJSONファイルを読み込む
        response = s3.get_object(Bucket=bucket_name, Key=object_key)
        json_content = response['Body'].read().decode('utf-8')
        json_data = json.loads(json_content)

        # レスポンスを構築
        response_data = {
            'statusCode': 200,
            'body': json.dumps(json_data),
            'headers': {
                'Content-Type': 'application/json'
            }
        }
        return response_data

    except Exception as e:
        # エラーハンドリング
        response_data = {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)}),
            'headers': {
                'Content-Type': 'application/json'
            }
        }
        return response_data

 

S3バケットの作成

ここからはAWSコンソールでの作業のためGoogleで検索してAWSのドキュメントなどを参考に準備していきました。

Amazon S3のコンソールから「バケットを作成」で作成します。以下のようなセッティングにしました。
・ACL無効
・パブリックアクセスをすべてブロック
・バケットのバージョニング無効
・暗号化タイプ:AmazonS3マネージドキー
・バケットキー有効
・オブジェクトロック無効
そしてサンプルファイルを一つアップロードしておきました。

Lambda関数の作成

AWS Lambdaのコンソールから「関数の作成」を実行します。以下のようなセッティングにしました。
・一から作成
・ランタイム:Python 3.11
・アーキテクチャ:x86x64
・実行ロール:基本的なLambdaアクセス権限で新しいロールを作成

作成したLambda関数のコード欄にChatGPT先生にいただいたサンプルをペタリしてS3のバケット名やオブジェクトキー(ファイルのパス)を変更して、テストを行いました。

しかしAccessDeniedエラーが出ます。S3ファイルにアクセスできないようです。
S3バケットに対するアクセス権を設定する必要があります。

Lambda関数のロールにS3へのアクセス権を設定する

IAMのコンソールで、Lambda関数作成した時に作られたロールを確認します。Lambda実行に関する基本的なポリシーがすでに設定されています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:ap-northeast-1:xxxxxxxxxxxx:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:xxxxxxxxxxxx:log-group:/aws/lambda/my-lambda-function-name:*"
            ]
        }
    ]
}

 

ポリシーの編集ページで新しくポリシーを作成します。先ほど作成したS3バケットへのアクセス(get, post, put)を許可するポリシーを設定します。コンソールからポリシーエディタのチェックボックスで権限をチェックしてもいいし、ポリシー編集画面にjsonを貼り付けでもよいです。権限設定はS3側のポリシーにすることもできます(書き方は違います)。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::my-s3-bucket/*"
        }
    ]
}

 

上記のポリシーを、先ほどのロールの編集画面で「許可を追加」→「ポリシーをアタッチ」で適用します。

この状態で再度Lambda関数のテストを行うと無事ファイルを取得して表示することが出来ました。

API Gatewayの作成

API GatewayコンソールからAPIを作成します。下記のようなセッティングにしました。
・APIタイプ:REST API
・APIの詳細:新しいAPI
・APIエンドポイントタイプ:リージョン

作成したAPIの管理画面で、リソースを作成します。
リソースはディレクトリ構造のようになっていて、これがURLというかエンドポイントとなっていきます。

「test/{id}」というリソースを作成します。この{}はパスパラメーターとなります。

この{id}リソースに対してGETメソッドを作成します。以下のようなセッティングにしました。
・統合タイプ:Lambda関数
Lambdaプロキシ統合を有効にします!(大事)
・Lambda関数:作成したLambda関数のARNを指定します。

「Lambdaプロキシ統合」を有効にすると、Lambda関数の中で上記の{id}をパスパラメーターとして簡単に利用することができます。Lambda関数内ではevent[‘pathParameters’][‘id’]の中に格納されることになります。

API Gatewayのメソッドの「テスト」タブでidを指定してテストすることが出来ます。

テストしてみると無事に指定したidのファイル名のjsonがS3から取得できました。

この状態で「APIをデプロイ」ボタンを押して、ステージを作成(prodとかstgとか)してデプロイすると、APIのURLが発行されてAPIが利用できるようになります。

まとめ

ChatGPT先生はキャプチャを例示してくれないので、管理画面操作などが絡む事のレクチャーには不向きかなと思いました。

しかし大まかな流れを知りたい、調べるためのキーワードすらわからないようなときには色々聞いてみるのが良いと思います。

また、設定で詰まった時などは解決につながるヒントが得られるかもしれません。

reiko suzuki
OLD SKOOLシステムエンジニア。ねこを撫でながら働いています。