LDAP Managerを使ってみた！ 9. LDAP→ODBC、ODBC→LDAP反映編

[前回](https://qiita.com/ahra_/items/930dfda8c26aaee2531d)の続きです。
## LDAP→ODBC反映とは
LDAPフィルタの条件に合致したユーザをODBCデータソースを介してDBに反映するプラグインです。
## 事前準備
### MySQLの準備
[LDAP Managerのサポートリスト](https://exgenkb.atlassian.net/wiki/spaces/exgeninfo/pages/1152188425/LDAP%2BManager%2B7.0)より、MySQL 8.4を反映先DBとしました。
RHEL 9.4のリポにはMySQL 8.4がないので、リポを追加します。
```
$ dnf install https://dev.mysql.com/get/mysql84-community-release-el9-1.noarch.rpm
```
追加後、インストールを実施します。
```
$ dnf install mysql-server
```
MySQLサービスを開始します。
```
$ systemctl start mysqld
```
MySQLの`root`ユーザの初期パスワードを確認します。
```
$ cat /var/log/mysqld.log
2024-12-18T08:29:50.980903Z 0 [System] [MY-015017] [Server] MySQL Server Initialization - start.
2024-12-18T08:29:50.982771Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.4.3) initializing of server in progress as process 29048
2024-12-18T08:29:51.035404Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-12-18T08:29:55.098009Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-12-18T08:29:59.226056Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: yTBFuj=3737*
2024-12-18T08:30:03.192714Z 0 [System] [MY-015018] [Server] MySQL Server Initialization - end.
2024-12-18T08:30:03.265782Z 0 [System] [MY-015015] [Server] MySQL Server - start.
2024-12-18T08:30:03.526420Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.4.3) starting as process 29086
2024-12-18T08:30:03.566004Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-12-18T08:30:05.431772Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-12-18T08:30:06.184268Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2024-12-18T08:30:06.184352Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2024-12-18T08:30:06.302704Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
2024-12-18T08:30:06.303189Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.4.3'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MySQL Community Server - GPL.
```
`yTBFuj=3737*`が初期パスワードのようです。
MySQLの初期設定を行います。
以下のコマンドを実行します。
```
$ mysql_secure_installation
```
<details><summary> mysql_secure_installation </summary>

最初に`root`ユーザのパスワードを聞かれるので、先ほど確認した初期パスワードを入力します。
```
Securing the MySQL server deployment.
Enter password for user root:
```
次に、再設定する`root`ユーザのパスワードを入力します。
```
The existing password for the user account root has expired. Please set a new password.

New password:

Re-enter new password:
```
先ほどパスワード検証コンポーネントの検証に耐えるパスワードを`root`ユーザに設定したのでここは`N`とします。
```
The 'validate_password' component is installed on the server.
The subsequent steps will run with the existing configuration
of the component.
Using existing password for root.

Estimated strength of the password: 100
Change the password for root ? ((Press y|Y for Yes, any other key for No) : N

 ... skipping.
```
匿名ユーザを削除します。
```
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.
```
リモートからの`root`ユーザでの接続は不許可とします。
```
Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.
```
`test`データベースは削除します。
```
By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.
```
資格情報テーブルをリロードします。
```
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done!
``` 
</details>

MySQLがリッスンするアドレスとポートを`/etc/my.cnf`に指定してMySQLを再起動します。
```diff 
+ port=3306
+ bind-address = 0.0.0.0
``` 
```
$ systemctl restart mysqld
```
ユーザ、データベース、テーブルを作成します。
```
$ mysql -p 
Enter password:

mysql> create user 'odbcuser'@'%' IDENTIFIED BY 'P@sw0rd+';
Query OK, 0 rows affected (0.02 sec)

mysql> create database lmodbc;
Query OK, 1 row affected (0.00 sec)

mysql> grant all on lmodbc.* to odbcuser;
Query OK, 0 rows affected (0.00 sec)

mysql> create table lmodbc.ldapuser (
    -> employeenumber varchar(10) PRIMARY KEY,
    -> passwordexpirationtime time,
    -> passwordexpirationdate date,
    -> commonname varchar(15),
    -> surname varchar(15),
    -> givenname varchar(15),
    -> userid varchar(44),
    -> ldapm varchar(2)
    -> );
Query OK, 0 rows affected (0.04 sec)
```
### ODBCデータソースの準備
[提供サイト](https://dev.mysql.com/downloads/connector/odbc/)からインストーラーをダウンロードし、LDAP Managerがインストールされているサーバにインストールします。
インストール後、ODBC データ ソース アドミニストレーター（64ビット）より、ODBCドライバのセットアップを行います。
Unicode版のODBCドライバを使用します。
MySQL上に設定したユーザとデータベースを設定し、接続を確認して保存します。
![pic (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/5a107c72-53f9-532b-e98a-30e9f69643a2.png)
## プラグインの設定
LDAP Manager コンソールから「環境設定」 > 「LDAP -> ODBC反映1」を選択します。
まず、抽出元LDAPサーバとデータソース情報を設定します。
![pic (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/f8cf1877-1ed5-ac6f-823b-063c82d9ee12.png)
次に、テーブル情報の「追加」を押下し、反映先テーブルに関する設定を行います。
LDAPサーバからの抽出フィルタと、対象テーブル名を指定します。
![pic (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/e77f957c-a286-bbfa-a000-7ab4388b8a22.png)
その後、ODBC属性名の「属性インポート」を押下し、テーブルの列情報を読み込みます。
取得した列情報からレコード識別属性を指定します。（必要な場合）
![pic (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/da5ffef8-fbd2-cd42-4361-2c2c2efb9060.png)
マッピングは以下のように行いました。
![pic (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/eb43eaef-5801-e7d8-2c86-08fab03fdc52.png)
## 確認
プラグインを手動実行します。
![pic (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/03459ea9-97ae-1c03-8a1e-139e9dd88322.png)
レコードがDBに挿入されます。
![pic (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/0c763ad5-b361-1de1-bfde-243ca0974938.png)
```
mysql> select * from lmodbc.ldapuser;
+----------------+------------------------+------------------------+------------+----------+-----------+----------------------------------------------+-------+
| employeenumber | passwordexpirationtime | passwordexpirationdate | commonname | surname  | givenname | userid                                       | ldapm |
+----------------+------------------------+------------------------+------------+----------+-----------+----------------------------------------------+-------+
| 1              | 09:58:33               | 3024-04-21             | user1      | Tanaka   | Jiro      | Q5LRABncLhvWgoOQteHF9ib6iyDRQFUBWwUklrCoK3o= | LM    |
| 2              | 09:58:49               | 3024-04-21             | user2      | Nakamura | Tomoki    | YvVzDsmeC70Ai+eHp6e3tLfEXdX5+1qVlk4xBqqKudc= | LM    |
| 3              | 09:59:02               | 3024-04-21             | user3      | Koga     | Yujiro    | QJvfnol2ktrLqwTMWeQJ2P5LU8o9JB6YssMOrdierU8= | LM    |
+----------------+------------------------+------------------------+------------+----------+-----------+----------------------------------------------+-------+
3 rows in set (0.00 sec)
```
ユーザ情報を変更、削除して実行します。
![pic (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/60c64d84-dccf-f20b-102a-b61f206c6543.png)
![pic (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/82006f63-df99-7d92-7291-bd7736be846a.png)

この通り、変更情報や削除が反映されています。
```
mysql> select * from lmodbc.ldapuser;
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
| employeenumber | passwordexpirationtime | passwordexpirationdate | commonname | surname | givenname | userid                                       | ldapm |
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
| 1              | 09:58:33               | 3024-04-21             | user1      | Tanaka  | Jiro      | Q5LRABncLhvWgoOQteHF9ib6iyDRQFUBWwUklrCoK3o= | LM    |
| 2              | 10:16:45               | 3024-04-21             | user2      | Yasuda  | Tomoki    | YvVzDsmeC70Ai+eHp6e3tLfEXdX5+1qVlk4xBqqKudc= | LM    |
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
2 rows in set (0.00 sec)
```
レコード識別属性について確認します。
以下のように、レコード識別属性`ldapm`に指定の属性値`LM`が含まれないようにします。
```
mysql> update lmodbc.ldapuser SET ldapm = 'NO' where employeenumber = '2';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from lmodbc.ldapuser;
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
| employeenumber | passwordexpirationtime | passwordexpirationdate | commonname | surname | givenname | userid                                       | ldapm |
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
| 1              | 18:58:33               | 3024-04-21             | user1      | Tanaka  | Jiro      | F8vW6uFbjqtWuLgrGD1uASrfJPPl9zVOP/W5UhiqfJQ= | LM    |
| 2              | 19:16:45               | 3024-04-21             | user2      | Yasuda  | Tomoki    | HfBnEJiOitSW9g9ik5YdN5nMWeCPnGuR+MJrOhxev6o= | NO    |
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
2 rows in set (0.00 sec)
```
ユーザ情報を変更します。
![pic (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/edfc37db-0f20-1908-32ac-5452e126e6a3.png)
ここでLDAP→ODBC反映を実行すると、更新処理がスキップされます。
![pic (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/0060501f-2791-d272-d3f8-d5f0878f39b4.png)
```
mysql> select * from lmodbc.ldapuser;
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
| employeenumber | passwordexpirationtime | passwordexpirationdate | commonname | surname | givenname | userid                                       | ldapm |
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
| 1              | 18:58:33               | 3024-04-21             | user1      | Tanaka  | Jiro      | F8vW6uFbjqtWuLgrGD1uASrfJPPl9zVOP/W5UhiqfJQ= | LM    |
| 2              | 19:16:45               | 3024-04-21             | user2      | Yasuda  | Tomoki    | HfBnEJiOitSW9g9ik5YdN5nMWeCPnGuR+MJrOhxev6o= | NO    |
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
2 rows in set (0.00 sec)
```
最後に、抽出フィルタを変更します。
![pic (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/78c3ce24-1bae-52f4-5afb-bacb0871c81f.png)
このようにフィルタに合致しなくなったユーザが削除されます。
```
mysql> select * from lmodbc.ldapuser;
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
| employeenumber | passwordexpirationtime | passwordexpirationdate | commonname | surname | givenname | userid                                       | ldapm |
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
| 1              | 09:58:33               | 3024-04-21             | user1      | Tanaka  | Jiro      | Q5LRABncLhvWgoOQteHF9ib6iyDRQFUBWwUklrCoK3o= | LM    |
+----------------+------------------------+------------------------+------------+---------+-----------+----------------------------------------------+-------+
1 row in set (0.01 sec)
```
## ODBC → LDAP反映とは
データベースからODBCを介してユーザ情報をLDAPサーバに連携するプラグインです。
## 事前準備
### SQL Server Expressの準備
抽出元DBにはSQL Server 2022 Expressを使用します。
[提供サイト](https://www.microsoft.com/ja-jp/download/details.aspx?id=104781)からインストーラーをダウンロードして実行します。
[SSMS](https://learn.microsoft.com/ja-jp/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16)もインストールしています。
SQL Server構成マネージャー > SQL Server ネットワークの構成 > SQLEXPRESSのプロトコル > TCP/IPを「有効」とします。
![pic (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/18c7ef61-3143-183d-9a60-22cd0389ff52.png)
`IPAll`のTCPポートを指定します。
![pic (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/af7274b3-e892-d5c8-1866-e48d85eb0f7d.png)
#### データベースの準備
SSMSを起動してSQL Serverに接続します。
![pic (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/add77585-0701-55d5-4c1c-a86eb61e0fe4.png)
SQL Server認証モードを有効にします。
![pic (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/2a9804c4-bf1a-d2fa-cbee-643a5baad7c1.png)
新しいデータベースを作成します。
![pic (18).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/666e683f-e99c-9b43-5c65-5eb34c2d0dc5.png)
UTF-8に対応させるため照合順序を変更します。
![pic (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/fb0c7b71-958d-bf85-b90d-5482328f2b50.png)
ログインを作成します。
「既定のデータベース」を`odbclm`にします。
![pic (20).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/fd23491c-2d04-15d9-61d8-b14c32bc3bf6.png)
次に、データベースユーザを作成します。
データベースユーザとログインをマッピングし、既定のスキーマを設定します。
![pic (21).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/d6a278ef-62c2-b51e-8a11-a53adf24b395.png)
今回は既定の`dbo`を使用するので他にスキーマは設定しません。
![pic (22).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/13a23f03-67b6-a402-1604-a98b05e3b73f.png)
[メンバーシップ（ロール）](https://learn.microsoft.com/ja-jp/sql/relational-databases/security/authentication-access/database-level-roles?view=sql-server-ver16)は`db_owner`を割り当ててしまいます。
![pic (23).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/da1d4511-3426-cb4b-a773-37a33b2807d0.png)
セキュリティ保護は特にしないので設定しません。
![pic (24).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/d11c4292-6110-739e-3c34-15482c14b746.png)
これで、ログイン`odbclm`でSQL Serverに接続できます。
最後にテーブルを作成します。プラグインの設定で`RDN属性`とする属性とマッピングされる列を必ず作成する必要があります。
```
create table employees (
employeenumber varchar(10) PRIMARY KEY,
surname varchar(50),
givenname varchar(50)
);
```
### ODBCデータソースの準備
[提供サイト](https://learn.microsoft.com/ja-jp/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver16)からインストーラーをダウンロード、インストールします。
ODBC データ ソース アドミニストレーター（64 ビット）より、SQL Server用のデータソースを追加します。
![pic (25).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/afb54a31-3966-ee99-4e47-6461bd53e8e1.png)
![pic (26).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/c60c496f-dc6d-3a89-f069-e3b75db1980c.png)
![pic (27).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/209039e7-936a-2874-ae1b-899af179ea7d.png)
![pic (28).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/4d291aa7-feb6-d922-665e-ce1b430aad02.png)
![pic (29).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/eb99eead-363a-6586-1a83-d800b72a8f5a.png)
![pic (30).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/09c577d9-5b0b-bb62-ff74-4347441d6215.png)
## プラグインの設定
プラグインをインストールします。
![pic (31).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/69199dc2-0be2-9514-21d9-ee14372c58c1.png)
LDAP Managerコンソール「環境設定」 > 「ODBC -> LDAP反映1」を開きます。
まず「基本設定」を行います。
ODBC、LDAPの情報を設定します。抽出条件用SQLには`select * from employees`を指定しました。
![pic (32).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/d829805f-b13d-3c68-704a-e48fb3a9a520.png)
次に、「ODBC属性名設定」から「属性インポート」します。
![pic (33).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/8daaedfb-4896-cdab-a3de-7a42567513a3.png)
「マッピング設定」は以下のようにしました。先述の通り、RDN属性（ここでは`cn`）にマッピングするODBC属性（列）が存在する必要があります。
![pic (34).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/da319267-3da2-b86c-2b7a-56bf3376c886.png)
## 確認
現在、データベースにはレコードがなく、LDAPサーバには2つのユーザエントリが存在する状態です。
![pic (35).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/669ee2b2-6517-1bc6-34a9-f266aee912aa.png)
![pic (36).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/e0512289-58ec-0248-45a5-94b7ef4d8b92.png)
この状態で実行すると、LDAPサーバ側のユーザエントリは削除（無効化）されます。
![pic (37).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/8f48fff7-d85f-9e98-144a-32929bfc69c2.png)
データベースにデータを挿入してからプラグインを実行します。
![pic (38).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/672aef1d-50ed-2f05-2f39-0a0553eeba28.png)
データがLDAPに反映されます。
![pic (39).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/9bb584b2-46ec-8775-354d-2aa42c5b3554.png)
![pic (40).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/84725387-b378-dafc-686d-783ec1b23dff.png)
DB側のデータを更新して再度プラグインを実行します。
``` 
update employees 
SET surname = 'Watanabe'
where employeenumber = '4'
;
```
LDAP側の更新が確認できます。
![pic (41).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/5662b2c9-cd14-8ba7-8c4e-118594c77b3b.png)
抽出条件を変更します。
![pic (42).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/6d2aefec-fde2-3c2f-43df-0b47242e19b4.png)
`'4'`という`employeenumber`を持つユーザが抽出されなくなり、以下の通り無効化処理が実施されます。
![pic (43).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/4bbc7a16-0760-d89b-6859-28e2572ef468.png)
## まとめ
LDAPから/LDAPへDBの情報を連携する2つのプラグインについての検証でした。
[次の記事](https://qiita.com/ahra_/items/aa4ae37e7476ff299296)では、LDAP Managerのワークフローシステムである **IDワークフロー** について検証します。