掲載内容は個人の見解であり、所属する企業を代表するものではありません.
もうかなり前の話になりますが Azure WebApp がリージョン VNET 統合に対応し、リージョン内であれば VPN Gateway が不要になったため閉域構成はかなり楽になりました。
Azure Functions でも基盤は同じ App Service なのでまあ一緒だろうと思って高を括っていたのですが、実際に組んでみると地味にはまりました。。。
結論から言えば「どのような構成をすれば良いか?」の答えは大体以下に書いてありますので、本記事は解説編的な位置づけになります。
公式ドキュメント読んでも「なんでこんなことしているのか?」わからないんですもの・・・
Azure Functions をポータルからポチポチっと作成すると4つのリソース(Functions アプリ、App Service プラン、ストレージアカウント、Application Insights)が作られると思いますが、これらの役割を考えてみます。 図中でストレージアカウントを3つに分けて記載しているのは、既定で作成されるのは 1 つだけなのですが、設定内容と使われ方を解きほぐすと 3 つの役割に分けられ、分離することも可能だからです。
なお、以下ではホスティングプランは Elastic Premium プランを利用するものとして解説しています。 従量課金プランではそもそもVNET統合が設置できませんし、通常の占有型 App Service Plan であれば Elastic Premium プランよりも設定項目が少なくなります。
WebApp とは何が異なるのか、という意味では以下の 2 点、上の図で破線よりも下側の領域になります。
逆に破線よりも上側、主にアプリケーションのレイヤで行われるリソースアクセスに関しては WebApp とあまり変わりがありません。
さてストレージアカウントが Public IP アドレスを持ち、ネットワーク的にはインターネット経由でアクセス可能である、ということ(認証がかかっているとはいえ)許容できない方は一定数おられるように思います。 まあオンプレミス環境と接続された仮想ネットワークとそこに接続された各種リソースを活用することを考えれば、セキュリティポリシーの観点から閉域化する必要性もあるのでしょう。 せっかくストレージアカウントは Private Endpoint に対応しているんだから、仮想ネットワークに閉じ込めてしまえばいいじゃないか、というわけですね。
閉域化の前にストレージアカウントのバージョンを確認しましょう。 各種のストレージサービスに対して Private Endpoint を構成するには 汎用 V2 である必要があるのですが、 ポータルからポチポチと自動的に作られるストレージアカウントは現在のところ V1 のようです。 もし V1 のままであればこちらの手順 に従ってアップグレードしてください。 また Functions App が処理するデータを格納したストレージアカウントももしかしたら V1 になっているかもしれません。
まずは Functions App からの発信トラフィックを仮想ネットワークに引き込めるようにしましょう。 これはトリガーや入出力バインド(ないしはアプリ内のコード)から、ストレージアカウントなどのバックエンドリソースやオンプレミスリソースにアクセス可能にすることを意味します。
functions.json
内でトリガーや入出力バインドで使用するリソースを特定する168.63.129.16
に設定し、各バックエンドリソースの FQDN を仮想ネットワーク内の Private IP アドレスに解決するWEBSITE_DNS_SERVER
設定があることで FQDN は Private DNS Zone で Private IP アドレスに解決されるようになりますので、
VNET 統合を経由して仮想ネットワーク内にルーティングされます。
この Private IP アドレスは仮想ネットワーク内のアドレスレンジになってますので、Private Endpoint に到達できるわけですね。
さてこの状態でも Functions App は動作するのですが、バインド状態やアプリコンテンツを配置しているストレージへのアクセスは相変わらず Public IP アドレスを使用しています。 Azure バックボーンネットワーク内を経由しますので公衆インターネットを経由するわけではありませんし、 各種ストレージアカウントはアクセスキーなどがしっかり管理されていれば、不正なアクセスによるデータ漏洩のリスクは少ないでしょう。 しかしセキュリティポリシーが許さないというのであれば、これらも閉域化する必要があるのでしょう。
バインド状態やキー管理に使用されているのはやはり Blob ストレージですし、Durable Functions タスクハブ情報の管理に使用されるのは Queue や Table ストレージです。 これらのアクセスを仮想ネットワーク内に引き込みましょう。
次にアプリコンテンツを格納する Files へのアクセスを仮想ネットワーク内に引き込みましょう。
1
に設定して Files のマウントを仮想ネットワーク経由にするRegional VNET 統合を使用して閉域化を目指す場合には多くの場合 WEBSITE_VNET_ROUTE_ALL を設定するのですが、実はこの記事では設定していません。 ここまで紹介した内容でアクセスする対象リソースは Private Endpoint が使えるので、全て自動的に VNET 内にルーティングされるからです。 ただ「ストレージを閉域化したにも関わらずパブリック IP に好き勝手にアクセスしてよい」ということは多分無いと思いますので、 WEBSITE_VNET_ROUTE_ALL を設定して全てのトラフィックを仮想ネットワークにルーティングし、 そこからの Private Endpoint が設置できないサービスに対しては、サービスエンドポイントや Azure Firewall 等を使用した通信制御をご検討ください。 (本記事では割愛しています)