midPoint における源泉削除の同期処理

# はじめに

[midPoint by OpenStandia Advent Calendar 2024](https://qiita.com/advent-calendar/2024/midpoint-by-openstandia) の6日目は、[5日目](https://qiita.com/wadahiro/items/a239a743af5404a7325f)で説明しきれなかった下記の**1つ目**について、補足します。次は組織のインポートについて紹介する予告をしていましたが、組織インポートにおいてもこれは関係してくる話なので、先にこちらの補足記事を書くことにしました。

- **源泉削除に対する同期処理**
- マルチバリュー項目に対するマッピング処理

:::note info
5日目で構築したDocker Composeを利用した環境が前提となります。
:::

# 源泉削除に対する同期処理

[5日目の記事](https://qiita.com/wadahiro/items/a239a743af5404a7325f#%E8%A1%8C%E3%81%AE%E5%89%8A%E9%99%A4)で紹介したように、源泉CSVファイル側で行を削除しても、その内容をmidPointに反映することができていませんでした。これは、**「Import Task（インポートタスク）」** という種類のタスクを使用しているためです。同期用のタスクとしては他に、**「Reconciliation Task（リコンシリエーションタスク）」** と **「Live Synchronization Task（Live同期タスク）」** があり、それらであれば削除に対する同期処理も可能です。昨日の環境にタスクを追加して、動作を確認してみます。

:::note info
この3つの同期タスクの違いについては、[The Bookの「Synchronization」の章](https://docs.evolveum.com/book/practical-identity-management-with-midpoint.html#05-synchronization) などで語られています。インポートはその名のとおり、リソースからのインポート用です。なので削除は検知しません。リコンシリエーションはその英単語の意味である「和解」や「調和」が示すように、midPointとリソース間のデータの整合性を解消します。そのため、リソース側の削除も検知します。Live同期は特殊で、リアルタイムな同期を目的としています。差分情報だけmidPointに渡して処理するものであり、その差分として削除情報も渡せるようになっています（ただし、コネクターとリソース側が対応している必要があります）。


:::

## リコンシリエーションタスク

### リコンシリエーションタスクの作成

昨日の記事で紹介したタスクの作成とはまた別の導線からの作成方法を紹介します。リソースの詳細画面を開き、「定義されたタスク」メニューを開きます。この画面では、このリソースに関連するタスクの一覧を参照・追加などが可能です。すでに昨日、インポートタスクを作成済みですので、それが表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/b571992a-e3c7-345c-9e83-5ddc631577a6.png)

ここで![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/e7568f6c-a4b9-055b-b7df-90e4ed98d84f.png)アイコンをクリックすると、タスク作成のダイアログがポップアップ表示します。「Reconciliation task」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/a0f13232-4fdc-87a0-8ac2-e70ab3611136.png)

そうするとタスク作成のウィザード画面に遷移しますので、必要な設定を行います。まず、基本設定です。「名前」はタスク全体でユニークである必要があるので、被らないように任意の名前を設定すればよいです。「次へ：リソース・オブジェクト」ボタンをクリックして先に進みます。

- **名前**：`HR recon users`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/8a6e58e6-ad5d-e541-5cca-98df826a28e5.png)

リソース・オブジェクトの設定画面が表示されるので、以下を追加設定して「次へ：スケジュール」ボタンをクリックします。今回はタスクの一覧画面から作成を開始しているため、手動で設定する箇所が少し増えています。

- **種類**：`アカウント`
- **用途**：`default`
- **オブジェクトクラス**：`AccountObjectClass`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/02009c0d-d72e-3329-0708-54ded7655b1d.png)

リコンシリエーションタスクの場合、「スケジュール」の設定画面が次に表示されます。定期的な実行を**時間間隔設定**か**Cronライク書式設定**のどちらかで設定可能です。今回は定期実行させないため、未設定のまま「次へ：ディストリビューション」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/c1ba611d-7c41-92ab-efba-c63adee67f67.png)

ディストリビューションの設定画面が表示されます。インポートタスクと同様にワーカースレッド数を設定して、「設定を保存」ボタンをクリックします。

- **ワーカー・スレッド**：`1`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/26ad60d3-c3d9-e9f6-0004-025893f75f52.png)


リソースの編集画面に戻ってきます。今作成したタスクが増えていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/44483ce9-d601-d024-b23b-255d56d181f0.png)

### リコンシリエーションタスクの実行

削除同期のパターンを試してみます。CSVファイルから適当な行（例：`1001`のユーザー）を削除しておきます。

リソースの「定義されたタスク」に表示されている「HR recon users」をクリックして、リコンシリエーションタスクの詳細画面を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/5845aef0-f740-f478-3d23-65612658698c.png)

「再開する」ボタンをクリックしてタスクを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/e8609f6b-946b-5fff-89e2-f2ee7c1e7558.png)

しばらく待つと自動リフレッシュされ、「終了」状態になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/54471158-32b7-4d4e-873d-32a91eccfe2c.png)

ユーザー一覧を確認すると、`1001`のユーザーが消えていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/1db8601f-20e3-464d-2aa7-aeb66a1e9520.png)

midPointが記録する監査ログからも確認しておきます。画面左メニューの「監査ログビューザー」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/3adf5eb0-802b-ba9e-50b8-0fca166a843f.png)

監査ログビューアーより、`1001`のユーザーが削除されたことを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/e5b035d8-b74a-4d70-c837-f9b3cef25b01.png)


## Live同期タスク

Live同期タスクも同様に削除を同期することができます。ただし、[3日目の記事の脚注](https://qiita.com/wadahiro/items/df964d32e28f3e3427d8#fn-2)で少し触れていましたが、Live同期は、コネクター側（とリソース側も必要に応じて）が差分抽出に対応している必要があります。CSVコネクターは対応しているため、試すことができます。

:::note info
CSVコネクターの差分抽出の実装としては、CSVファイルの同ディレクトリに、前回Live同期タスクを実行した際にタイムスタンプ付きのファイル名でコピーを作成しておいて、それと現在のCSVファイルを比較して差分抽出を行っています。
:::

### Live同期タスクの作成

リコンシリエーションタスクと同じような流れでLive同期タスクを作成します。「Live synchronization task」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/cec932f8-de6b-0e8d-6e07-fde7ff7fe809.png)

- **名前**：`HR live-sync users`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/00ab682f-724c-2313-7659-f0d24eeea8d9.png)

以下を追加設定して「次へ：スケジュール」ボタンをクリックします。

- **種類**：`アカウント`
- **用途**：`default`
- **オブジェクトクラス**：`AccountObjectClass`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/98f9e0e2-0f79-1dfc-2e1f-2c8bc28292cc.png)

Live同期タスクもリコンシリエーションタスクと同じで、スケジュール設定の画面が表示されます。ここも同様に、今回は未設定のまま「次へ：ディストリビューション」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/ab2b61d5-86ec-91a4-5ae1-2518ccf78274.png)

同様に最後にワーカースレッド数を設定して、「設定を保存」ボタンをクリックします。

- **ワーカー・スレッド**：`1`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/d38851bc-7c39-17df-51cf-89c527130b13.png)

リソースの編集画面に戻ってきます。今作成したタスクが増えていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/e5bf4735-5ecd-4650-17ea-81277e4a4dae.png)

### Live同期タスクの実行

削除同期のパターンを試してみます。ですがその前に、先にタスクの再開を実施しておきます。作成したLive同期タスクの詳細画面を開き、「再開する」ボタンをクリックしてタスクを実行します。そうすると、ステータスのところに「1733384756775」のような値が設定されていることが分かります。これは「同期トークン」というもので、このLive同期タスクの最終実行日時（Unixタイムスタンプのミリ秒）を表しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/54dc4af4-f068-6181-d034-5cdfe4cb74a9.png)

また、`hr`ディレクトリ配下をみると、この同期トークン付きのファイルが増えていることを確認できます。次にLive同期タスクを実行すると、この同期トークン付きのファイルと比較して差分を検知するわけです。

```
-rw-r-----@ 1 user  staff   495B Dec  5 16:45 users.csv
-rw-r-----  1 user  staff   495B Dec  5 16:45 users.csv.sync.1733384756775
```

同期トークンが設定された状態で、CSVファイル（`hr/users.csv`）から適当な行（例：`1002`のユーザー）を削除します。

その後、Live同期タスクの詳細画面より「今すぐ実行」ボタンをクリックしてタスクを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/727f32c8-d6dc-8a73-6a07-3fb2194dd2a4.png)

しばらく待つと自動リフレッシュされ、「終了」状態になります。そして同期トークンが更新されたことも確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/94f40106-dc41-8d33-5633-520eb5e1c4f1.png)

ユーザー一覧を確認すると、`1002`のユーザーが消えていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/22a0d0ae-2393-7af4-c561-ac9f58a6d553.png)

同様に監査ログでも確認しておきます。Live同期タスクにより`1002`が削除されていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/6889af63-0b66-5bc1-cbf3-fcd1dfa3d7e4.png)

また、`hr`ディレクトリ配下をみると、新しい同期トークン付きのファイルが増えていることを確認できます。古い同期トークン付きのファイルも残っていますが、CSVコネクターの仕様として、デフォルトでこの同期トークン付きファイルを最大10個残すようになっています。

```
-rw-r-----@ 1 user  staff  495 Dec  5 16:56 users.csv
-rw-r-----@ 1 user  staff  551 Dec  5 16:45 users.csv.sync.1733384756775
-rw-r-----  1 user  staff  495 Dec  5 16:56 users.csv.sync.1733385377951
```

# まとめ

6日目は、5日目で説明しきれなかった **「源泉削除に対する同期処理」** について、補足解説を行いました。インポートタスクでは源泉データの削除について同期することができませんでしたが、他の種類の同期タスクを利用することで、削除同期ができることを紹介しました。

ただし、実際の現場では、HRシステムからCSVで渡される源泉データの形式が複数のパターンに分かれることがあります。例えば次のような場合です。

- パターン1：全量データが渡される
- パターン2：差分データが渡される（HRシステムや中間の配布システムで差分が計算される）

さらに、削除（退職）を表現する方法としては以下のような違いも想定されます。

- パターンA：削除を行削除で表現する
- パターンB：退職ステータスの更新で表現する

もし削除（退職）が行削除で表現されない場合、インポートタスクで十分対応できる可能性があります。仕様上、リコンシリエーションタスクはインポートタスクに比べて処理が重いため、要件を満たすのであれば、より軽量なインポートタスクを選択するのが望ましいでしょう。

次回はもう1点の **「マルチバリュー項目に対するマッピング処理」** について補足解説を行う予定です。お楽しみに！