midPoint にCSVの源泉データをインポートする（ユーザー編）

# はじめに

[midPoint by OpenStandia Advent Calendar 2024](https://qiita.com/advent-calendar/2024/midpoint-by-openstandia) の5日目は、4日目で構築した開発/検証環境の上でmidPointの設定を行い、ユーザー情報を含むCSV形式の源泉データをmidPointにインポートします。

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


# 源泉データの準備

サンプルの源泉データを準備します。なお、このダミーのユーザーデータはChatGPTに生成してもらいました。`primaryOrgId`は主務の組織ID、`secondaryOrgIds`は兼務の組織IDを表します。兼務は複数可能として、`;`を区切り文字としたマルチバリューとしています。

```csvs
employeeNumber,givenName,familyName,email,primaryOrgId,secondaryOrgIds
1001,太郎,山田,taro.yamada@example.com,005,006;007
1002,花子,佐藤,hanako.sato@example.com,006,005;009
1003,次郎,鈴木,jiro.suzuki@example.com,007,006
1004,美咲,高橋,misaki.takahashi@example.com,008,009
1005,健一,田中,kenichi.tanaka@example.com,009,008
1006,陽菜,伊藤,hina.ito@example.com,005,
1007,翔,渡辺,sho.watanabe@example.com,006,
1008,さくら,小林,sakura.kobayashi@example.com,007,
1009,優,中村,yu.nakamura@example.com,008,005;007
1010,一郎,山本,ichiro.yamamoto@example.com,009,006
```

上記内容のCSVファイルを作成し、`hr`ディレクトリを作成してその配下に`users.csv`として保存しておきます。

```
.
├── docker-compose.yml
├── hr
│   └── users.csv
└── post-initial-objects
    └── 000-system-configuration.xml
```

# docker-compose.ymlの修正

下記修正を行い、`hr`ディレクトリをmidPointコンテナにマウントさせておきます。これでmidPointからは、`/var/lib/hr/users.csv`でCSVファイルにアクセス可能になります。

```diff_yaml
  midpoint_server:
    image: evolveum/midpoint:${MP_VER:-latest}-alpine
    container_name: midpoint_server
    hostname: midpoint-container
    depends_on:
      data_init:
        condition: service_completed_successfully
      midpoint_data:
        condition: service_started
    command: [ "/opt/midpoint/bin/midpoint.sh", "container" ]
    ports:
      - 8080:8080
    environment:
     - MP_SET_midpoint_repository_jdbcUsername=midpoint
     - MP_SET_midpoint_repository_jdbcPassword=db.secret.pw.007
     - MP_SET_midpoint_repository_jdbcUrl=jdbc:postgresql://midpoint_data:5432/midpoint
     - MP_SET_midpoint_repository_database=postgresql
     - MP_SET_midpoint_administrator_initialPassword=Test5ecr3t
     - MP_UNSET_midpoint_repository_hibernateHbm2ddl=1
     - MP_NO_ENV_COMPAT=1
     - MP_ENTRY_POINT=/opt/entry-point
     - TZ=Asia/Tokyo
    networks:
     - net
    volumes:
     - midpoint_home:/opt/midpoint/var
     - ./post-initial-objects:/opt/entry-point/post-initial-objects:ro
+    - ./hr:/var/lib/hr
```

# midPointの起動

`docker compose up -d`で環境を起動します。

# リソース設定の追加

ここからmidPointの画面を操作して、CSVをインポートするためのリソース設定を追加していきます。例によってシステム管理者（`administrator`）でmidPointにログインし、設定作業を行います。

実は2022年10月にリリースされたmidPoint 4.6より、リソース設定のウィザード画面が刷新されました。今回はこの新しいウィザード画面を使い、XMLを直接編集せずに設定してみます。

https://docs.evolveum.com/midpoint/reference/support-4.8/admin-gui/resource-wizard/

:::note info
[1日目の記事](https://qiita.com/wadahiro/items/5a50efe246302ca4585b)で紹介した、
[Methodology: First Steps With MidPoint](https://docs.evolveum.com/midpoint/methodology/first-steps/#how-to-use-this-methodology)という新しい学習コンテンツでは、midPoint 4.8よりGUIウィザードを使用してセットアップする方法で最初は学ぶことを推奨しています。このアプローチの利点として、midPointのXML仕様について学習することなく始められるという点が挙げられています。

<details><summary>Methodology: First Steps With MidPoint より引用</summary>

> Before midPoint 4.8, we recommended our users and customers to review our samples and base their midPoint configuration on them. These samples represented a sample final configuration. They were written in midPoint XML language and any customization required our users to understand the midPoint language.
>
> Since midPoint 4.8, the recommended way of starting with midPoint is using GUI wizards and following this methodology. The advantage of this approach is obvious: administrators can configure midPoint features and try them without learning another language such as midPoint XML object language. One significant burden is removed. New features such as Simulations can be used right from the beginning. Exceptions using Object Marks can be defined directly in GUI. This all helps to achieve a safe environment to try midPoint and avoid any unexpected modifications or even deletes in the target systems.
>
> But there is also a small disadvantage: when using interactive wizards such as resource wizard, it’s hard to prepare complete examples for learning purposes. Having a ready-to-use example in final state or even for each step of the interactive process would not be efficient and would beat the purposes of the interaction entirely.
> 
>As the initial state for this methodology is basically an empty midPoint, we have decided to document the methodology by following the interactive wizards. Therefore, be prepared that connecting and configuring a new system is an iterative and interactive process. If you get lost, do not hesitate to watch the video mentioned in the Introduction chapter.

出所：https://docs.evolveum.com/midpoint/methodology/first-steps/#how-to-use-this-methodology
</details>
:::

## リソースの作成

画面左のメニューより「リソース ＞ 新規リソース」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/33873b23-759d-ee13-c07a-956f8bd041b4.png)

新規リソース作成の画面が表示されるので、「スクラッチ」を選択します。

:::note info
今回は使用しませんが、事前にテンプレートを作成しておいて、それをベースに作成する方法も用意されています。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/c39639b8-1c0d-59ea-c7b3-a0eba2317a22.png)

リソースカタログの一覧が表示されます。今回はCSVファイルからインポートを行うため、「CsvConnector」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/394e8e97-0280-4b79-c685-9706a352a968.png)

リソースの基本情報の入力画面が表示されるので、以下のように設定して「次へ：設定」ボタンをクリックします。

- **名前**：`HR Users`
- **ライフサイクル状態**：`Active (production)`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/9af638f0-6b10-43fd-a25e-eef341c4f3d6.png)

:::note info
「ライフサイクル状態」はデフォルトでは`Proposed (simulation)`となっています。この状態にすると、midPoint 4.7で追加された[シミュレーション機能](https://docs.evolveum.com/midpoint/reference/support-4.8/simulation/)を使用して、変更を行うことなく事前に安全に動作を確認することができます。シミュレーション機能については、また別の日に紹介する予定ですので、本記事では`Active（production）`として設定します。
:::

次の画面では、CSVファイルのパスを設定します。以下のように設定し、「次へ：ディスカバリー」ボタンをクリックします。

- **File path**：`/var/lib/hr/users.csv`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/8160db0a-932a-49f3-52d9-05f078ad2c20.png)

次の画面では、CSVコネクターの詳細設定を行います。以下のように設定します。

:::note info
CSVコネクターはディスカバリーと呼ばれるAPIを実装しているため、実際のCSVファイルを読み込んで設定値をサジェストしてくれます。キーボードで入力する必要はなく、マウスで値を選択するだけで済みます。
:::

- **Multivalue delimiter**：`;`
- **Field delimiter**：`,`
- **User password attribute name**：（空のまま）
- **Name attribute**：`employeeNumber`
- **Unique attribute name**：`employeeNumber`
- **Multivalue attributes**：`secondaryOrgIds`[^1]

[^1]:今回のダミーデータでは複数兼務を表現するため、`secondaryOrgIds`カラムはマルチバリュー項目になっています。CSVコネクターにマルチバリューであることを認識させるために、この設定が必要となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/96f8065c-70b1-c4e0-a3fa-d5c5582c0dfb.png)

**「Multivalue attributes」** はデフォルトでは非表示です。「空項目を表示する」ボタンをクリックすると、非表示となっているその他の設定項目を表示することができます。その中にある **「Multivalue attributes」** に`secondaryOrgIds`を設定します。その後、「次へ：スキーマ」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/061ba640-2d93-c1c0-0236-1d1cc49f418b.png)


次の画面では、コネクターがサポートするオブジェクトタイプの一覧が表示されます。その中で使用するものを選択します。デフォルトで「AccountObjectClass」が選択済みのため、そのまま「リソースの作成」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/2615b5d0-e4ba-d90d-2eee-bd568d06cb3b.png)

リソースの作成が一旦完了します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/3101d95e-984c-e287-9083-f7f54d1e7cd7.png)

なお、「Preview Resource Data」を選択すると、コネクターを通じてリソース内のデータ一覧を参照することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/c02a518c-3359-b3fa-cab9-24520d0cf48d.png)

次は、「オブジェクト・タイプの設定」を選択して、CSVのデータをmidPoint内のどのオブジェクトにマッピングしてインポートするか設定していきます。


## オブジェクト・タイプの追加

:::note info
もし、「ウィザードを終了」ボタンをクリックするなどで画面を閉じてしまった場合は、作成済みのリソースの詳細画面を開き、「スキーマ処理」メニューを開いて「オブジェクトタイプの追加」ボタンをクリックすると、オブジェクト・タイプの設定ウィザードをまた開始できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/def5fc0a-79b5-2ce5-7d62-ac3e71a89a17.png)
:::

基本情報の画面では以下を設定し、「次へ：リソース・データ」ボタンをクリックします。

- **表示名**：`Account`
- **種類**：`アカウント`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/4a8e4349-a930-efdd-3748-58dd608dae0b.png)


次のリソース・データの画面では、特に設定は不要です。「次へ：MidPointデータ」をクリックして先に進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/3d269f19-1e1d-5f97-d21f-73d5a1f37576.png)

MidPointデータの画面では以下を設定し、「設定を保存」をクリックします。今回はmidPointのユーザーオブジェクトとして取り込みたいので、「ユーザー」を設定します。

:::note info
アーキタイプは重要な機能なのですが、本記事ではまだ使用しません。別の記事で紹介したいと思います。
:::

- **タイプ**：`ユーザー`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/9ceec9be-9913-8a0d-5641-4eb69706721d.png)

オブジェクトタイプを保存すると、追加したオブジェクトタイプに関するウィザード画面が表示されますので、次は「マッピング」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/2a4407cd-f16f-ac47-77ff-fa354a6267b1.png)


### マッピングの設定

:::note info
もし、画面を閉じてしまった場合は、作成済みのリソースの詳細画面を開き、「スキーマ処理」メニューを開いて、先程追加した「Account」オブジェクトタイプの表示名部分をクリックすると、オブジェクト・タイプのウィザード画面にまたアクセスできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/39b05b3d-434a-12d1-2abb-2b30eb1754af.png)
:::

今回はCSVファイルを源泉データとして取り込み、midPoint内にユーザーを作成したいので、**インバウンドマッピング**を設定します（別の記事で解説予定ですが、midPoint内のデータを外部のリソースにプロビジョニングしたい場合は、アウトバウントマッピングを使用します）。

「インバウンドマッピング」タブが選択されていることを確認し、「インバウンドの追加」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/0fb3634d-1919-9a19-1698-3eceaa3d9409.png)

そうすると編集行が追加されます（緑色の箇所）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/89836431-82e5-03f2-a61b-16fdf755c460.png)

入力フィールドではサジェスト機能が働くため、マウスで選択や、先頭文字を少し入力すると絞込んで表示してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/17a33eaf-ee73-cb24-2a12-6b4598c904f4.png) ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/b8e258c6-273a-18c4-dfae-4f0526974979.png)

以下のように設定します。なお、名前（このマッピングの名前）は必須ではありません。デバッグ用途で使われます。**From resource attribute** はソース側（取り込み元）であるCSVの属性を指定します。**ターゲット** にはターゲット側（取り込み先）であるmidPointのユーザー属性を指定します。

- **From resource attribute**：`employeeNumber`
- **式**：`現状`[^2]
- **ターゲット**：`name`

[^2]:日本語翻訳がよくありませんが、英語だと**As is**となっています。意味としては、その値のままマッピングするという意味です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/00dbb13d-1b5d-b18c-4591-e32147ec0701.png)

続けて「インバウンドの追加」ボタンをクリックし、編集行を追加して他の属性のマッピングも設定します。これを取り込みたい属性の数分繰り返します。マッピング内容は下表を参考に設定してください。

| From Resource Attribute | 式   | ターゲット            |
|:------------------------|:-----|:---------------------|
| employeeNumber          | 現状 | name                |
| email                   | 現状 | emailAddress        |
| familyName              | 現状 | familyName          |
| givenName               | 現状 | givenName           |
| primaryOrgId            | 現状 | organization         |
| secondaryOrgId          | 現状 | organizationalUnit  |


最終的には以下のようなインバウンドマッピングが設定された状態となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/ae5b07a1-66b7-3b92-032d-72b1a43dffcb.png)

「マッピングを保存」をクリックして保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/08fc376f-4392-ca50-3410-f9c76be23023.png)

またウィザード画面に戻るため、次は「同期」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/a906e881-f69a-cb86-4c30-c8113b6ac32e.png)


### 同期の設定

インバウンドマッピングを設定しただけでは、midPointはまだデータの取り込み（同期）をしてくれません。細かい同期のルールを設定する必要があります。この同期のルール設定では、midPointがリソースとの間で検知した状況（Situation）に応じて、どのようなアクションを取るかを設定していきます。

「Add reaction」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/2579a2d2-557d-3c04-89ad-1ff7f2a97fe5.png)

そうすると編集行が追加されます（緑色の箇所）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/9e6e565d-8aea-7099-11e6-bb287c6afdc1.png)

以下を設定します。`Unmatched`という状況は、CSV内のユーザーに対応するデータがmidPoint内にまだ存在しない状況を意味します。この時、実現したいこととしては「midPointにユーザーを作成する」ですので、`フォーカスの追加`を選択します。

:::note info
フォーカス（Focus）はmidPoint用語の1つです。midPointでは管理の中心となるmidPointのオブジェクト（ユーザー、ロール、組織、サービス）のことを、まとめてフォーカスと呼んでいます。
:::

- **状況**：`Unmatched`
- **アクション**：`フォーカスの追加`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/3f32468a-d0a9-0339-e1c9-156a06a7d0bb.png)

続けて「Add reaction」ボタンをクリックして編集行を追加し、他のルールも追加します。ここでは例として、一般的な設定を行います。下表を参考に設定してください。

| 状況       | アクション           | 設定意図                                                                 |
|:-----------|:--------------------|:-------------------------------------------------------------------------|
| Unmatched  | フォーカスの追加    | midPoint内にまだ存在しない場合にユーザーを作成する                         |
| Linked     | 同期               | すでにインポート済みのユーザーに対してはCSV内容で属性を更新する           |
| Deleted    | フォーカスの削除    | CSVから削除された場合はmidPointのユーザーも削除する                       |
| Unlinked   | 紐づけ              | 既存のmidPointユーザー（画面から登録したユーザーや別の源泉から登録されたユーザーなど）と名寄せで一致する場合は紐づけ（そのShadowオブジェクトのオーナーをmidPointユーザーに設定）を行う


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/da9a06a8-ffff-4d71-df1a-eaa673db34c0.png)

「Synchronization設定を保存」ボタンをクリックして保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/a3392add-6de2-7806-a523-1188885cd82a.png)

またウィザード画面に戻るため、次は「Correlation」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/06111d61-1339-4d60-5af5-8a9cfa6882d9.png)




### Correlationの設定

Correlationはいわゆる **名寄せ** の設定です。先程の同期の設定で、状況が「Unlinked」の際にアクションを「紐づけ」と設定しました。この紐づけを正しく動作させるには、Correlationの設定を行い、どういったロジックで名寄せを行うのか設定する必要があります。

「ルールの追加」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/be8912d6-3026-f184-806c-40eb8c7b33cc.png)

そうすると編集行が追加されます（緑色の箇所）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/c09853bc-dd56-d8e7-0012-8be41cd474ee.png)

「ルール名」に区別が付くように`name`と入れておきます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/7ad8ae7a-fcd1-afd8-b58a-3d18c4c8118a.png)アイコンをクリックして編集画面を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/f2663bb2-c529-b923-fb82-ed3f35df5f55.png)

「Add correlator」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/d2fee8d6-b31a-44e8-f7d0-6df12e25d3d3.png)

そうすると編集行が追加されます（緑色の箇所）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/cd3f05bb-91c2-1ac7-fb34-439a08fc4fee.png)

「アイテム」に選択可能なアイテムは、インバウンドマッピングで設定したターゲットとなるmidPointのユーザーの属性になります。インバウンドマッピングの設定では、マッピング元となるリソース側（CSVファイル側）の属性を設定しており、`employeeNumber`を指定していました。このインバウンドマッピングの情報を利用して名寄せのルールを設定します。

今回は、CSVファイルの`employeeNumber`カラムの値を使用してmidPointのユーザーを`name`属性で検索し、完全一致するユーザーに対して名寄せを行う、シンプルなルールを設定します。以下のように設定します。

- **アイテム**：`name`
- **Search method**：`完全一致`（デフォルトのまま）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/f3fdb17f-a580-1580-9b80-098ba3fb94f4.png)

:::note info
この設定により、`name`に対するインバウンドマッピングの設定を参照して、CSVファイルの`employeeNumber`カラムを名寄せに使用します。
:::


「設定を確認」ボタンをクリックして元の画面に戻ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/7a4efdad-e266-2941-adfe-049e2d9d90f2.png)

ルールの一覧画面に戻ります。「Correlation設定を保存」ボタンをクリックして保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/1a50917b-6938-1f90-0b39-661de3987980.png)


# ユーザーのインポート

リソースの作成が完了しましたので、いよいよユーザーをインポートします。リソースの詳細画面から、手動で対象アカウントを選択してインポートすることもできますが[^3]、今回はインポートタスクを作成して一括取り込みを行います。

[^3]:2019年のAdvent Calendarの記事「[midPointにおける「IDライフサイクル管理」実践編（CSV/画面からの取り込み）](https://qiita.com/tama1/items/eb1fc55e38b3c48f88b4)」では、リソースの詳細画面から手動でインポートする手順を紹介していました。

## インポータタスクの作成

インポート処理を実行するタスクを作成します。いくつかやり方はありますが、今回は作成したリソースの編集画面の「アカウント」メニューから作成します。

画面左メニューの「リソース ＞ すべてのリソース」をクリックしてリソースの一覧を表示します。先ほどのウィザードで作成したリソースが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/deb7b9ab-2e3e-da2c-b8f0-30995a12d662.png)

リソースの編集画面を開き、「アカウント」メニューをクリックしてアカウント一覧を表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/df214854-7bd0-ee7f-20fa-f42a27e7c49e.png)

:::note info
リソースの作成ウィザードで「Preview Resource Data」を選択してリソースオブジェクトの一覧を参照していた場合は、そのタイミングでShadowオブジェクトが作成されるため、この画面でもアカウント一覧が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/59e23fb6-3811-9b07-a4f1-810d6bd017cd.png)
:::


画面上部にある「タスク」メニューを開き、「タスク作成」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/bd677579-20e8-6963-017c-e6fa8f0157e7.png)

タスクの作成画面が開きます。今回はインポートタスクという種類のタスクを作成したいので、「Import Task」を選択します。これで「タスク作成」ボタンをクリックします。

:::note info
今回はシミュレーション機能は利用しませんので、「Simulate task」は「OFF」のままとします。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/37326815-75a1-2aa0-0c63-0eb49bb24343.png)


基本設定画面が表示されるので、以下を設定して「次へ：リソース・オブジェクト」ボタンをクリックします。

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/ca6850d9-020e-bd9c-7242-c1c1cec8c3ae.png)


リソース・オブジェクトの設定画面が表示されるので、以下を追加設定して「次へ：ディストリビューション」ボタンをクリックします。

- **オブジェクトクラス**：`AccountObjectClass`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/f87be89f-32c1-5a04-e8fb-d38fcaaaf8a8.png)

ディストリビューションの設定画面が表示されます。このタスクの同時実行スレッド数[^4]を設定します。以下を設定して「設定を保存」をクリックします。

[^4]:インポート対象のデータ件数が多い場合、同時実行スレッド数を増やすとCPUをより消費しますが処理速度を上げることができます。ただし、CSVレコードの順番通りに処理されることを前提とするケースでは注意が必要です。マルチスレッドモードでは処理の順番は保証されません。

:::note warn
「保存して実行」をクリックすると、インポートタスクが即座に開始されますので注意してください。
:::

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/95690529-6bb9-63a2-d821-44e65df1cc9c.png)

リソースの編集画面に戻ってきます。「タスク」メニューを開き、「View import tasks」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/e875e8eb-4f0b-5ac4-f040-a8d23006cfed.png)


インポートタスクの一覧画面に遷移します。作成したインポートタスクが登録されていることが分かります。次はこのタスクを実行してユーザー取り込みをいよいよ行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/2b05dc38-e6e5-ee10-3e8a-99396a9b1e77.png)

## インポートタスクの実行

作成したインポートタスクの詳細画面を開きます。現在はまだ未実行の状態であり「一時停止済み」という状態になっています。「再開する」ボタンをクリックするとタスクが開始されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/57f881ce-1a20-dd77-94b9-144de548146d.png)

少し待つと、画面がリフレッシュされてタスクの実行結果が更新されます。以下のように「終了」状態となればタスクは実行完了しています。ここまで設定が正しく行われていれば、「成功」で完了しているはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/2612189e-cbe4-c92a-b638-26ceac8a9dab.png)

「オペレーション統計」メニューを開くと、もう少し詳細な実行結果を参照することができます。このタスクにより、10件処理されすべて成功したことが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/abfcbe76-efc2-7958-edb7-b7e96b276b45.png)

画面左メニューより「ユーザー ＞ すべてのユーザー」を開いて、ユーザーの一覧を確認してみましょう。無事にユーザーが取り込まれていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/219a00b7-8bc5-2528-b83d-a6c4527f0b74.png)

ユーザーの詳細画面をみると、各属性に想定通りマッピングされていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/dd472f09-ff33-8012-16cf-08b60ce07b3d.png)

## CSVファイルを変更して再インポート

CSVファイルの内容を編集して行を増減させたり、値を変更して再度インポートタスクを実行した際の挙動を確認しておきます。

### 行の追加

CSVファイルに以下の行を追加します。

```csvs
1011,菜々子,石井,nanako.ishii@example.com,007,005;009
```

インポートタスクの詳細画面より、「今すぐ実行」ボタンをクリックして再度実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/63fd8a07-60d4-d560-d26f-b3d8cbf98133.png)

midPointのユーザー一覧を再度確認すると、追加されていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/7ac4a0f7-01fc-d40b-0374-c32eb0ed9256.png)

### 行の削除

ちょうど先ほど追加した行（`1011`の行）をCSVファイルから削除して、同様にインポートタスクを再実行します。

すると、先程取り込んだ`1011`のユーザーは**残ったままです**。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/1747d657-d071-97ed-fe43-f885074628bc.png)

これは、**インポートタスクでは、同期の設定で追加した「状況（Situation）が Deleted」の状態を検知できない仕様** のためです。もし、源泉データから物理削除された状態を元に反映したい場合は、「Reconciliation Task（リコンシリエーションタスク）」か「Live Synchronization Task（Live同期タスク）」のどちらかを使用する必要があります。

:::note info
「Reconciliation Task（リコンシリエーションタスク）」と「Live Synchronization Task（Live同期タスク）」による源泉データの削除同期については、また別の記事で紹介したいと思います。ひとまず現時点では、インポートタスクだとデータの物理削除をmidPointに反映することはできない、という点を理解していただければと思います。
:::

### 値の更新（シングルバリュー項目）

以下のように、CSVファイルのメールアドレスを変更して、同様にインポートタスクを再実行します。

```csvs
1001,太郎,山田,taro.yamada@example.com,005,006;007
↓
1001,太郎,山田,yamada-taro@example.org,005,006;007
```

midPointのユーザー一覧を再度確認すると、メールアドレスが更新されていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/cefea51c-8b78-9b76-1707-79860fc10d8a.png)


### 値の更新（マルチバリュー項目）

今回のサンプルでは、midPointのユーザー属性である「組織（`organization`）」と「組織単位（`organizationalUnit`）」はマルチバリュー項目となっています。マッピング元となるCSVファイルの`primaryOrgId`、`secondaryOrgIds`列を更新するケースを次は試します。　

以下のようにCSVファイルを更新して、同様にインポートタスクを再実行します。

```csvs
1001,太郎,山田,yamada-taro@example.org,005,006;007
↓
1001,太郎,山田,yamada-taro@example.org,006,007;009
```

そうすると、midPointユーザーは以下のように更新され、**古い値が残り続けます**。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/dd924d08-cc13-dce9-2092-294ed7242b7e.png)

これは、マッピング先のユーザー属性はマルチバリュー項目であり、midPointではマルチバリュー項目に対してはデフォルトでは安全のため古い値を消さないという戦略を取っているためです。

:::note info
このあたりの話は、公式ドキュメントでは[Range](https://docs.evolveum.com/midpoint/reference/support-4.8/expressions/mappings/inbound-mapping/#range-of-inbound-mappings)と呼んで説明しています。CSV側を正にして値を完全に入れ替えたい場合は、追加の設定が必要となります。ただし現状（4.8 LTSだけでなく、最新のバージョン4.9でも）では、このRange設定はGUIでサポートされておらず、XMLを編集する必要があります。この設定についてはまた別の記事で紹介したいと思います。
:::

# Post-Initial Import化

今回設定したリソースとタスクも、[4日目の記事で紹介したPost-Initial Import](https://qiita.com/wadahiro/items/063d8cface3d1e49adf4#midpoint%E3%81%AE%E5%88%9D%E6%9C%9F%E6%A7%8B%E7%AF%89%E6%99%82%E3%81%AB%E8%A8%AD%E5%AE%9A%E3%82%92%E5%8F%8D%E6%98%A0%E3%81%99%E3%82%8B)を使うようにしておくと、一度環境を破棄しても再構築が容易になります。midPointでは「リポジトリ・オブジェクト」の画面から内部で管理されるオブジェクトをすべて参照・更新できますが、ここからエクスポートも可能です。

画面左メニューより「リポジトリ・オブジェクト ＞ すべてのオブジェクト」を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/bf1e40e2-2b80-2ff8-7aeb-7b92440c4d42.png)

「タイプ」を「リソース」に変更し、リソースの一覧を表示します。今回作成したリソース設定の「出力」ボタンをクリックしてエクスポートします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/29513f9b-fbc9-6036-75c1-657d12ad2b73.png)

同様に「タイプ」を「タスク」に変更してタスク一覧を表示し、「出力」ボタンをクリックして今回作成したインポートタスクの設定をエクスポートします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35233/bf28bd8c-9deb-cde9-6fad-a753585f4851.png)

エクスポートしたファイルをそれぞれリネームして分かりやすい名前に変更し、`post-initial-objects`ディレクトリ配下に配置します。リソース設定は`100-resource-hr-users.xml`、インポートタスク設定は`900-task-hr-import-users.xml`とします。

```
.
├── docker-compose.yml
├── hr
│   └── users.csv
└── post-initial-objects
    ├── 000-system-configuration.xml
    ├── 100-resource-hr-users.xml
    └── 900-task-hr-import-users.xml
```

なお、Post-Initial Importではファイル名のソート順で適用されます。よって、依存関係のあるファイルは依存元より順番に適用されるように、ファイル名の先頭に番号を振って調整するとよいでしょう。今回の場合、タスク設定のXMLからリソースを参照しているため、リソースを先に適用します。

```xml:900-task-hr-import-users.xml のリソースへの参照箇所
    <activity>
        <work>
            <import>
                <resourceObjects>
                    <resourceRef oid="26d1d987-0359-4de2-bdc8-c1bcfeb10a4b" relation="org:default" type="c:ResourceType">
                        <!-- HR Users -->
                    </resourceRef>
                    <kind>account</kind>
                    <intent>default</intent>
                    <objectclass>ri:AccountObjectClass</objectclass>
                </resourceObjects>
            </import>
        </work>
        <distribution>
            <workerThreads>1</workerThreads>
        </distribution>
    </activity>
```

また、リソース設定では一工夫必要になります。XMLファイルを開き、 `<connectorRef>`タグの箇所を探して以下の様に修正します。`<connectorRef oid="..."`で参照しているコネクターオブジェクトは、midPoint初回起動時に自動登録されたものです。そのため、このOID（UUID形式）は新規環境構築時に毎回変わってしまいます。そこで、OIDに頼らずにコネクターオブジェクトを参照するように設定変更を加えます。`<filter>`タグを使うとOIDではなく論理名を使って対象オブジェクトを探し、参照関係を設定することができます。

```diff_xml:100-resource-hr-users.xml のコネクター参照箇所
-    <connectorRef oid="e8ae015b-0a97-48ad-8323-b530c65c7763" relation="org:default" type="c:ConnectorType">
-       <!-- ConnId com.evolveum.polygon.connector.csv.CsvConnector v2.8 -->
+    <connectorRef relation="org:default" type="c:ConnectorType">
+       <filter>
+           <q:equal>
+               <q:path>c:connectorType</q:path>
+                <q:value>com.evolveum.polygon.connector.csv.CsvConnector</q:value>
+           </q:equal>
+       </filter>
    </connectorRef>
```

これでDocker Composeで新規に環境構築時に、今回作成した設定が自動適用されます。

試しに`docker compose down -v`で環境破棄後、`docker compose up`で再構築すると、以下のようにPost-Initial Importが実行されることを確認できます。

```
midpoint_server        | 2024-12-05 08:24:49,151 [] [main] INFO (com.evolveum.midpoint.init.PostInitialDataImport): Directory /opt/midpoint/var/post-initial-objects exists. Using it.
midpoint_server        | 2024-12-05 08:24:49,161 [] [main] INFO (com.evolveum.midpoint.init.PostInitialDataImport): Starting post-initial import of file 000-system-configuration.xml.
midpoint_server        | 2024-12-05 08:24:49,587 [MODEL] [main] INFO (com.evolveum.midpoint.model.impl.importer.ObjectImporter): Imported object systemConfiguration:00000000-0000-0000-0000-000000000001(SystemConfiguration)
midpoint_server        | 2024-12-05 08:24:49,591 [] [main] INFO (com.evolveum.midpoint.init.PostInitialDataImport): Starting post-initial import of file 100-resource-hr-users.xml.
midpoint_server        | 2024-12-05 08:24:49,917 [MODEL] [main] INFO (com.evolveum.midpoint.model.impl.importer.ObjectImporter): Imported object resource:26d1d987-0359-4de2-bdc8-c1bcfeb10a4b(HR Users)
midpoint_server        | 2024-12-05 08:24:49,928 [] [main] INFO (com.evolveum.midpoint.init.PostInitialDataImport): Starting post-initial import of file 900-task-hr-import-users.xml.
midpoint_server        | 2024-12-05 08:24:50,190 [MODEL] [main] INFO (com.evolveum.midpoint.model.impl.importer.ObjectImporter): Imported object task:0e92a971-6bb1-4fce-aeb3-b1df8007e792(HR import users)
midpoint_server        | 2024-12-05 08:24:50,191 [] [main] INFO (com.evolveum.midpoint.init.PostInitialDataImport): Post-initial object import finished (3 objects imported, 0 scripts executed)
```


# まとめ

5日目では、4日目に構築した開発・検証環境上で、CSV形式の源泉データをmidPointのユーザーとしてインポートするための設定を紹介しました。2019年のAdvent Calendarの記事「[midPointにおける「IDライフサイクル管理」実践編（CSV/画面からの取り込み）](https://qiita.com/tama1/items/eb1fc55e38b3c48f88b4)」ではXML設定を直接編集していましたが、midPoint 4.8では基本的な設定がGUIベースでも可能になっていることがお分かりいただけたかと思います。

とはいえ、現時点では高度な設定を行うにはXMLを直接編集する必要がある場合も多いです。midPointのさらなる進化に期待したいところですが、個人的には、Gitでの設定ファイル管理との相性を考えると、最終的にはXMLでの管理の方がしっくりきています。

また、タスクの種類による挙動の違い、マルチバリュー項目に対するマッピング時のデフォルトの挙動についても取り上げました。これらについては、また別の記事で紹介したいと思います。

次回は、ユーザーデータではなく、組織データのインポートについて紹介する予定です。お楽しみに！