/ #lambda #API Gateway 

【CDK/Python】Lambda認証付きのHTTPタイプのAPIを作る

もくじ

以前RestAPIで同じことをしていますが、今度は後発のHttpAPIで作ってみます。

では 作っていきましょう👻

プロジェクトを用意する

雛形を用意

$ mkdir cdk-http-api-lambda && cd $_
$ cdk init --language python
$ rm setup.py source.bat
$ mkdir src tests

依存パッケージ

aws-cdk.core==1.124.0

aws_cdk.aws-lambda==1.124.0
aws_cdk.aws_lambda_python==1.124.0
aws-cdk.aws_apigatewayv2==1.124.0
aws-cdk.aws_apigatewayv2_integrations==1.124.0
aws_cdk.aws_apigatewayv2_authorizers==1.124.0

ResAPIはaws_apigatewayvのモジュールなので、完全に総入れ替えです

RestAPI側の記事はこちら

インストール

$ python3 -m venv .venv
$ source .venv/bin/activate
$ pip install -r requirements.txt

Stackを用意する

aws_apigatewayv2のパッケージを使いますが、ほとんどRestAPIの場合と同じです。

その中で唯一大きな違いは、認証Lambdaの方式です。

RestAPI側はトークン認証だったのですが、HTTP API側はシンプル(type?)を使うことができるのでそちらを使います。(今回やらないですが、今まで通りの認証のやり方も可能)

from aws_cdk import core as cdk
from aws_cdk.aws_apigatewayv2 import CorsHttpMethod, HttpApi, HttpMethod
from aws_cdk.aws_apigatewayv2_authorizers import HttpLambdaAuthorizer, HttpLambdaResponseType
from aws_cdk.aws_apigatewayv2_integrations import LambdaProxyIntegration
from aws_cdk.aws_lambda import Runtime
from aws_cdk.aws_lambda_python import PythonFunction

APP_NAME = "CdkHttpApiLambda"


class CdkHttpApiLambdaStack(cdk.Stack):
    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        common_lambda_param = {"runtime": Runtime.PYTHON_3_9}
        auth_lambda = PythonFunction(self, f"{APP_NAME}AuthLambda", entry="src/authorizer", **common_lambda_param)
        app_lambda = PythonFunction(self, f"{APP_NAME}AppLambda", entry="src/app", **common_lambda_param)

        authorizer = HttpLambdaAuthorizer(
            authorizer_name="hogehoge_authorizer",
            identity_source=["$request.header.HogeAuthorization"],
            response_types=[HttpLambdaResponseType.SIMPLE], # シンプルタイプを指定
            handler=auth_lambda,
        )

        lambda_integration = LambdaProxyIntegration(handler=app_lambda)

        http_api = HttpApi(
            self,
            f"{APP_NAME}HttpApi",
            cors_preflight={
                "allow_origins": ["*"],
                "allow_headers": ["*"],
                "allow_methods": [CorsHttpMethod.ANY],
            },
        )
        http_api.add_routes(
            path="/",
            methods=[HttpMethod.ANY],
            integration=lambda_integration,
            authorizer=authorizer,
        )

余談でPython3.9がcdkでも使えるようになったので、使ってみました(笑)

アプリを書く

認証用のLambdaです。

トークン認証の場合とレスポンスが大きく変わり、必須パラメーターはisAuthorizedだけです。

この値に対して{ true | false }で認証成功/失敗を返すことができます!

お手軽ですねー

認証以外に後ろのLambdaに渡したいパラメータがあればcontextに入れればOKです。

後方のLambdaには、eventからこんな感じで受け取れます。

// eventの中身
{
    ...
    "requestContext": {
        ...
        "authorizer": {
            "lambda": {
                "hogeKey": 12345
            }
        },
        ...
}

というわけで、具体的な実装は下記。

def handler(event, context):
    res = {"isAuthorized": False}
    if event["headers"]["hogeauthorization"] == "hogehoge":
        res.update({"isAuthorized": True, "context": {"hogeKey": 12345}})
    return res

動きはRequestのheaderを見てhogeauthorizationhogehogeという値だったら許可します!

次にapp側です。

def handler(event, context):
    return {"statusCode": "200", "body": "Hello World !!"}

はい。説明不要ですね(笑)

デプロイ

下記のコマンドでデプロイ!

$ cdk deploy

動作確認

AWS環境で

# 失敗
$ curl https://767mhcfq8c.execute-api.ap-northeast-1.amazonaws.com
{"message":"Unauthorized"}
$ curl https://767mhcfq8c.execute-api.ap-northeast-1.amazonaws.com -H 'HogeAuthorization: a'
> {"message":"Forbidden"}

# 成功
$ curl https://767mhcfq8c.execute-api.ap-northeast-1.amazonaws.com -H 'HogeAuthorization: hogehoge'
Hello World !!

local環境で(おまけ)

実は今年の4月末くらいに CDKがSAMで動かせるというとんでも機能が出てます!!

ということでlocalでも動かしてみます。

導入方法はこちらを参考にしてください!

local環境でAPI起動!!

$ sam-beta-cdk local start-api --project-type CDK

エンドポイントを叩く

$ curl http://127.0.0.1:3000/
SHello World !!

はい、認証Lambda貫通でapi叩けます(汗)

SAMは認証はしてくれないのですねー。詳細は下記を御覧ください

https://github.com/aws/aws-sam-cli/issues/137

以上ですー

今回のリポジトリはこちら

https://github.com/sisi100/cdk_http_api_lambda

Author

Sisii

インフラが好きなエンジニアぶってるなにか