GoogleAppEngineのサービス間通信の認証などについて調べたこと（未解決）


# 概要

AppEngineには[複数のサービスを作りマイクロサービス風の構成にする機能](https://cloud.google.com/appengine/docs/standard/python3/an-overview-of-app-engine#services)があるが、各サービス間の通信をどのように制御可能か分からなかったので調べた。（スタンダード環境のPython3を想定）

ここでいう制御とは、認証やアクセス制限のこと。パブリックのAPIとインターナルなAPIを分けたり。

**結論：よく分からん。**

結局解決はしていないが、調べたことやURLを残しておきたいのでこの記事を書く。何か分かったら追記する。


# やりたかったこと

サービスAとサービスBを作り、サービスAはパブリックに公開するが、サービスBはインターナルなWebAPIとして外部公開はしない。

セキュリティ的な設定として、サービスBがインターネットから呼ばれる経路は作りたくない。（極めて一般的な要件だと思う。）


# 調べたこと
## ドキュメントを読むとできそうな気がしてくるが…
[公式ドキュメント](https://cloud.google.com/appengine/docs/standard/python3/an-overview-of-app-engine)から引用。

> 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 によってアクセスされるアプリケーションの一元的な承認レイヤを確立できるため、ネットワークレベルのファイアウォールに頼らずに、アプリケーションレベルのアクセス制御モデルを使用できます。

https://cloud.google.com/iap/docs/concepts-overview

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アドレスが固定化される。


https://stackoverflow.com/questions/47745439/using-google-compute-engine-as-a-proxy-for-a-google-app-engine-web-app

## 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

## 似ている悩み

https://stackoverflow.com/questions/49685512/google-app-engine-firewall-and-internal-access

フレキシブル環境だし、Node.jsだし、ちょっと違うけど。

## フレキシブル環境の場合
スタンダード環境ではなく、フレキシブル環境の場合。

[ここ](https://stackoverflow.com/questions/49296666/google-app-engine-firewall-restrict-access-to-all-services-but-the-default-one)にあるように、ComputeEngineのファイアウォール機能を使えば目的を達せれそうな雰囲気がある。（未検証）


## 昔のAppEngineならできてた？ - Backends

2014年に廃止された「バックエンド」が今回やりたかったことに似ている気がする。

https://cloud.google.com/appengine/docs/standard/python/backends/#Python_Public_and_private_backends

バックエンドは、基本的にはユーザーに公開されない。

バックエンドはモジュールに代わったあと、現在のサービスに代えられたが、公開・非公開のところは変わってしまったようだ。


# 結論

よく分からん。知っている人教えてください。（切実）

# 参考資料

* https://cloud.google.com/appengine/docs/standard/python3/communicating-between-services
    * 期待させるタイトルだが、アクセス制御に関することは書いていない