この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
CognitoやAuth0を使って、API GatewayのLambdaオーソライザーで「OK・NG」を判断することは多いと思います。 このとき、一部のAPIを公開したくなったので、試してみました。
OpenAPIを使った場合は、下記をご覧ください。
おすすめの方
- AWS SAMでLambdaオーソライザーを作りたい方
- AWS SAMで一部のAPI(Lambda)にLambdaオーソライザーを適用したくない方
サーバーレスアプリを作成する
sam init
sam init \
--runtime python3.8 \
--name Lambda-Authorizer-Sample \
--app-template hello-world \
--package-type Zip
SAMテンプレート
Lambda自体は3つ作成します。
- Lambdaオーソライザー
GET /hello
用(Authorizerあり)GET /hello2
用(Authorizerなし)
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Lambda-Authorizer-Sample
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: dev
Auth:
DefaultAuthorizer: MyLambdaAuthorizer
Authorizers:
MyLambdaAuthorizer:
FunctionArn: !GetAtt AuthorizerFunction.Arn
Identity:
ReauthorizeEvery: 0
# Lambda Authorizer
AuthorizerFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: authorizer.lambda_handler
Runtime: python3.8
Timeout: 5
AuthorizerFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${AuthorizerFunction}
# API: GET /hello (Authorizerあり)
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Timeout: 5
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
RestApiId: !Ref MyApi
HelloWorldFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorldFunction}
# API: GET /hello2 (Authorizerなし)
HelloWorld2Function:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Timeout: 5
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello2
Method: get
RestApiId: !Ref MyApi
Auth:
Authorizer: NONE
HelloWorld2FunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorld2Function}
Outputs:
HelloWorldApi:
Value: !Sub "https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/dev/hello"
Lambdaコード
Authorizer
authorization
がabc
ならOKとしています。
authorizer.py
def lambda_handler(event, context):
token = event['authorizationToken']
effect = 'Deny'
if token == 'abc':
effect = 'Allow'
return {
'principalId': '*',
'policyDocument': {
'Version': '2012-10-17',
'Statement': [
{
'Action': 'execute-api:Invoke',
'Effect': effect,
'Resource': event['methodArn']
}
]
}
}
GET /hello
用
GET /hello2
と共通です。
app.py
import json
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': json.dumps({
'message': 'hello world',
}),
}
デプロイ
sam build
sam package \
--output-template-file packaged.yaml \
--s3-bucket cm-fujii.genki-deploy
sam deploy \
--template-file packaged.yaml \
--stack-name Lambda-Authorizer-Sample-Stack \
--s3-bucket cm-fujii.genki-deploy \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
動作確認
APIエンドポイントを取得する
aws cloudformation describe-stacks \
--stack-name Lambda-Authorizer-Sample-Stack \
--query 'Stacks[].Outputs'
GET /hello
Authorizationあり(OK)
curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello \
--header 'authorization: abc'
{"message": "hello world"}
Authorizationあり(NG)
curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello \
--header 'authorization: xxx'
{"Message":"User is not authorized to access this resource with an explicit deny"}
Authorizationなし(NG)
curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello
{"message":"Unauthorized"}
GET /hello2
Authorizationなし(OK)
curl https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello2
{"message": "hello world"}