1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

CDK + API Gateway + Lambda Proxy + API Key 構成でCORSを回避するためにOPTIONSだけ認証を外したい

Posted at

課題

以下の構成でAWSリソースを作ろうとしています。

  • AWS CDK (typescript)
    • AWS のリソースをコードで管理したい
  • Lambda
    • FastAPI 製の API を提供したい
  • API Gateway
    • API のエンドポイントとして提供したい
    • Lambda で提供する機能をプロキシしたい
    • API Key を設定して、アクセスを制限したい(Lambda 内でやってもいいが、できれば API Gateway で弾いておきたい…)

上記の構成を取りたい場合、以下の構成を取るのが自然です。

const mainApi = new RestApi(this, `Api`, {
	// ...一部設定を省略
  defaultCorsPreflightOptions: {
    allowOrigins: Cors.ALL_ORIGINS,
    allowMethods: Cors.ALL_METHODS,
    allowHeaders: Cors.DEFAULT_HEADERS,
    statusCode: 200,
  },
});
const backendResource = mainApi.root.addResource("main");
const backendResourceProxy = backendResource.addProxy({
  defaultIntegration: mainBackendIntegration, // FastAPI を mangum 経由で提供している Lambda
  anyMethod: true,
  defaultMethodOptions: { apiKeyRequired: true},
});

const apiKey = mainApi.addApiKey("ApiKey", {
  apiKeyName: `example-api-key`,
});
const plan = mainApi.addUsagePlan("UsagePlan", {
  name: `example-api-usageplan`,
});
plan.addApiKey(apiKey);
plan.addApiStage({ stage: mainApi.deploymentStage });

しかしながら、 apiKeyRequired: true を指定しているため、OPTIONS もAPIキーが必須となってしまっています。

image.png

OPTIONS メソッドは認証を切っておかないと、CORS 検証時のプリフライトリクエストでコケるという話があります[1]。

実際、筆者も何度か同様の問題でハマってきました。

通常、API Gateway に関数を追加する場合、1つのメソッドに対して Lambda Integration を割り当てるというやり方をしますが、今回は裏側でリクエストを解釈したいため、どうしてもプロキシを通したいのです。

しかし、ドキュメントを見ても OPTIONS のみ apiKeyRequired を切るというパラメータはありませんでした。

AWS の UI コンソール上で手動で切るとこの問題は解決するのですが…できれば取りたくない手段です。

解決策

anyMedhod: trueとせずに、一つ一つ必要なメソッドを追加することで解決できます。

const backendResourceProxy = backendResource.addProxy({
  defaultIntegration: props.mainBackendIntegration,
  anyMethod: false,
  defaultMethodOptions: { apiKeyRequired: false},
});
backendResourceProxy.addMethod("GET", props.mainBackendIntegration, {apiKeyRequired: true})
backendResourceProxy.addMethod("POST", props.mainBackendIntegration, {apiKeyRequired: true})

今回は、API 内に GET と POST しかないので、2つのみを追加しました。

ドキュメントを眺めていたら、addProxy メソッドで返される ProxyResourceaddMedhod があることがわかり、これを使うことで GET も POST も FastAPI で設定したパスにリクエストを通すことができるようになりました。

また、OPTIONS の認証設定が外れたので、課題だった CORS のプリフライトリクエストが通らない問題も解決しました。

image.png

その他のメソッドが必要な場合も同様に追加していくことで対応できそうです。

参考文献

[1] https://future-architect.github.io/articles/20200717/

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?