Amplify生成のAPI Gatewayリソースをオーバーライドする
amplify override api上記のコマンドを実行して、Amplify生成のAmazon API Gatewayリソースをオーバーライドします。
このコマンドは、amplify/backend/api/<resource-name>/の下に新しいoverrides.tsファイルを作成します。このファイルはAmplify生成のリソースをCDKコンストラクトとして提供します。
override(...)関数内にすべてのオーバーライドを適用します。例えば:
// このファイルはREST APIリソース設定をオーバーライドするために使用されますimport { AmplifyApiRestResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';
export function override(resources: AmplifyApiRestResourceStackTemplate) { resources.restApi.description = "Custom description"; resources.restApi.minimumCompressionSize = 1024;}特定のパスのフィールドを変更するには、resources.restApi.body.paths[\<route-path\>]を使用します:
export function override(resources: AmplifyApiRestResourceStackTemplate) { // デフォルトのCORSレスポンスヘッダーAccess-Control-Allow-Originを"'*'"からAPIのドメインに変更します resources.restApi.body.paths['/items'].options['x-amazon-apigateway-integration'].responses.default.responseParameters['method.response.header.Access-Control-Allow-Origin'] = { 'Fn::Sub': "'https://${ApiId}.execute-api.${AWS::Region}.amazonaws.com'" };}Amplifyが生成する以下のREST APIリソースをオーバーライドできます:
| Amplify生成リソース | 説明 |
|---|---|
| restApi | amplify add apiによって作成されたAmazon API Gateway REST API |
| deploymentResource | 上記のREST APIをステージにデプロイするデプロイメントリソース |
| policies | ユーザープールグループ関連のIAMポリシー。例:resources.policies["/items"].groups["Admin"] |
Cognito User PoolsでAPI要求を認可する
Amazon Cognito User Poolsは、アプリケーションにユーザーのサインアップとサインインを追加する場合、API Gatewayと一緒に使用する一般的なサービスです。アプリケーションがエンドポイントを呼び出したユーザーの代わりにS3などの他のAWSサービスと相互作用する必要がある場合は、Cognito Identity PoolsでIAM認証情報を使用する必要があります。
Amplify CLIはCognito User Pool認可者をすぐにサポートしていません。この機能を実装するには、REST APIをオーバーライドして、次のコードをoverride(...)関数に順番に追加することで、Cognito User Pool認可者を自分で追加する必要があります。
まず、Amplify Projectで設定されたAuth リソースが、認可者として使用したいCognito User Poolであると想定して、そのUser Pool ARNを解決するパラメータを作成します:
// 以下をAuth リソース名に置き換えますconst authResourceName = "<your-auth-resource-name>";const userPoolArnParameter = "AuthCognitoUserPoolArn";
// User PoolのIDのパラメータをCloud Formation Templateに追加しますresources.addCfnParameter({ type: "String", description: "The ARN of an existing Cognito User Pool to authorize requests", default: "NONE", }, userPoolArnParameter, { "Fn::GetAtt": [`auth${authResourceName}`, "Outputs.UserPoolArn"], });次に、OpenAPI拡張機能x-amazon-apigateway-authorizerを使用して、Cognito User Poolsを使用したREST API認可者を定義します。この変更は、REST APIのセキュリティ定義を変更することで適用されます:
// 上で定義したAuthCognitoUserPoolArnパラメータを使用して認可者を作成しますresources.restApi.addPropertyOverride("Body.securityDefinitions", { Cognito: { type: "apiKey", name: "Authorization", in: "header", "x-amazon-apigateway-authtype": "cognito_user_pools", "x-amazon-apigateway-authorizer": { type: "cognito_user_pools", providerARNs: [ { 'Fn::Join': ['', [{ Ref: userPoolArnParameter }]], }, ], }, },});最後に、REST APIのすべてのパスのセキュリティメソッドを更新して、この新しいCognito User Pool認可者を使用します。また、これらのパスへの受信リクエストにAuthorizationヘッダーをパラメータとして追加して、ユーザーがCognito User ID トークンを提供する場所として使用できます。
// REST API内のすべてのパスについてfor (const path in resources.restApi.body.paths) { // リクエストに認可ヘッダーをパラメータとして追加します resources.restApi.addPropertyOverride( `Body.paths.${path}.x-amazon-apigateway-any-method.parameters`, [ ...resources.restApi.body.paths[path]["x-amazon-apigateway-any-method"] .parameters, { name: "Authorization", in: "header", required: false, type: "string", }, ] ); // セキュリティのために新しいCognito User Pool認可者を使用します resources.restApi.addPropertyOverride( `Body.paths.${path}.x-amazon-apigateway-any-method.security`, [ { Cognito: [], }, ] );}REST APIにリクエストを実行する場合、Cognitoによって提供されるID トークンを含むAuthorizationヘッダーを追加してください。
エンドポイントへのリクエストは、エンドポイントを呼び出しているユーザーに関するCognitoの情報が入力されます。また、エンドポイントリゾルバで検証されたID トークンを再利用して、AWS AppSyncやS3などの他のサービスにアクセスするためにユーザーのアイデンティティを引き受けることができます。
Lambda認可者でAPI要求を認可する
Amplify CLIはLambda認可者をネイティブにサポートしていませんが、REST APIリソースをオーバーライドすることでこの機能を実装できます。次の手順では、トークンベースのLambda認可者を作成する方法について説明します。
まず、Amplify projectで認可者として使用する、必要な認可ロジックを持つLambda認可者関数が必要です。amplify add functionを使用して関数を設定するステップを参照してください。
amplify override apiを実行した後、以下のコードをoverride(...)関数に追加します。
まず、Lambda Function ARNに解決するパラメータを作成します。
// 以下をFunction リソース名に置き換えますconst functionResourcename = "<your-function-resource-name>";const functionArnParameter = "FunctionArn";
// 認可者関数arnのCloud Formation Templateにパラメータを追加していますresources.addCfnParameter( { type: "String", description: "The ARN of an existing Lambda Function to authorize requests", default: "NONE", }, functionArnParameter, { "Fn::GetAtt": [`function${functionResourcename}`, "Outputs.Arn"], });次に、OpenAPI拡張機能x-amazon-apigateway-authorizerを使用して、Lambda認可者を定義します。この変更は、REST APIのセキュリティ定義を変更することで適用されます:
// 上で定義したfunctionArnParameterパラメータを使用して認可者を作成しますresources.restApi.addPropertyOverride("Body.securityDefinitions", { Lambda: { type: "apiKey", name: "Authorization", in: "header", "x-amazon-apigateway-authtype": "oauth2", "x-amazon-apigateway-authorizer": { type: "token", authorizerUri: { 'Fn::Join': [ '', [ "arn:aws:apigateway:", { Ref: 'AWS::Region' }, ":lambda:path/2015-03-31/functions/", { Ref: functionArnParameter }, "/invocations" ] ], }, authorizerResultTtlInSeconds: 0 }, },});API Gatewayが認可者Lambda関数を呼び出すアクセス許可を必要とするため、以下のコードを使用して関数にリソースベースのポリシーを追加します:
// Lambda認可者関数にリソースベースのポリシーを追加していますresources.addCfnResource( { type: "AWS::Lambda::Permission", properties: { Action: "lambda:InvokeFunction", FunctionName: {Ref: functionArnParameter}, Principal: "apigateway.amazonaws.com", SourceArn:{ "Fn::Join": [ "", [ "arn:aws:execute-api:", { "Ref": "AWS::Region" }, ":", { "Ref": "AWS::AccountId" }, ":", { "Ref": "<your-API-resource-name>" }, "/*/*" ] ] } } }, "LambdaAuthorizerResourceBasedPolicy");最後に、REST APIのすべてのパスのセキュリティメソッドを更新して、この新しいLambda認可者を使用します。また、これらのパスへの受信リクエストに認可ヘッダーをパラメータとして追加して、ユーザーが認証トークンを提供する場所として使用できます。
for (const path in resources.restApi.body.paths) { // リクエストに認可ヘッダーをパラメータとして追加します resources.restApi.addPropertyOverride( `Body.paths.${path}.x-amazon-apigateway-any-method.parameters`, [ ...resources.restApi.body.paths[path]["x-amazon-apigateway-any-method"] .parameters, { name: "Authorization", in: "header", required: false, type: "string", }, ] ); // セキュリティのために新しいLambda認可者を使用します resources.restApi.addPropertyOverride( `Body.paths.${path}.x-amazon-apigateway-any-method.security`, [ { Lambda: [], }, ] );}REST APIにリクエストを実行する場合、Lambda認可者関数によって必要とされるトークンを含む認可ヘッダーを追加してください。