Swagger と AWS SAM を使って Cognito オーソライザーを使って簡単な REST API HTTP 統合してみる
はじめに
おはようございます、もきゅりんです。
皆さん、API Gateway 使ってますか?
API Gateway といえば、 Lambda というくらいのセットイメージが一般的には強いと思うのですが、いろいろなサービスと関連付けることができますよね。
API の Gateway なのですから、APIを利用する側とAPIを提供する側の仲介、調整役として、 API Gateway は様々な機能を有しております。
ということで、本稿では REST API のHTTP統合を Swagger と Serverless Application Model (以下 SAM) でデプロイします。
実は大分前に、本稿を書いている途中、【初心者向け】SwaggerとAWS SAMを使ってWebAPIを簡単に作ってみた | DevelopersIO というグレートなブログを見つけて、あ、このブログいらないな、ということでそのままになっていました。
が、しばらくしてまた SAM を触る機会があったのですが、(普段あまり触らないので) あれ、サムってどんなんだったけ、とド忘れしてしまっていたため、自身の備忘録の意味もあり、まとめておくこととしました。
【初心者向け】SwaggerとAWS SAMを使ってWebAPIを簡単に作ってみた | DevelopersIO との構成の違いは下記になります。
- Cognito オーソライザーと連携する
- Lambda プロキシ統合ではなく、HTTP統合である
- CloudWatchLogs にログ出力する
構成図
API は Spring BootのREST APIをAWS Fargateにデプロイしてみた | DevelopersIO を再利用しています。
やること
- Cognito UserPool を作る
- SAMテンプレートを作る (Swaggerテンプレートも作る)
- デプロイする
- Postman で確認する
1 Cognito UserPool を作る
温かみある手動で Cognito UserPool は作成します。
基本的にデフォルト設定です。クライアントシークレットは解除、認証用の管理 API のユーザー名パスワード認証は有効にします。
手順は Cognitoで認証されたユーザーだけがAPI Gatewayを呼び出せるオーソライザーを使ってみた | DevelopersIO で丁寧にまとめられていますのでご参照下さい。
今回はIDトークンが欲しいだけなんです!
Cognito のサインイン時に発行されるトークンとそれらの役割についての詳細な説明は、Cognitoのサインイン時に取得できる、IDトークン・アクセストークン・更新トークンを理解する | DevelopersIO がとても分かりやすいです。
2 SAMテンプレートを作る
何はともあれ、 sam init
で開始します。
Getting started with AWS SAM - AWS Serverless Application Model を参考に SAM CLI を手に入れて、その使い方や作業の流れを、 Tutorial: Deploying a Hello World application - AWS Serverless Application Model を確認して進めます。
デフォルトテンプレートを AWS Serverless Application Model (AWS SAM) specification - AWS Serverless Application Model の仕様を参考に更新していって、ビルドしてデプロイします。
そんなこんなで、SAM テンプレートは以下になりました。
なお、 AWS SAMで「Stage」ステージが作られるバグを回避する に注意します。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: demo-project Globals: Api: OpenApiVersion: 3.0.2 Resources: ApiGatewayLogs: Type: AWS::Logs::LogGroup Properties: LogGroupName: /demo/sam-rest-api RetentionInDays: 30 ApiGatewayApi: Type: AWS::Serverless::Api Properties: StageName: dev AccessLogSetting: DestinationArn: !GetAtt ApiGatewayLogs.Arn Format: $context.identity.sourceIp $context.identity.caller \ $context.identity.user [$context.requestTime] \ "$context.httpMethod $context.resourcePath $context.protocol" \ $context.status $context.responseLength $context.requestId EndpointConfiguration: REGIONAL Name: sam-rest-api Auth: Authorizers: cognitoAuth: UserPoolArn: arn:aws:cognito-idp:reagion:account-id:userpool/reagion_cognito_id DefaultAuthorizer: cognitoAuth InvokeRole: CALLER_CREDENTIALS DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: ./swagger.yml MethodSettings: - DataTraceEnabled: true LoggingLevel: INFO ResourcePath: '/*' HttpMethod: '*' Outputs: HelloWorldApi: Description: API Gateway endpoint URL for Prod stage for Hello World function Value: Fn::Sub: https://${ApiGatewayApi}.execute-api.${AWS::Region}.amazonaws.com/dev/greeting/
Swagger を使ってドキュメントを作る
OpenAPI (Swagger) 超入門 - Qiita とかを参考に Swagger Editor, Swagger UI, Swagger Codegen など好きなもので作ります。
この辺は身近な API 職人にアドバイス貰うと良いでしょう。(アドバイス貰いたい...)
なお、API Gateway 独自の仕様があるので、手元の Swagger ファイルをそのまま使えるわけではない可能性もあるので、注意が必要です。
詳細は、OpenAPI への API Gateway 拡張機能の使用 - Amazon API Gateway をご参照下さい。
自分が頑張って作ったのが以下です。
openapi: 3.0.1 info: title: Sample Hello API version: 1.0.0 servers: - url: / paths: /greeting: get: description: Return Hello responses: 200: description: 200 response content: {} x-amazon-apigateway-integration: responses: default: statusCode: "200" uri: http://xxxxxxxxxxxxxxxxx.ap-northeast-1.elb.amazonaws.com/greeting passthroughBehavior: when_no_match httpMethod: GET type: http
頑張ったけど、ドキュメントを眺めながら気合で頑張るよりも、最初に手で自由に設定した後に API Gateway から REST API をエクスポートする - Amazon API Gateway を参考にエクスポートしちゃった方が効率的だと思いました。
## sample export command aws apigateway get-export --parameters extensions='apigateway' --rest-api-id abcdefg123 --stage-name dev --export-type swagger latestswagger2.json
APIを起動する
Spring BootのREST APIをAWS Fargateにデプロイしてみた | DevelopersIO を参考にAPIを起動させておきます。
デプロイする
AWS CLIがAWS::Include transformをS3へアップロードできるようになりました | DevelopersIO を参考に AWS::Include transform を使ってS3へSwaggerテンプレートをアップロードしてデプロイします。
## バケットがなければ適当にバケットを作成します aws s3 mb s3://everyday-sam-bucket aws cloudformation package \ --s3-bucket everyday-sam-bucket \ --template-file sam.yml \ --output-template-file template.yml Uploading to 002d01928360fe5180926ecbf91836a4 588 / 588.0 (100.00%) Successfully packaged artifacts and wrote output template to file template.yml. Execute the following command to deploy the packaged template aws cloudformation deploy --template-file <YOUR PATH>/template.yml --stack-name <YOUR STACK NAME>
言われるがままコマンド叩きます。
aws cloudformation deploy --template-file <YOUR PATH>/template.yml --stack-name <YOUR STACK NAME>
確認
IDトークンを取得します。
aws cognito-idp admin-initiate-auth \ --user-pool-id <YOUR USER POOL ID> \ --client-id <YOUR APP CLIENT ID> \ --auth-flow ADMIN_NO_SRP_AUTH \ --auth-parameters USERNAME=<YOUR USERNAME>,PASSWORD=<YOUR PASSWORD>
REST API のテストツールは何を使っても良いと思いますが、Postman を使用して REST API を呼び出す - Amazon API Gateway を参考に、 Postman を使って見てみると下記のような結果となりました。
問題ないようですね。
以上です。
最後に
またしばらく SAM を触らない間に忘れないように雰囲気まとめておきました。
ついでに、どなたかのお役に立つことがあれば幸いです。