AMPLS で Application Insights や Log Analytics を閉域化する話

# はじめに
今回はApplication InsightsやLog Analyticsを閉域化してくれる「**AMPLS（Azure Monitor Private Link Scope）**」について解説していきたいと思います。

# Application Insights の有用性
Web AppsやAzure FunctionsなどPaaSを用いたシステムを運用する際、「Application Insights」と「Log Analytics」は切っても切り離せない存在です。これらはAzure Monitorに属するサービスですが、Application Insightsは所謂APM（Application Performance Management）として、アプリケーションのアクティビティや正常性を示す"メトリクス"と"アプリケーションテレメトリ"に加えて、アプリケーションログも収集することができ、それらをAzureポータル上で簡単に可視化してくれます。Log Analyticsはそれらのログを集めてAzureポータルからシステム横断でクエリ検索ができるサービスです。どちらのサービスもシステムを運用する上で極めて重要なサービスです。

## Application Insights のセキュリティ
他方、セキュリティの観点で見た時、アプリケーションログに個人情報が含まれている可能性があります。個人情報を参照するためには、厳しいセキュリティ統制を掛けたアクセス経路を用意するのが一般的ですが、これがAzureポータルからサクっと見れてしまうことになります。もちろんAzureポータルについても「条件付きアクセス」や「RBAC」でアクセス経路や権限を制御することができますが、Azureポータルから参照できてしまうこと自体に抵抗を感じるお客様もいらっしゃいます。

## 個人情報出力に対するMicrosoftの注意喚起
Application InsightsとLog Analyticsにおける個人情報の出力に対する注意喚起と対策方法については、Microsoftからも案内が出ています。ざっくり言うと、以下の3項目を検討せよ という内容です。
* そもそも個人データを出さない。もしくは、難読化・匿名化を行い「個人データ」と見なさないようにする
* 個人データを正規化し、直接的でなく間接的に参照できるようにする
* 個人データのエクスポートと削除を行うプロセスを設ける

https://learn.microsoft.com/ja-jp/azure/azure-monitor/logs/personal-data-mgmt

確かに上記の対策は効果的で、新規構築時にアプリ含めて考慮して設計・開発しておけば、運用時に困ることはないでしょう。しかし、開発コストに余裕がない場合や既存システムにおいては、この対策を入れ込むのは少々ハードルが高いかと思います。そこで、今回ご紹介するAMPLSがこの課題を解決してくれる代替方法になります。

# AMPLS とは
AMPLS（Azure Monitor Private Link Scope）は **Azure Monitor の Private Linksサービス** です。Private LinkはPaaSサービスのエンドポイントをVNET内に引き込むことができる機能として様々なPaaSサービスに実装されていますが、AMPLSはAzure Monitorに対し同様の機能を提供してくれるものです。他のPrivate Linkと異なるのは、通常1つのPaaSリソースに対して1つのエンドポイントを作りますが、AMPLSは複数のAzure MonitorサービスをまとめてPrivate Link化します。（なので”Scope”と付いているのですね。）これにより、Application InsightsとLog Analyticsのように密に連携が必要なサービスをまとめ、パブリックネットワーク（Azureポータル経由含む）からのアクセス拒否、特定VNETからのアクセス許可、といった制御ができるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/25f7f98a-f748-39ab-ff7a-e5c5847cabd5.png)
(出典：https://learn.microsoft.com/ja-jp/azure/azure-monitor/logs/private-link-security)

## APMLS を作ってみる
早速AMPLSを試してみましょう。AMPLSはログだけでなくメトリクスなども同様に閉域化できますが、今回は個人情報を含むアプリケーションログ出力の閉域化を主眼において進めていきます。

### 1. 手始めに Application Insights を作成してログ出力してみる
まず、AMPLSに含めるApplication Insightsを作成します。個別で作成することもできますが、今回はAzure Functionsと一緒に作成されるApplication Insightsを使います。Azure Functionsについては今回はログ出力だけしてくれればいいので、Azureポータルからコードが触れるPowerShell版を用意しHttpTrigger関数を作成しました。テンプレートから余計な箇所を消していますが、追加したのは **"Write-Information"** の部分だけです。

```powershell
using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."

# Interact with query parameters or the body of the request.
$name = $Request.Query.Name
if (-not $name) {
    $name = $Request.Body.Name
}

$body = "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."

if ($name) {
    $body = "Hello, $name. This HTTP triggered function executed successfully."
    # ↓これだけ追加
    Write-Information "Request query name key is $name"

}

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $body
})
```
「コードとテスト」から「実行」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/f74f8567-7de7-ebdc-93b3-45720e2871dd.png)

すると、こんな出力が返ってきます。ここまでは普通のサンプルの動きです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/de32480b-9be9-2db6-e0e7-32ec84758e88.png)

さて、この実行に関する処理内容はApplication Insights（正確にはApplication Insightsと連携しているLog Analytics ワークスペース）に記録されています。今回"Write-Information"に出力したログは以下のような感じで簡単に参照することができます。これは露骨に出力した例ですが、同様にrequests、traces、Exceptionsといったアプリケーションログも簡単に参照できてしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/5d82a0fa-525d-7b01-706c-835df286be23.png)

### 2. AMPLS を作成する
ここからAMPLSを作っていきます。Azureポータルの検索から「Azure Monitor Private Link スコープ」が見つかりますので、必要項目を入れて作成します。この時、2つの大事な項目があります。AMPLSはAzure Monitorのトラフィックを閉域化するサービスですが、オプションとして「パブリックからのデータの受け入れ」や「パブリックからのクエリ検索」を許可することができます。

* クエリ アクセス モード：AMPLS化した上で、中のデータをパブリックから参照（クエリ検索）可能とするか
* インジェスト アクセス モード：AMPLS化した上で、パブリックからデータ受け入れを可能とするか

完全に外部と遮断する場合は両方とも「プライベートのみ」を選択すればOKですし、外部からデータ受け入れは許可するが参照はさせないとするならば、「クエリ アクセス モード」だけ「プライベートのみ」とします。後にも出てきますが、この設定は元々Azure Monitorの各サービスの管理ブレードに存在しています。ただ、Application InsightsとLog Analyticsで設定が違う、といったミスが起きてしまうため、後になってAMPLS自体にもこの設定を設け全体整合とれるようにしたようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/b23a48be-cfcd-bf4f-966e-8e78fe2bf542.png)

### 3. AMPLS に Application Insights と Log Analytics を繋ぐ
作成したAMPLSにApplication Insightsを繋ぎます。AMPLSの管理ブレードから[Azure Monitor リソース]を選択し、対象のApplication Insightsを選択します。これだけでAMPLS化は完了です。同様の手順でApplication Insightsに紐づいているLog AnalyticsもAMPLS化しましょう。設定後のイメージはこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/75c9b488-9df1-47cc-49bc-b1c2fb900e45.png)

ちなみに、Application InsightsにどのLog Analyticsワークスペースが紐づいているかは、Application Insightsの[プロパティ]にある”ワークスペース”設定を確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/2b0d7f5f-83ee-4b4f-844f-269dc982325c.png)

さて、AMPLS自体に「クエリ アクセス モード」や「インジェスト アクセス モード」がありましたが、同様の設定がApplication InsightsとLog Analyticsにも存在しています。まずApplication Insightsに進み、管理ブレードから[ネットワーク分離]を選択します。ページ下部に”仮想ネットワークのアクセス構成”と書いてる部分です。

* プライベート リンク スコープを通じて接続されていないパブリック ネットワークからのデータ インジェストを受け入れる（＝インジェスト アクセス モード）
* プライベート リンク スコープを通じて接続されていないパブリック ネットワークからのクエリを受け入れる（＝クエリ アクセス モード）

今回はAzure Functionsからログ出力させていますが、Azure Function自体はパブリックな領域にありますので、AMPLS化して「インジェスト アクセス モード」をプライベートにした場合、Application Insights に繋がらなくなってしまいます。この時、ログを出力する側のリソースもAMPLSと繋がっている必要があります。具体的にいうと、VNETの中にいるリソース（VMやAKS）であれば、そのVNETにAMPLSのプライベートエンドポイントを作成すればOKです。パブリックな領域にあるWeb AppsやAzure Functionsについては恐らくVNET統合で繋げば上手く行くかと思いますが未検証です。

今回の検証では、「インジェスト アクセス モード」をパブリックにし外部からのインジェストは許可します。一方「クエリ アクセス モード」はプライベートにしAMPLS内からしか参照できないようにします。


■Application Insightsの[ネットワーク分離] 設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/fa2554cb-195b-b5c2-eae3-afddd1b3d5c0.png)

■Log Analyticsの[ネットワーク分離] 設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/c93b2798-dfa7-5eae-cafd-b065e80c09aa.png)

この状態でAzureポータルからログのクエリ検索を掛けようとすると、このような感じでログクエリ検索ができなくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/1515f8af-4acf-cde8-bd66-16bc19873db8.png)

### 4. AMPLS 内から Azure Monitor を参照する
AMPLS内のAzure Monitorリソースを参照するために専用のVMを作成します。VMとVNETの作成手順は割愛しますが、今回はWindowsVMを用意しました。VNET作成後にはAMPLSのプライベートエンドポイントを作成する必要があります。AMPLSの管理ブレードから[プライベートエンドポイント接続]に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/1688ed37-528f-6bf1-1014-f80c4d5f1714.png)

プライベートエンドポイントのリソース種類は「Microsoft.Insights/privateLinkScopes」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/27066f88-00da-63cb-658a-36c88b044c92.png)

続いてプライベートエンドポイントができるVNETとサブネットを指定しますが、こちらは参照用のVMが所属するサブネットを選択します。
（このあたりはVNETとNSGの世界になりますので、設計ポリシーに沿って進めていただければ結構です。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/a8dd6b16-dbcf-94d3-3c93-b0cda5e19425.png)

そして、このプライベートエンドポイントに対して名前解決ができるようプライベートDNSを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/57497442-47fa-defd-42ee-6a714a3a8215.png)

検証OKとなれば[作成]に進みます。これでVNET内のVMがAMPLS内のAzure Monitorリソースに接続可能となりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/120ce3f2-e64c-0f63-a9fc-ec232fbb7067.png)

### 5. AMPLS 内のアプリケーションログを参照する
AMPLS内のアプリケーションログを見てみましょう。はじめに先の手順で作成したVMにログインしましょう。（bastionでもなんでもOKです）
PowerShellを起動したら、下記コマンドよりAz.OperationalInsightsモジュールをインストールします。
```powershell
Az.OperationalInsights
```
インストールが完了したらAzureにログオンします。
```powershell
Connect-AzAccount
```
いよいよログを見てみましょう。下記コマンドよりログを取得します。

```powershell
$workspace = Get-AzOperationalInsightsWorkspace -ResourceGroupName ampls-rg -Name ampls-logana
$query = 'union *  | take 10'
$QueryResults = Invoke-AzOperationalInsightsQuery -Workspace $workspace -Query $query
$QueryResults.Results
```
ログ取得成功です！こんな感じでログ取得できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199489/a47316fb-67fd-dd7a-2717-6d4f16dd2963.png)

## AMPLSを使う際の注意点
AMPLSのメリットと使い方について見てきましたが、デメリットや注意点があります。

### 可読性が著しく低下する
これが致命的なデメリットです。Azureポータルのクエリ検索に比べるとCUIのコマンド実行は著しく可読性を低下させ、実運用では耐えきれない危険性があります。もちろん出力したログをJSONやCSV出力して可視化ツールに食わせるといった仕組みを作ればある程度の改善にはなるかもしれませんが、完全に手組する必要があります。（Microsoftサポートにも上手いやり方がないか聞いてみましたが、有効な回答は得られませんでした。）
この点については、AMPLS採用前に関係者（特に実運用で操作する立場のメンバー）とよく議論してください。私もこの仕組みをいれましたがアプリチームからのクレームは必至でした。。

### Application Insights の診断設定に注意
これも引っ掛けですが、Application Insightsには現状Log Analyticsに出力する方法が2つあります。
1. Application Insightsの[プロパティ]にある”ワークスペース”設定
2. Application Insightsの[診断設定]にある”Log Analyticsワークスペース”設定

現在は1. の方が主流なので、将来的には2. の方が無くなるかもしれませんが、現時点では両方設定すると両方のLog Analyticsにログが出力されます。片方のLog AnalyticsをAMPLS化して安心していると、実はもう片方のLog Analyticsからは普通にAzureポータルのクエリ検索が使えていた、ということがありますので、こちらも注意してください。この場合、2. の方の設定を削除すればOKです。

### AMPLS のネットワーク設計
検証レベルの動作確認であれば問題ないですが、実際の本番ワークロードに適用する際には、AMPLSのネットワークトポロジーやDNSルーティングトポロジを設計する必要があります。ここは各環境のリソース状況や環境設計ポリシーに従って進めていきますが、詳細については下記サイトにしっかり書いてありますのでご参照ください。

https://learn.microsoft.com/ja-jp/azure/azure-monitor/logs/private-link-design

# おわりに
今回はAMPLSについて解説してまいりましたがいかがでしたでしょうか？AMPLS自体はとても良いサービスだと思いますが、ノックアウトになりかねないデメリットもありますので、採用の際はよく検討いただくようにお願いいたします。それではまた！