Linux の audit ログを Azure の Blob Storage で長期保存する

# 概要
ログの管理については様々な方法がありますが、今回は Azure VM 上で動作する Linux の監査ログ(audit.log)を、 LogAnalytics および Blob Storage で保存する方法についてご紹介します。

ログの管理を Azure だけで完結させたい場合や、監査対応等で長期間のログ保存が必要な場合に有用な方法となります。


# 構成イメージ
![azure-log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/ecd997ad-7fda-9add-0f8d-3a575a9b579e.png)


# 全体の流れ
設定の流れは以下のようなイメージです。

1. Linux で audit の設定をする
1. Linux VM へ LogAnalytics エージェントをインストールする
1. エージェント経由で LogAnalyticsへログを収集
1. 長期保存用のBlobストレージへログデータの転送設定をする

# 設定手順

## Linux VM で audit の設定を実施する
今回は audit.log を収集するので、最初に audit の設定を実施します。
その他のログを収集する場合、本手順は読み飛ばしてください。

以下の手順は全てrootユーザで実施してください。

- 事前ルール確認
```
# auditctl -l
No rules
```

- 事前ルールファイルの確認
```
# grep -v "^#\|^$" /etc/audit/rules.d/audit.rules
-D
-b 8192
-f 1
```

- audit.rulesの編集

このケースでは、execve システムコールが発行された時のログをまるっと取得する例です。
```
# vi /etc/audit/rules.d/audit.rules
-D
-b 8192
-f 1
-a always,exit -F arch=b64 -S execve  <- 追記
```

- 設定反映のためaudit.serviceを再起動
```
# service auditd restart
```

- 事後ルールの確認
```
# auditctl -l
-a always,exit -F arch=b64 -S execve
```
<font color="red">**-a always,exit -F arch=b64 -S execve**</font> が表示されることを確認します。

- audit.log に execve システムコールに関するログが出力することを確認します。
```
# tail -f /var/log/audit/audit.log
type=SYSCALL msg=audit(1633917159.095:272483): arch=c000003e syscall=59 success=yes exit=0 a0=22878c0 a1=21ba720 a2=21b3d10 a3=7ffe7d126ee0 items=2 ppid=25078 pid=25976 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=7713 comm="tail" exe="/usr/bin/tail" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
type=EXECVE msg=audit(1633917159.095:272483): argc=3 a0="tail" a1="-f" a2="/var/log/audit/audit.log"
type=CWD msg=audit(1633917159.095:272483):  cwd="/root"
type=PATH msg=audit(1633917159.095:272483): item=0 name="/bin/tail" inode=16879639 dev=08:02 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:bin_t:s0 objtype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
type=PATH msg=audit(1633917159.095:272483): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=33715359 dev=08:02 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:ld_so_t:s0 objtype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
type=PROCTITLE msg=audit(1633917159.095:272483): proctitle=7461696C002D66002F7661722F6C6F672F61756469742F61756469742E6C6F67
```
これで audit の設定は完了です。

## LogAnalytics ワークスペースを作成する
任意のサブスクリプションを選択し、 **リソースグループ** と **インスタンス名** を入力して作成します。
![image-20211214-031754.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/60ce0393-dae3-f976-9f4c-04a96d71acd6.png)

## Linux VM に LogAnalytics エージェントをインストール
作成したワークスペースの「エージェント管理」→「Linuxサーバー」タブを選択。
wgetのコマンドラインをコピーしておく。
![スクリーンショット 2021-11-24 15.56.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/3f25038c-4769-f1c8-7cb2-0c43e13372fd.png)

- 対象VMでコマンドを実行しインストールする
```
# wget https://raw.githubusercontent.com/Microsoft/OMS-Agent-for-Linux/master/installer/scripts/onboard_agent.sh && sh onboard_agent.sh -w ＊＊＊＊＊＊＊＊＊＊＊ -s ＊＊＊＊＊＊＊＊＊＊＊ -d opinsights.azure.com
: (省略)
```

- インストール後の状態確認
```
# /opt/microsoft/omsagent/bin/omsadmin.sh -l
Primary Workspace: ＊＊＊＊＊＊＊＊＊＊＊    Status: Onboarded(OMSAgent Running)
```
<font color="red">**Status: Onboarded(OMSAgent Running)**</font> となっていることを確認する。


## VM と LogAnalytics ワークスペースと関連付ける
ワークスペースの「仮想マシン」から対象のVMを選択します。
![スクリーンショット 2021-11-24 16.16.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/20e33986-5262-821c-0f7d-073048dc773f.png)

接続ができていない場合は、「接続」をクリックしてVMと連携させます。
![スクリーンショット 2021-11-24 16.17.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/3240842a-2b68-c60c-f46d-21350a009cc7.png)

## カスタムログ設定で audit.log を LogAnalytics で収集する
- Azure Portal にログインし、対象のワークスペースを選択します。
- 画面左側の [カスタム ログ] ブレードを選択します。
- [+ カスタム ログの追加] をクリックし、カスタム ログの作成画面を開きます。
- [サンプル] タブより、サンプル ログ ファイルをアップロードします。
※ サンプル ログは、監視対象の端末より audit.log を取得の上指定する。
![image-20211011-235751.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/6f8e834a-b26a-fae3-c04a-4e68d5ab69be.png)

- [レコードの区切り記号] タブより、レコードの区切り文字を選択します。
![image-20211011-235811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/72f20e3d-6fa8-1123-4494-02030d1a9748.png)

- [コレクション パス] タブより、仮想マシン上でログ収集を行う際のパスを追加します。
![image-20211011-235837.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/d030452d-3296-4dc0-9093-76bff6ed51c0.png)

- [詳細] タブより、カスタム ログ名と説明を入力します。
![image-20211011-235854.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/6eebf47a-6286-33fa-6b51-47bbabf20c35.png)

- [確認および作成] タブより、[作成] をクリックします。
![image-20211011-235908.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/2000cedb-ce72-5d1a-be7f-597c33770af3.png)

上記設定後、カスタムログの収集が開始されます。

:::note info
INFO
カスタムログに定義されているポイントから開始されます。
カスタムログ作成中にアップロードしたエントリは保持されませんが、ログファイルに既に存在するエントリが収集される動作です。
なお、設定反映までに最大1時間程度かかる可能性がある点は注意が必要です。
:::

対象の LogAnalytics ワークスペース上から以下のようなサンプルクエリを実行し、対象ログの検索が可能かを確認してください。
```
サンプル クエリ
〇〇_CL       -> "〇〇" は、上記手順で入力したカスタムログ名です。
```
![image-20211011-235932.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/beed554f-1d97-0352-0474-f91a2c09f0ee.png)

## ログデータをBlobストレージへ配置する
### ストレージ アカウントにコンテナーを作成する

- Azure Portal にアクセスし、ログの保存先としたいストレージ アカウントを開きます。
- 左側メニューの [コンテナー] をクリックし、画面上部の [+コンテナー] をクリックします。
- コンテナーの名前とアクセス レベルを設定します。
※ここでは、例として "loganalytics-data" の名前のコンテナーを作成します。
![image-20211214-082340.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/24562e98-82d5-275a-3625-26c19ef0a5c4.png)
- [作成] をクリックします。

### ロジック アプリを作成します
- Azure Portal にアクセスし、画面上部の検索欄から、ロジックアプリを開きます。
- 画面上部の [+追加] から、ロジックアプリリソースのデプロイを行います。
- 「ログ分析を有効化」を有効にして先に作った LogAnalytics を選択します。
![image-20211214-082546.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/b09af47c-9b7b-abda-a299-f589d51308c3.png)

### ロジックアプリのワークフロー(トリガー)を作成する
作成したロジックアプリを開くと、[Logic Apps デザイナー] が展開されます。

- 「繰り返し」 アクションを設定する
[一般的なトリガーで開始する] から、"繰り返し" を選択します。
![image-20211214-083053 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/a4dd812f-83ad-3b4c-ad65-a8412cb39199.png)

「繰り返し」コネクターを作成することで、設定した頻度で以下に作成するワークフローを実行する事が可能です。
ここでは、1日1回実行されるように、[間隔]を"1"、[頻度]を"日"と設定します。
![image-20211214-083154.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/ccfd1974-dfa2-c1ce-02d8-12019faef5cc.png)

- Azure Monitor Logs アクションを設定する
    - [+ 新しいステップ] をクリックし、検索欄で "azure monitor" と検索します。
"Azure Monitor ログ" をクリックし、[アクション] タブから 「クエリを実行して結果を一覧表示する」を選択します。
    - 対象の Log Analytics ワークスペースが存在する [テナント] を選択し、[サインイン] をクリックします。
    - [サブスクリプション] 、[リソースグループ]、[リソースの種類]、[リソース名] を選択します。
    - 任意の [クエリ] 、 [時間範囲] を設定します。

この処理で Log Analytics ワークスペースで出力したいデータを検索できます。

<font color="LimeGreen">**サンプル クエリ**</font>
※現在日時の 1 日前のデータ 1 日分を検索します
```
let dt = now();
let year = datetime_part('year', dt);
let month = datetime_part('month', dt);
let day = datetime_part('day', dt);
let hour = datetime_part('hour', dt);
let startTime = startofday(make_datetime(year,month,day,0,0)) - 1d;
let endTime = startTime + 1d - 1tick;
Audit_Log_CL // カスタム ログ テーブル名を指定します
| where ingestion_time() between(startTime .. endTime)
```
![image-20211214-092721.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/c447f88b-0c65-99f7-b173-ad1959ea1949.png)

:::note warn
本アクションは以下の制限があるので、注意してください。
・ ログ クエリで 500,000 より多い行を返すことはできません。
・ ログ クエリで 64,000,000 より多いバイト数を返すことはできません。
・ 既定では、ログ クエリの実行時間は 10 分を超えることはできません。
・ Log Analytics コネクタは、1 分あたり呼び出し 100 回に制限されます。
:::

- Parse JSON アクティビティ ("JSON の解析") を設定する
    - [+ 新しいステップ] をクリックし、検索欄で "json" と検索します。
    - [ビルトイン] タブから、"JSON の解析" を選択します。
    - [コンテンツ] をクリックし、[クエリを実行して結果を一覧表示する] から、"本文" を選択します。
    - [サンプルのペイロードを使用してスキーマを生成する] をクリックし、サンプル ペイロードを入力します。

<font color="LimeGreen">**サンプル ペイロードの例**</font>
```
{
    "TenantId": "e2af94d3-d574-490d-9c5c-7c722e32c2df",
    "SourceSystem": "OpsManager",
    "MG": "00000000-0000-0000-0000-000000000002",
    "ManagementGroupName": "tmpVM01",
    "TimeGenerated": "2021-10-27T22:30:14Z",
    "Computer": "tmpVM01",
    "RawData": "type=USER_START msg=audit(1635373794.205:129): pid=2340 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:unconfined_service_t:s0 msg='op=PAM:session_open grantors=pam_keyinit,pam_limits,pam_keyinit,pam_limits,pam_systemd,pam_unix acct=\"root\" exe=\"/usr/bin/sudo\" hostname=? addr=? terminal=? res=success'\r\n",
    "Type": "Audit_Log_CL",
    "_ResourceId": "/subscriptions/4db33d72-262b-4238-8de3-2fcd63ac074b/resourcegroups/2110050060000725/providers/microsoft.compute/virtualmachines/tmpvm01"
}
```
![image-20211214-093417.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/8a77d4b0-df44-3410-a111-d3e356ffcaf3.png)

- 「作成」アクションを設定する
    - [+ 新しいステップ] をクリックし、検索欄で "作成" と検索します。
[ビルトイン] タブから、"作成" を選択します。
    - [入力] をクリックし、[JSON の解析] から、"本文" を選択します。
![image-20211214-093526.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/df12599e-3011-2b1a-1d71-20b0de00110a.png)

- BLOB の作成アクションを設定する
    - [+ 新しいステップ] をクリックし、検索欄で "blob" と検索します。
    [すべて] タブから、"Blob を作成する (V2) " を選択します。
    - 任意の [接続名] を入力し、[認証の種類]、[Azure Storage のアカウント名]、[Azure Storage アカウントのアクセス キー] を入力し、[作成] をクリックします。
    - 出力先の [ストレージ アカウント名] 、[フォルダーパス] を入力します。
    - [Blob] 名を指定します。
![image-20211214-093631.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/a8da2f8e-34d7-af46-d3b2-48ef96fe30f6.png)

:::note info
INFO
[認証の種類] 、[アクセス キー] は、該当のストレージアカウントのメニューより確認できます。
[認証の種類] は、[Azure Portal] -> [ストレージ アカウント] -> [コンテナー] -> 該当のコンテナー で確認できます。
:::

![image-20211214-093728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/abf85458-ec09-a774-d5bf-165ea656f129.png)

:::note info
INFO
[アクセスキー] は、[Azure Portal] -> [アクセスキー]より確認できます。
:::
![image-20211214-093756.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/f5566afc-763b-dc93-50b7-6522724a74e2.png)

ワークフローが実行されると、[フォルダーパス] の配下に [Blob名] にて指定をしたファイル名でログが出力されます。
例えば、[式] にて以下を指定すると、 1 日前の日付のファイル名でログが出力されます。
```
subtractFromTime(formatDateTime(utcNow(),'yyyy-MM-dd'), 1,'day')
```
![image-20211214-094101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/0e59df46-2710-cbb5-439b-9746399402f8.png)



### ロジックアプリをテストする

- 画面上部の [保存] をクリックします。
- 画面上部の [トリガーの実行] をクリックします。ワークフローが開始されます。
なお、ワークフローの開始時刻、および成功したかの確認は、ロジックアプリの [概要] より確認できます。

「成功」 した場合は、Blob ストレージを確認し、ログファイルが出力されていることを確認します。

<font color="LimeGreen">**出力例**</font>
![image-20211214-094256.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/8d676f5b-a8eb-a0ca-eb6f-58f3b4ebb6ec.png)

「失敗」 した場合は、"失敗" をクリックし、失敗箇所の詳細を確認し修正します。

<font color="LimeGreen">**「失敗」の確認例**</font>
![image-20211214-094344.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982074/b464a3c7-8efb-d4a7-187c-b4be2a8ffeba.png)

設定は以上となります。
あとは、設定した通りにログが出力されるようになったことを見届ければ完了です！

# まとめ
- LogAnalyticsに出力するまでは結構すぐいける
- BlobとLogic Appあたりで詰まってやめたくなる
- ワークフローでエラーになるとショックでかい
- 乗り越えたらあとは放置でハッピー :raised_hands:

# 参考文献
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/security_guide/sec-understanding_audit_log_files

https://learn.microsoft.com/ja-jp/azure/azure-monitor/logs/log-analytics-overview

https://learn.microsoft.com/ja-jp/azure/storage/blobs/storage-blobs-introduction

https://learn.microsoft.com/ja-jp/azure/logic-apps/logic-apps-overview