🐡
SAM で Lambda + APIGW (HTTP API) と Firebase Auth
TL;DR
- SAMを使うと簡単にサーバーレスでAPIを構築できる
- API Gateway + Lambda を簡単に構築できる
- API Gateway の HTTP API を使えば、JWT認証ができる
- OIDCのIDトークンによる認証ができる
- JWT認証でFirebase Authのトークンを検証できる
SAMとは
- AWS サーバーレスアプリケーションモデル
- SAM CLI を使って簡単にサーバーレスのアプリケーションを構築できる
- CloudFormationテンプレートベースのSAMテンプレートで構成を記述
- 開発用にローカルでLambda実行やAPIサーバーの起動も容易
API Gateway HTTP APIとは
- Amazon API Gateway とは何ですか?
- API Gateway は、APIの作成とか管理とかができるサービス
- API Gateway には、何種類かあってその中の2つが REST API と HTTP API
- 比較は次が参考になると思う
- 今回関わる主な違いとしては、HTTP APIはJWT認証ができること
SAM + ApiGW (HTTP API) でJWT認証する
- AWS CLI/SAM CLIのインストールから、Firebase Authのトークン検証を行うエンドポイントを作るまで
AWS CLIインストール
- Install or update the latest version of the AWS CLI に従う
- Ubuntuの場合
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
SAM CLIインストール
- Installing the AWS SAM CLI に従う
- Ubuntuの場合
curl -L https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip -o aws-sam-cli-linux-x86_64.zip
unzip aws-sam-cli-linux-x86_64.zip -d sam-installation
sudo ./sam-installation/install
SAMアプリケーションを作る
-
sam init
コマンドを使ってアプリケーションの初期化を行う- ランタイムは Go を使う
- AWS Quick Start Templates (Hello World Example) を利用
- x-rayとかcloudwatch insightsとかはなし
- プロジェクト名は適当に sam-ple とした
sam init --runtime go1.x
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Infrastructure event management
3 - Multi-step workflow
Template: 1
Based on your selections, the only Package type available is Zip.
We will proceed to selecting the Package type as Zip.
Based on your selections, the only dependency manager available is mod.
We will proceed copying the template using mod.
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: n
Would you like to enable monitoring using CloudWatch Application Insights?
For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwat
ch-application-insights.html [y/N]: n
Project name [sam-app]: sam-ple
-----------------------
Generating application:
-----------------------
Name: sam-ple
Runtime: go1.x
Architectures: x86_64
Dependency Manager: mod
Application Template: hello-world
Output Directory: .
Configuration file: sam-ple/samconfig.toml
Next steps can be found in the README file at sam-ple/README.md
Commands you can use next
=========================
[*] Create pipeline: cd sam-ple && sam pipeline init --bootstrap
[*] Validate SAM template: cd sam-ple && sam validate
[*] Test Function in the Cloud: cd sam-ple && sam sync --stack-name {stack-name} --watch
- 以下コマンドでAPIサーバーをローカルで起動し、動作確認
- ログは長いので省略
-
Hello, 127.0.0.1!
が返ってくる
cd sam-ple
sam build
sam local start-api
curl localhost:3000/hello
デプロイ
- aws cli の認証情報を設定
- 例えば、
aws configure
でAPIキー入れる
- 例えば、
-
sam deploy --guided
- ガイドにそって進めていけばデプロイできる
-
https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/
にブラウザでアクセス- このURLは
sam deploy
のログに出力されている -
Hello, {IP Address}!
が表示される
- このURLは
カスタマイズする
- 以下2つのカスタマイズをする
- API Gateway の種類を REST API から HTTP API に変える
- JWT認証でFirebase Authのトークンを検証できるようにする
-
template.yaml
を編集
@@ -11,7 +11,27 @@ Globals:
Timeout: 5
MemorySize: 128
+Parameters:
+ JwtIssuer:
+ Type: String
+ JwtAudience:
+ Type: String
+
Resources:
+ MyApi:
+ Type: AWS::Serverless::HttpApi
+ Properties:
+ StageName: Prod
+ Auth:
+ Authorizers:
+ OAuth2Authorizer:
+ IdentitySource: $request.header.Authorization
+ JwtConfiguration:
+ Issuer: !Ref JwtIssuer
+ Audience:
+ - !Ref JwtAudience
+ DefaultAuthorizer: OAuth2Authorizer
+
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
@@ -22,8 +42,9 @@ Resources:
- x86_64
Events:
CatchAll:
- Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
+ Type: HttpApi # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
+ ApiId: !Ref MyApi
Path: /hello
Method: GET
Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
@@ -36,7 +57,7 @@ Outputs:
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
HelloWorldAPI:
Description: "API Gateway endpoint URL for Prod environment for First Function"
- Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
+ Value: !Sub "https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: "First Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
- 解説その1 API Gateway の種類を REST API から HTTP API に変える
- Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
+ Type: HttpApi # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
- 解説その2 JWT認証でFirebase Authのトークンを検証できるようにする
- API Gatewayを個別に定義し、JWT認証を指定する
- トークンは
Authorization
ヘッダに乗せる -
OAuth2Authorizer を参考にしたので、
OAuth2Authorizer
になっている
- トークンは
- API Gatewayを個別に定義し、JWT認証を指定する
+Parameters:
+ JwtIssuer:
+ Type: String
+ JwtAudience:
+ Type: String
+
Resources:
+ MyApi:
+ Type: AWS::Serverless::HttpApi
+ Properties:
+ StageName: Prod
+ Auth:
+ Authorizers:
+ OAuth2Authorizer:
+ IdentitySource: $request.header.Authorization
+ JwtConfiguration:
+ Issuer: !Ref JwtIssuer
+ Audience:
+ - !Ref JwtAudience
+ DefaultAuthorizer: OAuth2Authorizer
+
-
- ↑で定義した
MyApi
を指定するように変更
- ↑で定義した
+ ApiId: !Ref MyApi
- Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
+ Value: !Sub "https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
-
samconfig.yaml
にパラメータを追加する- FirebaseのProject IDが必要
- Firebaseにプロジェクト作ってIDを取得する
- Firebase Authのセットアップもしておく
- (Firebaseのセットアップについては深堀しないので、他の記事とかを検索してください)
- (Firebase Auth以外を使う場合はここを変える)
[default.deploy.parameters]
(省略)
parameter_overrides = [
"JwtIssuer=https://securetoken.google.com/{firebase-project-id}",
"JwtAudience={firebase-project-id}"
]
再ビルド&デプロイ
sam build
sam deploy
-
https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello
にブラウザでアクセス-
{"message":"Unauthorized"}
が返ってくる (ステータス401) - 最後の
/
(スラッシュ) があると、Not Found(404) が返ってくるかも
-
- Firebase Authのトークンを取得
- Firebase Authのトークンをどうにかして登録する
- メールアドレス&パスワード認証が有効な場合は、↓を参考にcurlで取得できる
- トークンをヘッダーに入れてリクエストしてみる
- curlが簡単なので、ここではcurlでリクエストしてみる
-
Hello, {IP Address}!
orHello, world!
が返ってくる
curl -H 'Authorization: Bearer {token}' https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello
後片付け
- 使い終わったら、忘れずに片付ける
sam delete
Discussion