LoginSignup
1
0

Amazon API Gateway : Lambdaオーソライザーの認可結果に応じたファイルをS3から取得

Last updated at Posted at 2023-09-25

初めに

プロジェクトを進めている際にS3からファイルを取得するAPIを外部ユーザー向けに用意することになりました。追加の制約事項は以下の通りです。

  • 権限を持つユーザーのみアクセスできる
  • S3上のディレクトリはユーザーごとに分かれている
    (バケット名/部署ID/ユーザーIDのようなパスになっている)
  • ユーザーはファイル名を指定するだけでそれぞれのフォルダからファイルを取得することができる
    (S3のフォルダ構成を意識する必要がない)

SDKを利用して作成することもできたのですが、API GatewayのLambdaオーソライザーを試したかったのでそちらで作成してみました。作成手順をこの記事にて紹介させて頂きます。

Amazon API Gateway

Amazon API GatewayはAWS上で効率的にAPIを作成し公開できるサービスです。その他AWSサービスと統合することでS3やLambdaなどのプロキシとして作成することができます。詳細は公式デベロッパーガイドをご参照ください。

API GatewayのLambdaオーソライザー

API Gatewayで作成したAPIの認可方法としてLambda関数を設定することができます。それがLambdaオーソライザーです。独自の認可処理を組み込めるだけでなく、認可情報に基づいてAPIの処理を分岐させることもできます。

Lambdaオーソライザーの認可結果に応じたファイルをS3から取得するAPIの作成

今回の要件を実現するAPIの作成手順について説明します。

認可用Lambda関数の作成

Lambda関数の新規作成

最初に認可用のLambda関数を用意します。画面に従って空のLambda関数を作成します。
Lambda関数の作成.PNG

認可処理の記述

Lambda関数に認可処理を記述します。戻り値にはAPI実行を許可または拒否するIAMポリシーをJSONで返却する必要があります。今回の要件の一つに「ユーザーごとのフォルダからファイルを取得する」というものがありますので、Lambdaオーソライザーで取得した認可情報もAPIに伝えておく必要があります。そういう時に利用できるのがContextです。Contextにはカスタムプロパティを自由に追加することが可能で、またIAMポリシーとともに返却することで、後続処理にカスタマイズされた認可情報を引き渡すことができます。後続処理でのContextの利用方法は「APIの作成」で説明します。Lambdaの詳細は下記コードをご参照ください。

app.py
def lambda_handler(event, context):
    user = event["headers"]["user"]
    password = event["headers"]["password"]

    user_info = validate(user, password)
    if user_info is not None:
        return generate_policy("execute-api:Invoke", "Allow", event["methodArn"], user_info)
    else:
        return generate_policy("execute-api:Invoke", "Deny", event["methodArn"])

def generate_policy(action, effect, resource, user_info=None):
    policy = {
        "principalId": "*",
        "policyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": action,
                    "Effect": effect,
                    "Resource": resource,
                }
            ],
        },
    }
    if user_info is not None:
        policy["context"] = {
            "user_id": user_info["user_id"],
            "group_id": user_info["group_id"],
        }
    return policy

def validate(user, password):
    if user == 'user1' and password == 'user1_pass':
        return {
            'user_id': '10001',
            'group_id': 'Group1',
        }
    elif user == 'user2' and password == 'user2_pass':
        return {
            'user_id': '10002',
            'group_id': 'Group2',
        }
    else:
        return None

APIの作成

次にAPI GatewayにS3アクセス用のAPIを作成します。下記の通りREST APIを新規作成します。
REST APIの作成.PNG

オーソライザーの作成

APIの作成が完了したらAPI画面でオーソライザーを作成します。Lambda関数を呼び出すための権限をAPI Gatewayに追加する必要があるため、作成時に権限追加について確認するダイアログが表示されます。そのまま「付与及び作成」ボタンを押下することで自動で必要な権限が付与されます。
オーソライザイー作成.PNG

Lambdaイベントペイロードではトークンまたはリクエストを選択できます。トークンの場合、Lambda関数のeventパラメータに引き渡す認可用ヘッダの名前と認可用ヘッダの事前チェックを設定することができます。リクエストの場合、認可パラメータの取得元を指定します。Lambda関数にはリクエスト全体が引き渡されます。

リソースの作成

アクションボタンからリソースを作成します。
リソースの作成.PNG

メソッドの作成

アクションボタンからS3と統合したGETメソッドを作成します。「パス上書き」には取得するファイルのS3上でのパスを指定します。ブレースで囲ったパス変数はマッピング元を指定することで動的に置き換えることができます。
メソッドの作成.PNG

オーソライザーとクエリパラメーターの設定

認可に先ほど作成したLambdaオーソライザーを設定します。また、取得するファイル名を指定する必要があるためクエリパラメーターを設定します。
オーソライザーの設定.PNG

パスパラメータの設定

パス変数のマッピング元を指定します。上記の通りファイル名({file_name})はクエリ文字列のfile_nameから取得するためmethod.request.queryString.file_nameを指定します。LambdaオーソライザーからContextに出力したカスタムプロパティはcontext.authorizer.プロパティ名でアクセスできます。{group_id}{user_id}のマッピング元にそれぞれLambdaオーソライザーから出力したものを指定します。
パスパラメータの指定.PNG

デプロイ

以上で最低限の準備が整いましたのでAPIをデプロイします。
デプロイ.PNG

APIのテスト

今回はテスト用に下記のようなテキストファイルを用意しました。
ユーザー情報テキストファイル.PNG

それぞれ異なるパスに配置します。
S3ユーザー情報1.PNG
S3ユーザー情報2.PNG

試しにPostmanで実行してみます。
Postmanユーザー情報1.PNG
Postmanユーザー情報2.PNG

ユーザー情報に応じたファイルの取得に成功しました。

最後に

表題の要件に合致する内容がなかなか見つからなかったため簡単ですがこちらでまとめさせて頂きました。誰かの助けになれば幸いです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0