React×Spring Bootな構成をAWS Fargateで動かす(5) ~ 構成上の問題の解消方法

Pocket

プライベートサブネットからCognitoにアクセスする

前回の記事の最後で、考えていた構成では問題があると締めくくっていました。

React×Spring Bootな構成をAWS Fargateで動かす(4) 

バックエンドサービスは、認可のためにJWT検証のURLにアクセスする必要があります。
しかし元々考えていた構成では、以下のようにプライベートサブネットにあるバックエンドサービスからCognitoのJWT検証URLへのアクセス経路がなかったのです。

 

今回の記事は、この構成上の問題の解決方法を模索してみようというものになっています。

構成のパターン

まずはどんな構成が考えられそうか調べてみようということでググってみると、いくつか検索することができました。

Amazon Cognito ユーザープールエンドポイントへのアクセスパターンを考える

VPC Endpoint サポートされてないけど閉域から Cognito で認証したい!

これらを今回の構成に当てはめて、まとめると以下のようになります。

NAT Gateway経由でアクセスする構成

一番最初に思いつきそうなのがこの構成なのではないでしょうか。
プライベートサブネットからインターネットへのアクセスをNAT Gateway経由でアクセスするという構成です。
しかし、以下の理由から今回は見送りました。

  • NAT Gatewayの冗長化も考えるとコスト高
  • CognitoのJWT検証URLへのアクセスをするためだけにしてはオーバースペック
  • 任意のURLにアクセスできてしまう

フォワードProxy経由でアクセスする構成

パブリックサブネットにEC2とプロキシソフトウェアを構築して、プロキシサーバ経由でアクセスするという構成です。
そもそもFargateをベースとした構成の中にEC2が混ざるのもいやですし、EC2の運用もしなければならないということで、こちらも見送りました。

パブリックサブネットで起動する構成

Fargateをパブリックサブネットで起動することによって、インターネットにアクセスできる経路を確保しようという構成です。
こちらもNAT Gateway同様、任意のURLにアクセスできてしまうというのと、サブネット分離できずインターネットにさらされる危険性を排除できない、ということから見送りました。

API Gateway経由でアクセスする構成

プライベートなAPI Gatewayのエンドポイントを立て、API GatewayからCognitoにプロキシさせるという構成です。
こちらで実現できそうだったのですが、VPCエンドポイントがさらに増えてしまうのと、Cognito全体にプライベートからアクセスしたいわけでもないため、何か別の方法はないか考えることにしました。

別の構成の考察

そもそもJWT検証URLから返ってくるのは以下のようなJSONファイル。

このファイルを持っておいて、それを読ませればいいのでは?と考えたのですが、公式ドキュメントによると

ということで値は定期的にローテーションされる可能性があるということです。
当然と言えば当然ですね。
そこでフォワードProxy経由でアクセスする構成からヒントを得て、少々トリッキーではあるのですが、以下のような構成ならば実現できるのでは?と思いました。

まず、CognitoのJWT検証URLにアクセスして、そのままレスポンスを返す非VPCのLambdaを作成します。
ALBからこのLambdaに振り分けるようにします。
ALBはすでにあるはずなので、パスベースでルーティングすれば追加のコストはかかりません。
そしてバックエンドサービスからALB経由でLambdaにアクセスできさえすれば、実現できるのではないかと考えたのです。

ここで少々変更点があるのですが、元々の構成ではALBをパブリックに置いていたのですが、プライベートのALBにしています。
理由としては、バックエンドサービスから呼び出すときにプライベートALBでないとプライベートのIPアドレスが解決されず、結局アクセスできないためです。
元々は社内システムが想定ということで勘弁してくださいね。

構成の検証

思いついたら早速検証してみよう!
ということで検証のゴールは、プライベートなALB経由で非VPC Lambdaに振り分け、CognitoのJWT検証URLの内容をレスポンスできるか、と決めました。
検証のためのアプリももちろんCDKで作っていきます。
まずはお決まりのコマンドでCDKプロジェクトを作成します。

環境変数から値を渡すため、cognito-gateway.tsを以下のように修正します。

プロジェクトのルートにlambdaディレクトリを作成し、以下ののソースをlambda_function.pyとして保存しておきます。
このPythonプログラムが、CognitoのJWT検証URLの内容をレスポンスするLambdaになります。

最後にcognito-gateway-stack.tsを作成します。

プライベートサブネットのみのVPCを作成し、そこにプライベートなALBを置いています。
テストのために同じサブネットにEC2インスタンスを作成し、Session Manager経由でログインできるようにしておきます。
.envファイルにUSER_POOL_IDの値をセットして、いざデプロイ!
テスト用のEC2インスタンスから、curlコマンドでALBのURLを叩いたところ、無事にJSONの値を表示することができました😆

これで構成上の問題は解消できそうです。
次回はいよいよすべての構成をCDKでデプロイしていきたいと思います!
それでは、また次回に👋


シリーズ記事

お問い合わせ先

執筆者プロフィール

Hayakawa Masafumi
Hayakawa Masafumitdi デジタルイノベーション技術部
昔も今も新しいものが大好き!
インフラからアプリまで縦横無尽にトータルサポートや新技術の探求を行っています。
週末はときどきキャンプ場に出没します。
Pocket

関連記事