Azure App Service でリージョンVNet統合+Private Linkを試す

# はじめに
こんにちは。またApp Serviceネタです。App Service芸人ですね。

さて、Azure の PaaS サービスはパブリックネットワーク側にエンドポイントを設けていて、VNet側のリソースとは通信できない、というのが標準の構成です。

しかし、主にエンタープライズ領域では得てして閉域網での運用を前提としたセキュリティ基準が設けられているなどして、PaaSの利用を促進するための妨げとなったりしていました。

そこで今回は、最近GAを迎えたリージョンVNet統合を利用して、VNet側のリソースにアクセスすることに挑戦します。Private Linkもありますよ。

# 前提知識
## AzureとVNet
AzureにおけるVNetとは、IaaS層での仮想ネットワーク機能を提供しているコンポーネントとなります。
基本的にはオンプレミスのネットワークと同様にTCP/IPで各リソース間の通信が可能なプライベートネットワーク構築が可能となる仕組みです。
詳しくは、https://docs.microsoft.com/ja-jp/azure/virtual-network/virtual-networks-overview を参照してください。

## App ServiceとVNet統合
App Serviceでは、AzureのVNetに対して、App Service 上にデプロイしたアプリからアクセスするために、"VNet統合"と呼ばれる機能を提供しています。
VNet統合には、2種類の方式があります。
・リージョンVNet統合
同一リージョン内に存在するVNetに接続できます。ゲートウェイレスで利用できます。
・ゲートウェイが必要なVNet統合
他のリージョンのVNetや、クラシックVNet（ARMで管理されていない古いVNet）に接続する場合に利用します。接続先のVNet内にゲートウェイのデプロイが必要となります。
今回は、"リージョンVNet統合"を使用します。

## Private Link
Private Link を利用すると、Azure 上で提供されているPaaSに対して、パブリックネットワーク側ではなく、VNet側からアクセスする為のエンドポイントをVNet上にデプロイすることができます。これにより、VNet側からPaaSにアクセスする場合にパブリックネットワークを経由せず、閉域網内でのアクセスが可能となります。
Private Link は他にもオンプレミス/対応するSaaSに対して閉域網でのアクセスを提供することができます。
詳しくは、https://docs.microsoft.com/ja-jp/azure/private-link/private-link-overview を参照してください。

# 検証
## 準備
今回の検証では、App Service と CosmosDB を使用します。
まず始めに、CosmosDBにアクセスするアプリを作成して、App Serviceにデプロイします。VNet統合を利用するので、App Service の価格プランはStandard以上を選択してください。

まずは以下のような構成を使用します。VNet統合は行わず、App ServiceとCosmos DB間はパブリックネットワークを経由して通信する構成になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/b432d219-a75a-88e8-6f07-4882e9b0cab1.png)

Cosmos DBのコアはMongo DBとしました。このCosmos DBに対して、Spring BootでREST APIでMessageというエンティティを取り扱う簡単なアプリを作成しました。Messageクラスのプロパティは、それぞれString型の"key"と"message"です。REST APIの簡単な仕様は以下の通りです。

|Method	|Parameters |Summary |
|-------|-----------|--------|
|GET	|key	|key に該当する message を返します|
|PUT	|key, message	|key, messageの組合せを保存します|
|DELETE	|key	|keyに該当するデータを削除します|

Azure上で前述の環境を作成し、App Serviceにアプリをデプロイします。
Postmanやcurlで動作確認をしたところ、メッセージの保存と取得がきちんと動作しました。（当たり前）

**うん、面白くもなんともありませんね。**

## 本番
次に、以下のように構成を変更します。今回の検証の主題です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/33152cfe-2a2f-9275-92da-4d17dfcaa9f0.png)

AppService側にVNet統合、Cosmos DB側にPrivate Linkのエンドポイントを作成した形です。

では、まずはApp ServiceのVNet統合を構成します。
Azure Portalから対象のApp Serviceを選んで、"設定"のネットワークを選択し、上部のVNet統合で「構成するにはここをクリック」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/af03acbb-121d-14b4-2c4a-90d7d5277184.png)

VNet構成の画面になるので、「＋VNetの追加」を選択して、追加先のVNetとサブネットを指定します。
追加されると、以下のような画面になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/1319c54f-498d-841e-8228-c3b7c07211e7.png)

これで、App Serviceから接続したVNet上のリソースにアクセスすることが出来るようになりました。

次に、Cosmos DBのPrivate Link用Private EndpointをApp Serviceを接続したVNet上の別のサブネットにデプロイします。
Azure Portalから、対象のCosmos DBを開きます。"設定"から"Private Endpoint Connection"を選択し、「＋Private Endpoint」をクリックして、Private Endpointを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/6d167be4-4776-b879-b2cb-19b591011777.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/f02c4582-119d-d616-20d6-a021e8bacf35.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/45cddf39-892c-94bd-701f-70b5b84b304f.png)


Private Endpointのデプロイには10分くらいかかると思います。
デプロイ後にCosmos DB の Private Endpoint Connectionを開くと下記のようにPrivate Endpointが追加されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/975a90bb-7596-9c30-d7da-d6bc9ba98812.png)


しかし、この状態で再度アプリにアクセスすると、Internal 500 エラーが返ってきてしまいます。
サーバ側のエラーは下記のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/7847b6c0-b1d8-bd9d-5b49-10b7f2e217d8.png)

エラーメッセージの中に、気になる1文があります。

<font color="red">”Request originated from client IP 23.100.102.146 through public internet. This is blocked by your Cosmos DB account firewall settings”</font>

ということは、Cosmos DB側の Firewall の設定で蹴られているようです。確認してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/3e847e3d-8585-54bf-f511-0f6b5a0d1777.png)

Private Linkを作成したことにより、Firewallが自動的に有効になってます。また、"すべてのネットワーク"を選択することができません。
もう一つ気になるのは先ほどのエラーで"public internet"となっているところですね。
切り分けの為、"パブリック Azureデータセンター内からの接続を受け入れる"を有効にしてみましたが、状況は改善しませんでした。

しかし、そもそもApp ServiceからのCosmos DBへのアクセス経路がVNetではなく、パブリックインターネットになったままなのが問題です。
これは、下記のアプリケーション設定を追加することによって挙動を変更することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664942/d59b4ea8-6068-2960-f176-1017bd5640ee.png)

|パラメータ名|値|
|----|----|
|WEBSITE_DNS_SERVER|168.63.129.16|
|WEBSITE_VNET_ROUTE_ALL|1|

WEBSITE_DNS_SERVER は App Service上のアプリが参照するDNSサーバの設定で、Azure DNS Private ZoneのDNSサーバに設定（168.63.129.16 ）することにより、参照先のDNSサーバを変更することが出来ます。WEBSITE_VNET_ROUTE_ALLは1を設定することにより、アプリからの送信トラフィックが全て接続されたVNetを経由することになります。
参考URL:https://docs.microsoft.com/ja-jp/azure/app-service/web-sites-integrate-with-vnet

このアプリケーション設定を有効にした状態で、再びアプリにアクセスすると通常のレスポンスが返ってくることが確認出来ました。
検証、終了です。（特にトラブルもなく検証が終了してしまって不満でもある）

# まとめ
まとめると、Azure App ServiceとPrivate Linkの組合せにより、閉域網でPaaS同士を通信させることが容易に可能であることがわかります。便利な時代になりましたね。これでPaaS同士の通信経路をより限定することができるため、従来のサービスエンドポイント＋NSGの組合せよりもさらにセキュアな環境を実現することが出来ます。

どっとはらい