プレビュー公開されてから 1 年近くが経過して、ようやく App Service の Regional VNET Integration が GA されました。ただし GA は Windows のみとなっているので Linux は未だプレビューのままです。
以前からドキュメントには Windows の Regional VNET Integration は、本番ワークロードで利用可能と書いてあったので既に本番向けのいろんな部分で利用を開始してました。
なかなか GA しなかった理由は、RFC1918 以外のアドレスへのトラフィックを VNET 経由にする機能を追加するのに時間がかかったからのようですね。
これまでは RFC1918 なアドレスか Service Endpoints を設定した場合のみ VNET 経由になるようでしたが、これからは App Service からの Outbound トラフィック全てを VNET 経由に出来るので、NSG や UDR を設定できるようになりました。
NSG を使うことで特定の App Service からの通信先を制限することができます。既にドキュメントは新しく追加された機能ベースにアップデートされていたので読んでおきましょう。
日本語版は致命的に間違っている部分があるので、基本的に新しい機能のドキュメントは英語版を参照しておいた方が良いです。これで個人的には完全に ASE を使う必要性がなくなりました。
早速追加されたトラフィックを全て VNET 経由にする機能を試しておきました。Regional VNET Integration については以前に書いた内容から変わってないので、説明は省略します。
App Service のベストプラクティスをまとめたエントリにも Regional VNET Integration と Service Endpoints について書いてあるので、こっちも参照してもらえれば良いです。
最近では VNET は土管的な使い方をしていて、基本は Regional VNET Integration と Service Endpoints を組み合わせたアクセス制限に活用してます。
作成したリソースは以下のようになっています。Service Endpoints の確認用に Storage Account と別の App Service を作成して、それぞれの Service Endpoints を Subnet に追加しています。
Service Endpoints の有無で挙動が結構変わるので運用時には注意したいところです。具体的には App Service の場合は送信 IP アドレスが IPv6 に変わったりします。
全ての App Service は Regional VNET Integration を有効にしています。まだ Azure Portal 上では Preview という表記のままですが、実際には GA しています。
App Service からの Outbound を全て VNET 経由にするためには WEBSITE_VNET_ROUTE_ALL = 1
を App Settings に追加する必要があります。プロセスレベルでの分離という感じが相変わらず凄いです。
こういったプラットフォームに関する設定は ARM Template や Terraform で管理するようにしましょう。本来なら設定として用意してほしいですが、App Settings に追加するというアドホックな方法が多いです。
保存してワーカープロセスが再起動されれば、全てのトラフィックは VNET 経由に変わるようです。
この設定を有効にしなくとも、Service Endpoints を追加しているサービスへのトラフィックの場合は NSG を使った制限が有効になるようでした。仕組みを考えると納得できる結果ではあります。
分かりやすいように App Service が参加している Subnet に対して、VNET からの Outbound トラフィックを全て拒否するルールを追加してみました。
反映されるまで数十秒はかかるようですが、App Service への通信が以下のように通らなくなりました。もちろん Storage やそれ以外の Web サイトに対してのトラフィックも全てです。
そこで例として、以下のように HTTPS だけを通すようなルールを追加してみます。
今回は例なので非常に大雑把なルールですが、本来ならフロントエンドやバックエンドというように用途別に Subnet を分けて、細かく NSG や Service Endpoints を使って制限するべきでしょう。
これで Storage へのアクセスで HTTP / HTTPS それぞれを試してみると、HTTP の方は通らないですが HTTPS は問題なく通るようになりました。
本来なら Service Tag を使って Azure のサービス単位で通信を許可することが出来るはずなのですが、今のところ試している限りでは正しく動作していないようでした。同じ NSG を VM が入ってる Subnet に当てたら動いたので、NSG が間違っていることはないはずです。
検証した限りでは Service Tag で設定した Destination が実質 Any として扱われているような挙動でした。
Azure サービスへのアクセス制限は Service Endpoints を使いつつ、不必要なポートへのトラフィックは NSG で塞ぐというのが現状の最善手な気がしています。全てのアプリケーションでここまでの制御が必要かは別の話ですが、必要なシチュエーションはありそうです。