概要
AppEngineには複数のサービスを作りマイクロサービス風の構成にする機能があるが、各サービス間の通信をどのように制御可能か分からなかったので調べた。(スタンダード環境のPython3を想定)
ここでいう制御とは、認証やアクセス制限のこと。パブリックのAPIとインターナルなAPIを分けたり。
結論:よく分からん。
結局解決はしていないが、調べたことやURLを残しておきたいのでこの記事を書く。何か分かったら追記する。
やりたかったこと
サービスAとサービスBを作り、サービスAはパブリックに公開するが、サービスBはインターナルなWebAPIとして外部公開はしない。
セキュリティ的な設定として、サービスBがインターネットから呼ばれる経路は作りたくない。(極めて一般的な要件だと思う。)
調べたこと
ドキュメントを読むとできそうな気がしてくるが…
公式ドキュメントから引用。
For example, an app that handles your customer requests might include separate services that each handle different tasks, such as:
・API requests from mobile devices
・Internal, administration-type requests
・Backend processing such as billing pipelines and data analysis
「Internal, administration-type requests」をセキュリティ的にいい感じにやりたいというのが、今回の要件。
ファイアウォール設定
サービスごとにファイアウォールの設定を変えることができれば、解決しそう。
しかし、ファイアウォールはアプリケーション単位での設定しかできず、サービス単位では不可能。
つまり、サービスAをパブリックに公開するなら、サービスBもパブリックに公開される。(ファイアウォール的には)
何か別の方法が必要だ。
参考
- https://cloud.google.com/appengine/docs/standard/python3/creating-firewalls
-
https://cloud.google.com/appengine/docs/standard/java/creating-firewalls?hl=ja
- Javaの方は日本語訳があった
Cloud Identity-Aware Proxy(Cloud IAP)
Cloud IAP を使用すると、HTTPS によってアクセスされるアプリケーションの一元的な承認レイヤを確立できるため、ネットワークレベルのファイアウォールに頼らずに、アプリケーションレベルのアクセス制御モデルを使用できます。
AppEngineと連携が可能なため良さそうに見えるが、これもファイアウォールと同様にサービス単位で設定ができないように見える。
プロジェクトを分ければ何とかなるのか?
ファイアウォールもCloud IAPもサービス単位にならないから困っていた。では、AppEngineのサービスを使うのをやめて、プロジェクトを分けてしまうとどうか。
ファイアウォール
意味なし。AppEngineから出て行くIPアドレスが決まらない。
Cloud IAP
できそう。
ただし、プロジェクトA(サービスAを動かすプロジェクト)のAppEngineのデフォルトサービスアカウントをプロジェクトB(サービスBを動かすプロジェクト)に登録する必要がある。(たぶん)
デメリット
- プロジェクトが増えると、管理が面倒(保守性が落ちる)
- 「Cloud IAPで認証」は、「内部ネットワークにある」と比べると、わかりにくい。(主観)正しく設定できているか確認がよく分からない。
URL Fetch serviceってなに?
サービス間の通信を支援してくれるっぽい。
https://cloud.google.com/appengine/docs/standard/python/issue-requests
https://cloud.google.com/appengine/docs/standard/python/outbound-requests
でも、今回の要件とは違う気がする。
いまいちな解決策:AppEngineの前にプロキシを置く
ComputeEngineでリバースプロキシを構築して、サービスAにプロキシする。AppEngineのファイアウォール設定では、ComputeEngineに設定した固定IPアドレスのみを許可する。
プロキシ設定を適切に行えば、インターネットからサービスBへの経路を塞ぐことができる。(はず)
コストと運用面で微妙。
メリットとしては、アプリケーションのIPアドレスが固定化される。
login:admin
スタンダード環境のPython3では使えないが、Python2では"login:admin"を設定できた。
この機能を使えば、以前はサービス間の制御が可能だった?(気が向いたら調べる)
参考
- https://stackoverflow.com/questions/41864284/how-to-authenticate-requests-across-internal-app-engine-modules
- https://cloud.google.com/appengine/docs/standard/python/config/appref?hl=ja#handlers_login
似ている悩み
フレキシブル環境だし、Node.jsだし、ちょっと違うけど。
フレキシブル環境の場合
スタンダード環境ではなく、フレキシブル環境の場合。
ここにあるように、ComputeEngineのファイアウォール機能を使えば目的を達せれそうな雰囲気がある。(未検証)
昔のAppEngineならできてた? - Backends
2014年に廃止された「バックエンド」が今回やりたかったことに似ている気がする。
バックエンドは、基本的にはユーザーに公開されない。
バックエンドはモジュールに代わったあと、現在のサービスに代えられたが、公開・非公開のところは変わってしまったようだ。
結論
よく分からん。知っている人教えてください。(切実)
参考資料
-
https://cloud.google.com/appengine/docs/standard/python3/communicating-between-services
- 期待させるタイトルだが、アクセス制御に関することは書いていない