Azure Files のログ分析 (Log Analytics/Sentinel)

# 本記事について

Azure ストレージアカウントは Blob, Files, Queue, Table の４種類のストレージからなります。その中でも SMB でマウント可能な Azure Files は簡易的なファイルサーバーやアプリケーションの共有ストレージとして良く利用されます。

その一方で、本稿でご紹介する[**リソースログ (診断ログ)**](https://learn.microsoft.com/ja-jp/azure/storage/files/storage-files-monitoring#azure-monitor-resource-logs) は後から登場したこともあり、中々知られておらずウェブ上の情報も限られています。しかし、重要なファイルやデータをストレージアカウントに置く場合は、そのログ (ファイル・フォルダーの操作やアクセスの記録) を保持して検索可能にしておくことはとても重要です。

ですので、本記事では、ストレージアカウントの診断設定で Log Analytics ワークスペースに Azure Files のログを送り、実際にクエリを書いて分析するところまでを見ていきます。

# Azure ストレージの診断設定

**ストレージアカウントの診断設定**から、Files を選択して、ログ送信の設定をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/eee243fa-bb50-f776-21aa-e0ede646f81a.png)

診断設定で取得したいログカテゴリーを選択し、送信先として事前に作成しておいた Log Analytics ワークスペースを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/19a7e8c1-4bea-c982-6c33-7af891bb3e94.png)

公式ドキュメントは下記になります。

https://learn.microsoft.com/ja-jp/azure/storage/files/storage-files-monitoring#collection-and-routing

なお、Azure Files のログのストレージアカウントへの取得については、マイクロソフトのサポートチームのブログがわかりやすく解説されています。

https://jpaztech.github.io/blog/storage/azureFilesMonitoring/

# Log Analytics ワークスペースでの Azure Files のログ分析

Azure Files のログは、[**StorageFileLogs**](https://learn.microsoft.com/ja-jp/azure/azure-monitor/reference/tables/storagefilelogs/) という名前のテーブルに格納されます。このテーブルのスキーマ情報は下記になります。

https://learn.microsoft.com/ja-jp/azure/azure-monitor/reference/tables/storagefilelogs

なので、たとえば下記のクエリで直近31日分のログを時間の降順で取得できます。

```:Kusto
StorageFileLogs 
| where TimeGenerated > ago(31d)
| sort by TimeGenerated desc 
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/5ac82cee-a91a-45a9-8fee-608092637095.png)


特に Azure Files は SMB で利用されることが多いかと思うので、``Protocol == "SMB"`` でフィルターをかけてみます。また、``IPC$``へのアクセスのログを除外して表示するようにします。また、ログの列が多いので、``project`` 句で絞ってみます。

```:Kusto
StorageFileLogs 
| where TimeGenerated > ago(31d)
| where Protocol == "SMB"
| where ObjectKey !contains "file.core.windows.net\\IPC$\\"
| sort by TimeGenerated desc 
| project TimeGenerated, AccountName, Location, Protocol, OperationName, AuthenticationType, Uri, ObjectKey, SmbPrimarySID, Category, SmbCommandMinor, MetricResponseType, Type, _ResourceId
```

検索結果として、たとえばファイルを開いたイベントは下記のようにログでとらえられます。 (このレコードは ``SmbCommandMinor`` が ``FileOpen`` になっています。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/5c953274-5f5d-7017-beca-1c9a73d4dd9a.png)

## SMB アクセスのユーザーの分析 - SmbPrimarySID

さて、ここで分析の課題になるのが、SMB でのアクセスで Active Directory のユーザーの情報が **SID (SmbPrimarySID)** で表示されることです。SMB のストレージとして利用する場合、Active Directory で認証されたユーザーにアクセス許可を与えているケースが多いかと思いますが、どのユーザーがアクセスしてきたのかを、この SID では直感的につかむことが困難です。

Active Directory や Microsoft Entra Connect で AD と同期している Entra ID であればユーザーの SID の情報を持っているはずですが、都度そのディレクトリを見に行くのはなかなか大変かと思います。

Log Analytics でクエリをかける場合、SID 情報を含むユーザー一覧を別途[**カスタムログ (テキストログ)**](https://qiita.com/YoshiakiOi/items/0a93fe3bbde8845fe3d0) や **Watchlist (要 Sentinel)** として取りこむ、Blob Storage に参照用のファイルを置いて検索するなど、いくつか手法が考えられます。ですが、特にもし Microsoft Entra Connect を使っている場合は、Sentinel の [**UEBA 機能**](https://learn.microsoft.com/ja-jp/azure/sentinel/identify-threats-with-entity-behavior-analytics) を便利に活用することができます。

### Sentinel UEBA の利用

利用する Log Analytics ワークスペースで Sentinel が有効になっている場合、そのワークスペースで [**UEBA 機能**](https://learn.microsoft.com/ja-jp/azure/sentinel/identify-threats-with-entity-behavior-analytics) を有効にすることで、Entra ID からユーザー情報が同期され、ワークスペースの [**IdentityInfo** テーブル](https://learn.microsoft.com/ja-jp/azure/azure-monitor/reference/tables/identityinfo) に格納されます。Entra Connect で ID 同期を行っている場合、Entra ID 側でも Active Directory のユーザー情報を保持しており、その中には Active Directory の SID も含まれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/e49da662-b66b-76d1-8526-4ab68a607b04.png)

Log Analytics ワークスペースに格納された、UEBA が生成した  [**IdentityInfo** テーブル](https://learn.microsoft.com/ja-jp/azure/azure-monitor/reference/tables/identityinfo) からアカウント一覧を取るには、例えば下記のようにします。(arg_max()関数の使い方については、[「Azure Log Analytics と Kusto (KQL) 入門 3 - Join の使い方」](https://qiita.com/YoshiakiOi/items/95dd309fe0dcfc20a31a#arg_max%E5%BC%95%E6%95%B01-%E5%BC%95%E6%95%B02-by-%E5%88%97%E5%90%8D1-%E9%9B%86%E8%A8%88%E9%96%A2%E6%95%B0)にてご紹介していますので、ご興味ある方はご参照ください。)

```: Kusto
IdentityInfo 
| where TimeGenerated > ago(31d) 
| where isnotempty(AccountUPN)
| summarize arg_max(TimeGenerated, *) by AccountUPN
```

そして、IdentityInfo テーブルでは、AccountSID 列が SID になっているので、StorageFileLogs テーブルの SmbPrimarySID とそれぞれ Key にして Join をかけます。こうすることで、検索で出たきたテーブルの中にアクセスしたユーザーの UPN が含まれるようになります。

サンプルのクエリは下記になります。

```: Kusto
StorageFileLogs 
| where TimeGenerated > ago(31d)
| where Protocol == "SMB"
| where ObjectKey !contains "file.core.windows.net\\IPC$\\"
| sort by TimeGenerated desc 
| join kind=leftouter ( 
    IdentityInfo
    | where TimeGenerated > ago(31d) 
    | where isnotempty(AccountUPN)
    | summarize arg_max(TimeGenerated, *) by AccountUPN
    | project AccountUPN, AccountSID
    ) on $left.SmbPrimarySID == $right.AccountSID
| project TimeGenerated, AccountName, Location, Protocol, OperationName, AuthenticationType, Uri, ObjectKey, SmbPrimarySID, AccountUPN, Category, SmbCommandMinor, MetricResponseType, Type, _ResourceId
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/3b66fedb-e17d-b9d9-65d5-17c5a6cfb79e.png)

### Blob Storage に参照用ファイルを配置

もし Sentinel を利用しない場合、各ユーザーのオンプレミス AD の SID を参照するために、そのリストを Blob Storage に置いておいて Log Analytics から参照するということが考えられます。

例えば、特定のストレージアカウントの Blob コンテナーに置いた userlist.csv というファイルに対してクエリをかけるには下記のような検索文を使うことができます。

\<Blob Storage に配置する userlist.csv の例\>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/d373e595-ce86-2a49-519b-7fae01d188f4.png)

\<その CSV ファイルの中身を Kusto クエリで扱う例\>

```:Kusto
externaldata(Id:string, DisplayName:string, UserPrincipalName:string, OnPremisesSecurityIdentifier:string)
[
@'<Blob Storage コンテナーの URL>/userlist.csv?'
h@'<SAS>'
]
with (format='csv', ignorefirstrecord = true)
```

なお、Kusto (KQL) で、`@`はエスケープ、`h文字列`は難読化用です。

そして、Sentinel UEBA の時と同じく、Join でクエリを生成することができます。

```:Kusto
let UserList = externaldata(Id:string, DisplayName:string, UserPrincipalName:string, OnPremisesSecurityIdentifier:string)
[
@'<Blob Storage コンテナーの URL>/userlist.csv?'
h@'<SAS>'
]
with (format='csv', ignorefirstrecord = true)
| project UserPrincipalName, OnPremisesSecurityIdentifier;
StorageFileLogs 
| where TimeGenerated > ago(31d)
| where Protocol == "SMB"
| where ObjectKey !contains "file.core.windows.net\\IPC$\\"
| sort by TimeGenerated desc 
| join kind=leftouter ( 
    UserList
    ) on $left.SmbPrimarySID == $right.OnPremisesSecurityIdentifier
| project TimeGenerated, AccountName, Location, Protocol, OperationName, AuthenticationType, Uri, ObjectKey, SmbPrimarySID, UserPrincipalName, Category, SmbCommandMinor, MetricResponseType, Type, _ResourceId
```

上記の userlist.csv という Entra ID 上のユーザーのリストは、Microsoft Graph PowerShell SDK の Beta 版を使って、取得することができます。

```PowerShell: PowerShell スクリプト例
Connect-MgGraph -Scopes 'User.Read.All'
$userList = Get-MgBetaUser -All
$userList | Select-Object Id, DisplayName, UserPrincipalName, OnPremisesSecurityIdentifier | Export-Csv userlist.csv -NoTypeInformation
```

# (補足) Kusto (KQL) 参考情報

先に Kusto (KQL) について記事にまとめていますので、もし KQL 自体の確認をされたい方はこちらをご覧ください。

https://qiita.com/YoshiakiOi/items/f2cb2b5626c2f7f71dba

https://qiita.com/YoshiakiOi/items/9f649c9b9c97dc6e8e3d

https://qiita.com/YoshiakiOi/items/95dd309fe0dcfc20a31a

# 最後に

本記事では Azure Files の診断設定と Log Analytics ワークスペースへのログ送信を確認し、またワークスペース上でのクエリのかけ方について見ていきました。本稿が、Azure Files のログ活用の一助になれば幸いです。

＊本稿は、個人の見解に基づいた内容であり、所属する会社の公式見解ではありません。また、いかなる保証を与えるものでもありません。正式な情報は、各製品の販売元にご確認ください。