大田区から発信するゆるゆる日記

主にITエンジニアに関する備忘録日記。たまに趣味も。何か不備があればコメント頂けると幸いです。Twitterアカウント https://twitter.com/ryuzan03

【AWS/Python】Lamdaオーソライザー リクエストパラメーター × IPアドレス制限(1/2)

※下記の内容に不備がありましたら、コメント頂けると幸いです。また、下記の内容をご使用頂ける場合は自己責任でお願いします。

概要

Lambdaオーソライザーでリクエストパラメーターベースの認証とIPアドレス制限を実装します。

AWSの公式サイトでは、IPアドレス制限はリソースポリシーで実装するのが一般的なようです。 API Gateway リソースポリシーが認証ワークフローに与える影響 - Amazon API Gateway

今回のIPアドレス制限は、何かしらの理由でリソースポリシーを使わない想定で、LambdaオーソライザーでIPアドレス制限を実装していきます。

Lamdaオーソライザー リクエストパラメーター実装

構成

AWS公式サイトを元に簡単な構成図を作成しました。
以下ページのリクエストパラメータベースを参考にしました。
API Gateway Lambda オーソライザーを使用する - Amazon API Gateway

Lambdaオーソライザー
Lambdaオーソライザー 構成図


リクエストベースの Lambda オーソライザー関数を作成

Lambdaコンソールでオーソライザー用の関数を作成します。

オーソライザー用の設計図が用意されているのですが、ランタイムがpython2.7であること、コードが多いことから、公式サイトのNode.jsのコードと設計図を参考に自作で作成しました。

Lambdaコンソールで「関数の作成→一から作成」を選択し、以下のコードを貼り付けてデプロイします。

api-auth.py

def handler(event, context):
    headers = event['headers']
    queryStringParameters = event['queryStringParameters']
    pathParameters = event['pathParameters']
    stageVariables = event['stageVariables']

    tmp = event['methodArn'].split(':')
    apiGatewayArnTmp = tmp[5].split('/')
    awsAccountId = tmp[4]
    region = tmp[3]
    restApiId = apiGatewayArnTmp[0]
    stage = apiGatewayArnTmp[1]
    method = apiGatewayArnTmp[2]
    resource = '/'
    if apiGatewayArnTmp[3]:
        resource += apiGatewayArnTmp[3]

    if headers['headerauth1'] == 'headerValue1':
        return generate_allow('me', event['methodArn'])
    else:
        return generate_deny('me', event['methodArn'])


def generate_policy(principalId, effect, resource):
    # if effect and resource:
    authResponse = {
        'principalId': principalId,
        'policyDocument': {
            'Version': '2012-10-17',
            'Statement': [{
                'Action': 'execute-api:Invoke',
                'Effect': effect,
                'Resource': [resource]
            }]
        },
        'context': {
            'stringKey': 'stringval',
            'numberKey': 123,
            'booleanKey': True
        }
    }

    return authResponse


def generate_allow(principalId, resource):
    return generate_policy(principalId, 'Allow', resource)


def generate_deny(principalId, resource):
    return generate_policy(principalId, 'Deny', resource)

必要ない変数もあると思うので、要件に合わせて調整しください。


検証用のLambdaとAPIを作成

Lambdaのコンソール画面、及びにAPI Gatewayのコンソール画面からLambda関数とAPI(REST API)を作成します。

こちらの説明は割愛させていただきます。


オーソライザーを作成

API Gatewayコンソール画面の左帯にある「オーソライザー」からオーソライザーを作成します。

「Lambda関数」の項目には、先ほど作成したオーソライザー用のLamabda関数を選択します。

APIGateway オーソライザー
APIGateway オーソライザー
テストでオーソライザーがちゃんと作動しているか一度確認しておきましょう。


オーソライザーを検証用APIに設定

API Gatewayコンソール画面の左帯にある「リソース」からオーソライザーを検証用APIに設定します。

下記のメソッドリクエストをクリックします。

APIGateway リソース
APIGateway リソース 設定前

認可を先ほど作成したオーソライザーに設定する。

この時、2点注意しなければならない箇所があります。
1つ目は赤丸のチェックボタンをクリックしてください。
2つ目は左上にある「アクション」セレクトボタンから「APIのデプロイ」を実行してください。

APIGateway 設定
APIGateway 設定

すると、認可の部分が先ほど作成したオーソライザーに設定ができています。

APIGateway リソース 設定後
APIGateway リソース 設定後
更新が間に合わず、上手く設定ができていないことがあるので、都度ページの更新を行いながら作業を進めることをオススメします。


【確認作業】PostmanでAPIを叩く

下記の様にheadersにパラメーターを設定して、APIを叩きます。

Postman
Postman


おまけ

  • オーソライザーのテストで400エラー発生する
    拒否になっている場合が多いですが、たまにリクエストパラメーターを間違えているケースがあります。

  • オーソライザーのテストで500エラー発生する
    コードのミス、またはLambda関数の戻り値のIAMポリシーの構成を間違えているケースがあります。

  • SAMでも実装可能そう
    いつか挑戦してみたい。 Lambdaオーソライザーの例 - AWS Serverless Application Model



今後に向けて

次回はオーソライザー用のLambdaでIPアドレス制限を実装していきます。



参考

素晴らしい記事に感謝致します。
API Gateway リソースポリシーが認証ワークフローに与える影響 - Amazon API Gateway
API Gateway Lambda オーソライザーを使用する - Amazon API Gateway
Lambdaオーソライザーの例 - AWS Serverless Application Model