AzureにUbuntuたててOpenLDAPいれてWin10のC#プログラムから接続してみる

#はじめに
LDAPの勉強をしたまとめです。
Azure上の仮想マシンにUbuntuを構築して、OpenLDAPをインストールしてから、
Windows10からOpenLDAPにアクセスするC#プログラムサンプルプログラムを作成するところまでです。

:o:以下のことが書いてあります:o:	

- Azure上でのUbuntuの構築
- OpenLDAPのインストール
- C#プログラムからLDAPへのアクセス

:x:以下のことは書いていません:x:	

- Azureのユーザー登録方法
- Ubuntuとは何か？
- LDAPとは何か？

**※細かいことは考えずとりあえずやってみた系です**

#環境
作業はWindows10のPC1台でやってますが、Azureに仮想マシン作るのでマシン的には2台です。

- Server OS=Ubuntu Server 18.04 LTS(Microsoft Azure)
	- OpenLDAP(Apr 10 2019 12:53:11)
- Client OS=Windows10 Pro 1809 (64bit)
	- Tera Term(Version 4.102)
	- LDAP Admin(Version 1.8.3.0)
	- SampleProject=Visual Studio 2019 C# WPF アプリケーション(.Net Framework 4.7.2)


#概要
以下の手順でやっていきます。
各項目は Windowsでやる／Azureでやる／Ubuntuでやる のいずれかです。

1. TeraTermでキーペアを作成する
2. 仮想マシン(Ubuntu)を作成する
3. Ubuntuに接続
4. OpenLDAPのセットアップ
5. UbuntuのLDAPポート開放
6. WindowsからLDAPに接続
7. OpenLDAPのDN変更
8. LDAPにアクセスするC#プログラム

#1. TeraTermでキーペアを作成する
**※Windowsでの作業です※**

操作するWindowsPCにTeraTermを入れてSSH接続用のキーペア(秘密鍵、公開鍵)を作成します。

###TeraTermのインストール
以下のサイトからTeraTermをダウンロードしてインストールします。
- [Tera Term (テラターム) プロジェクト日本語トップページ](https://ja.osdn.net/projects/ttssh2/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/6b9ad673-691e-bff9-eede-895a0b7c79c3.png)

###鍵生成
UbuntuにはSSH-公開鍵認証方式で接続します。
キーペア（秘密鍵を公開鍵）を生成してUbuntu側に公開鍵を設定、TeraTerm側に秘密鍵を設定する必要があります。
今回はTeraTermでキーペアを生成します。

- TeraTermを起動してメニューから[鍵生成]を実行
<img width="494" alt="1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/7927eca7-01f9-fa00-6af8-cf72af31c527.png">

- パラメータを設定して[生成]
	- とりあえず、この画面の通りに設定すればいいと思います。

<img width="289" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/65faa924-2434-db47-3043-e4f396ece2e4.png">

- **パスフレーズ**を入力して[公開鍵を保存]、さらに[秘密鍵を保存]
	- **パスフレーズ**は秘密鍵を暗号化するキーです。忘れないようにしましょう。
	- 公開鍵、秘密鍵はわかりやすいファイル名にして、適当なところに保存しておきましょう。後で使います。

<img width="289" alt="3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/92715f26-bdce-0a4c-02d7-42fc1f9cb66e.png">

次はAzure上に仮想マシンを構築します。


#2. Azureに仮想マシン(Ubuntu)を作成する
**※Azureでの作業です※**

Azureへの登録、ログインは完了していて、リソースがまだ作成されていない状態から始めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/ea095950-dcb6-7432-3edc-a4cd4fcbf37c.png)


###リソースグループの作成
Azureの左メニュの[リソース グループ]からリソースを作成します。

TESTという名前でリソースグループを作成します。
（リージョンは東日本にしました）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/34fe7824-cfc5-adca-1f13-e88ad713fccc.png)

###仮想マシンの作成
Azureの左メニュの[Virtual Machines]から仮想マシンを作成します。
選択項目がたくさんあります。
今回は以下の設定で作成しています。
記載のない項目はデフォルトのママ、変更していないということです。

####基本

| 項目 | 設定値 |備考|
|:-:|:---|:---|
|リソースグループ|TEST|先ほど作成したもの|
|仮想マシン名|Ubuntu|名前なんでお好みで|
|地域|東日本|お好みで|
|イメージ|Ubuntu Server 18.04 LTS||
|サイズ|Standart B1s||
|認証の種類|SSH 公開キー||
|ユーザー名|gebo|ログインするときのユーザー名です|
|SSH公開キー|※後述|さっき作成した公開鍵、パスワードの代わりみたいなもの|
|パブリック受信ポート|選択したポートを許可する||
|受信ポートを選択する|SSH(22)||

**※SSH公開キー**
SSH公開キーはテキストです、先ほどTeraTermで作成した公開鍵を指定します。
- 公開鍵をメモ帳で開きます。
- ssh-rsa、半角スペースの後に`AAAAB3N...`といった意味不明のデータが書いてありますが、最後の半角スペースの後のユーザー情報みたいなもの(下例では`gebo@WINDOWS10PC`)は不要ですので、そこを除いたデータを[SSH公開キー]の入力欄にコピペします。

```:SSH公開鍵
// これの[ssh-rsa～N2ZB+Q==]が公開鍵
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAoVx0oQzVrkmPiLPad/4Ms132itkbHZ38GFTXtFJ95qrNSO4DzkuXOViISOmNgJtzSVMM9UQ3nvCdqIPEztbt7rxnW+6SlY7ie7paDsJceLZAbLQ+jv6Uwczf2IbI4Yxcq8Zs7JipS/ZYNV8vPxn6QBDxikco2JZsgYeuWDNKsRthAO7iRetBbgogaRSX+pbDuw0SKHvAwzw1vK/P3kbAYFPRglCASmc5sYIvuqH5bGqQMUCrKiQE+HMScr87lPnSSQBvxxtUmZg0qFSHL2aK7uCmBid3zW/haQI35JZ3CU+H2kmRHrA6Rm9qhBMy9xHotspMiBvW2lRhBBbPN2ZB+Q== gebo@WINDOWS10PC
```

####ディスク

| 項目 | 設定値 |備考|
|:-:|:---|:---|
|OSディスク種類|Standard SSD||

####管理

| 項目 | 設定値 |備考|
|:-:|:---|:---|
|ブート診断|オフ||
|自動シャットダウンを有効にする|オン||
|シャットダウン時刻|19:00||
|タイムゾーン|(UTC+9:00)大阪、札幌、東京||

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/1fff6252-3191-cf8f-b29c-f554cc7e4b07.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/4bf3f160-f118-67cd-a234-8a62223989d1.png)


※私の環境では2分ほどでデプロイが完了しました、速い・・・
デプロイが完了すると仮想マシンはそのまま起動していますので、IPアドレスを確認しておきましょう。
Azureの`ホーム>Virtual Machines>[マシン名]`から`[パブリック IP アドレス]`で確認することができます。
この後、Windowsから仮想マシンに接続してUbuntuの初期設定を行います。


#3. Ubuntuに接続
**※Windowsでの作業です※**

操作しているWindowsPCからAzure上に構築したUbuntuへの接続にはTeraTermを使います。
（Windowsに標準で入っているリモートデスクトップでは接続できません)

###TeraTermで接続する

- TeraTermを起動してメニューから[新しい接続]を実行
	- ホストにUbuntuのIPアドレスを設定(さっき作成した仮想マシンのパブリックIPアドレスです)
	- TCPポートに22
	- SSHを選択
	- [OK]で接続

<img width="494" alt="4.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/c3a4a982-c176-6068-fae5-27a932acaeaf.png">

- 認証の画面
	- ユーザ名にUbuntuのユーザー([仮想マシンの作成-基本]()のとこで設定したものです)
	- パスフレーズに秘密鍵のパスフレーズ([鍵生成]()のとこで設定したものです)
	- 秘密鍵ファイルを指定([鍵生成]()のとこで保存したものです)
	- [OK]で接続

<img width="372" alt="5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/932ecc81-4c7c-0880-9db1-0cd3f60e648d.png">

- なにやら情報が出てプロンプトが表示されれば接続OK
	- 試しにpwdコマンドを打ってみましょう。自分のいる場所（パス）が表示されます。

<img width="494" alt="6.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/907bb367-f078-2891-4c05-25d9c765d0c9.png">

接続ができたらUbuntuの初期設定をしていきましょう。


#4. OpenLDAPのセットアップ
**※Ubuntuでの作業です※**

#### OpenLDAPのインストール
TeraTermでUbuntuに接続して以下のコマンドを実行します。

**sudo apt-get update**
(環境のアップデート、と思われる)

- `sudo apt-get update`はapt-getコマンドを管理者権限で実行するという意味です。

```:アップデート
gebo@Ubuntu:~$ sudo apt-get update
Hit:1 http://azure.archive.ubuntu.com/ubuntu bionic InRelease
Hit:2 http://azure.archive.ubuntu.com/ubuntu bionic-updates InRelease
Hit:3 http://azure.archive.ubuntu.com/ubuntu bionic-backports InRelease
Hit:4 http://security.ubuntu.com/ubuntu bionic-security InRelease
Reading package lists... Done
gebo@Ubuntu:~$
```

**sudo apt install slapd ldap-utils**
(OpenLDAPのインストール)

```:OpenLDAPのインストール
gebo@Ubuntu:~$ sudo apt install slapd ldap-utils
Reading package lists... Done
Building dependency tree
```

OpenLDAPの管理者パスワードの入力の画面が出てくるので、パスワードを入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/d6f51be5-54e5-d0ac-b078-0288bbae9c50.png)

**slapd -V**
(正常にインストールされたかどうか確認)

```:OpenLDAPのバージョン確認
gebo@Ubuntu:~$ slapd -V
@(#) $OpenLDAP: slapd  (Ubuntu) (Apr 10 2019 12:53:11) $
        Debian OpenLDAP Maintainers <pkg-openldap-devel@lists.alioth.debian.org>
```

### LDAPの接続情報をGET

**sudo slapcat**
(`slapcat`はLDAPのディレクトリデータを出力するコマンドです)

実行すると、ダラダラと出てきます。

```bash:slapcat
gebo@Ubuntu:~$ sudo slapcat
dn: dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=cloudapp,dc=net
objectClass: top
objectClass: dcObject
objectClass: organization
o: etnxy3denhdednurc4eny0pxja.lx.internal.cloudapp.net
dc: etnxy3denhdednurc4eny0pxja
structuralObjectClass: organization
entryUUID: 72428406-09c4-1039-9f29-6ddfd98d1f52
creatorsName: cn=admin,dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=cl
 oudapp,dc=net
createTimestamp: 20190513121448Z
entryCSN: 20190513121448.270870Z#000000#000#000000
modifiersName: cn=admin,dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=c
 loudapp,dc=net
modifyTimestamp: 20190513121448Z

dn: cn=admin,dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=cloudapp,dc=
 net
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9ZG9YTWV2UlFXT1dGREE3TFk0ZUszVUtUYUJvUUhPWnQ=
structuralObjectClass: organizationalRole
entryUUID: 7244270c-09c4-1039-9f2a-6ddfd98d1f52
creatorsName: cn=admin,dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=cl
 oudapp,dc=net
createTimestamp: 20190513121448Z
entryCSN: 20190513121448.281637Z#000000#000#000000
modifiersName: cn=admin,dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=c
 loudapp,dc=net
modifyTimestamp: 20190513121448Z

```

```bash:ちなみにslapcatのusage
usage: slapcat 
       [-v] [-d debuglevel] [-f configfile] [-F configdir] 
       [-o <name>[=<value>]] [-c] [-g] 
       [-n databasenumber | -b suffix] [-l ldiffile]
       [-a filter] [-s subtree] [-H url]
```

slapcatの結果をよく見ると、2つのレコードがあるっぽいです。

①ルートDN（と言っていいかどうかわからないが、LDAPデータの頂点になるレコード)
`dn: dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=cloudapp,dc=net`

②アドミンCN（と言っていいかどうかわからないが、OpenLDAPをインストールするときに作ったAdminのレコード)
`dn: cn=admin,dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=cloudapp,dc=net`

**この①ルートDN、②アドミンCNの値をメモっておきましょう。
外部からLDAPに接続する際に必要な情報です。**

OpenLDAPのセットアップが完了したら、外部から接続するための設定をしていきます。


#5. UbuntuのLDAPポート開放
**※Azureでの作業です※**

LDAPは389番ポートを使うのがデフォルトです。
Ubuntu側はまだポートを開けていないのでAzureでポートを開けてやります。

1)Azureにログイン
2)ホーム>Virtual Machines>Ubuntu(仮想マシン名) - ネットワーク
3)受信ポートの規則を追加する
4)[受信セキュリティ規則の追加]で宛先ポート範囲：389とする
5)名前：Port_389とする
6)それ以外はそのままで作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/ec773519-3ff8-ba3e-a342-2fde74bf0a41.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/66ff0b67-9b9c-6788-a4b7-ba6e148ee90e.png)

これでポート389が解放され、外部から接続できるようになります。


#6. WindowsからLDAPに接続
**※Windowsでの作業です※**

操作しているWindowsPCからAzure上のUbuntuで動作しているOpenLDAPに接続します。
LDAPに接続するクライアントツールはいろいろありますが、今回はLDAP Adminを使います。
LDAPに接続するために必要な情報
- UbuntuのIPアドレス
- ポート情報＝LDAPはデフォルトで389ポートで接続します。
- LDAPのDN＝[LDAPの接続情報をGET]()で①ルートDNとしてメモっておいたものです。
- LDAPユーザー名＝[LDAPの接続情報をGET]()で②アドミンCNとしてメモっておいたものです。
- パスワード＝[4. OpenLDAPのセットアップ]()で登録したAdministrator passwordです。


### LDAP Adminをダウンロードする
[LDAPAdmin 日本語情報トップページ](https://ja.osdn.net/projects/sfnet_ldapadmin/)からダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/c1100f0d-13ac-b2e3-ac2a-94f6497bb3b9.png)

※インストールは不要です。LdapAdmin.exeをクリックで起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/6c508e31-c592-1a5f-dfba-890f4f12e047.png)

### LDAP Adminで接続

- メニューから[Connect]で[New Connecttion]を実行します。
- パラメータを入力して、[OK]で接続します。
	- ConnectionNameは接続名なんで、任意の文字列でOK
	- HostはUbuntuのIPアドレス
	- Baseは[LDAPの接続情報をGET]()で①ルートDNとしてメモっておいたもの
	- Usernameは[LDAPの接続情報をGET]()で②アドミンCNとしてメモっておいたもの
	- Passwordは[4. OpenLDAPのセットアップ]()で登録したAdministrator password

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/d7aa97cf-28f4-579d-12b4-de11ea1462b0.png)

- こんな感じでLDAPディレクトリの内容が表示されればOk

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/36e6c091-b9fe-6c03-dd17-004ea84ee8ae.png)


#7. OpenLDAPのDN変更
**※Ubuntuでの作業です※**

①ルートDNとしてメモっておいたもの
`dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=cloudapp,dc=net`
なんだか長くて嫌なので
`dc=gebogebo,dc=com`
に変更してみます。

ルートDNの設定変更は**dpkg**コマンドで行います。
このコマンドはOpenLDAPの設定全般の設定変更をするコマンドです。以降の手順はルートDN以外の設定変更はしません。

以下のコマンドを実行します。

```bash:dpkg
gebo@Ubuntu:~$ sudo dpkg -reconfigure slapd
```

そうするとこんな画面が出てきます。
Noで先に進む、Yesでキャンセルです。
<img width="478" alt="11.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/e4362006-eebc-7896-2066-5344c55ca947.png">

この画面のDNS dmain nameでルートDNを変更します。
gebogebo.comと入力してOK
<img width="480" alt="12.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/48137f07-0204-bbfd-d0fa-87153275e836.png">

Organization name。組織名でしょうか、gebogeboと入れてOK
<img width="479" alt="13.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/c76370b6-d407-f415-8932-98f91dee7b0e.png">

Administrator password。変えるつもりはないので同じものを入力。
<img width="479" alt="14.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/21c26ddb-1993-aede-6fb7-b19a7b6347ec.png">

パスワードの再入力。
<img width="483" alt="15.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/3ea1e662-ac46-d2ea-7924-72f0b13e5020.png">

BDB、HDB、MDBの選択。LDAPのDB形式の指定のようです、最初から選択されているMDBのままでOK。
<img width="476" alt="16.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/964e3c41-2980-8b3e-8c6d-22914aa391ae.png">

databese removeとかナントカ...Noにします。
<img width="480" alt="17.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/edbc4bd9-8685-0cb2-01ff-86b7342664a8.png">

Move old database?よくわからないのでデフォルトで選択されているYesを選択。
<img width="477" alt="18.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/d1b4f5d5-dd42-0a9e-ba30-28913c533685.png">

以上で設定は終了です。doneとログが出て終了です。

```bash:dpkg実行後
gebo@Ubuntu:~$ sudo dpkg -reconfigure slapd
  Backing up /etc/ldap/slapd.d in /var/backups/slapd-2.4.45+dfsg-1ubuntu1.2... done.
  Moving old database directory to /var/backups:
  - directory unknown... done.
  Creating initial configuration... done.
  Creating LDAP directory... done.
```

slapcatしてみてみましょう。
（ちゃんと変わっています）

```bash:slapcat
gebo@Ubuntu:~$ sudo slapcat
dn: dc=gebogebo,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: gebogebo
dc: gebogebo
structuralObjectClass: organization
entryUUID: 97fdb884-0adf-1039-8a27-3dd7d18b91fb
creatorsName: cn=admin,dc=gebogebo,dc=com
createTimestamp: 20190514220139Z
entryCSN: 20190514220139.147880Z#000000#000#000000
modifiersName: cn=admin,dc=gebogebo,dc=com
modifyTimestamp: 20190514220139Z

dn: cn=admin,dc=gebogebo,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9RlRtUTMvaXg4NU1Kc2VSWGRqM1FFYWlaOTVETzZlbGU=
structuralObjectClass: organizationalRole
entryUUID: 98005cc4-0adf-1039-8a28-3dd7d18b91fb
creatorsName: cn=admin,dc=gebogebo,dc=com
createTimestamp: 20190514220139Z
entryCSN: 20190514220139.165269Z#000000#000#000000
modifiersName: cn=admin,dc=gebogebo,dc=com
modifyTimestamp: 20190514220139Z
```

LDAP Adminで接続するときのBaseとUsernameも変えて接続確認をしておきましょう。


#8. LDAPにアクセスするC#プログラム
**※Windowsでの作業です※**

C#でLDAPにアクセスするプログラムを作成します。

- Visual Studio 2019 C# WPF アプリケーション(.Net Framework 4.7.2)でプロジェクトを作成します。
- 参照に`System.DirectoryServices`を追加します。
- ソースコードには`using System.DirectoryServices;`を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252291/10c8f58b-25aa-94d9-65ff-d92ee38cba85.png)

###LDAPへの接続
DirectoryEntryクラスを生成し、NativeObjectを取得することで接続を確認することができますが、DirectoryEntryクラスのコンストラクタに指定する引数がわかりずらいので注意です。

```CS:DirectoryEntryコンストラクタ
public DirectoryEntry(string path, string username, string password, AuthenticationTypes authenticationType);
```
####path
接続するDNを**URL形式で**指定します。

```:LDAP_URL形式
ldap:// < LDAPホスト名 > : < LDAPポート番号 > / <検索ベース>
```

####username
OpenLDAPに登録されているユーザー名を**DN形式で**指定します。

####password
usernameで指定したユーザーの**パスワードをそのまま指定**します。

####authenticationType
この引数が今一つわからないのですが、以下で接続できます。
AuthenticationTypes.None

```cs:接続確認
string message = "";
try {
    string lserver = $"LDAP://{LDAPサーバーのIPアドレス}/dc=gebogebo,dc=com";
    string domainAndUsername = $"cn=admin,dc=gebogebo,dc=com";
    string pwd = $"password";

    DirectoryEntry entry = new DirectoryEntry(lserver, domainAndUsername, pwd, AuthenticationTypes.None);
    // Exceptionが発生しなければ接続成功
    object obj = entry.NativeObject;

    message = "接続成功しました";

} catch (Exception ex) {
    // Error
    message = ex.Message;
}
MessageBox.Show(message);
```

###OUの作成
接続確認と同様の方法でDirectoryEntryを生成した後に、Children.Add()します。
Add()の結果で得られたオブジェクトでCommitChanges()しないといけないところが注意です。
以下サンプルではtestouというOUを作成しています。
実行後にLDAPAdminで実際に生成されていることを確認してみましょう。

```cs:OUの作成
string message = "";
try {
    string lserver = $"LDAP://{LDAPサーバーのIPアドレス}/dc=gebogebo,dc=com";
    string domainAndUsername = $"cn=admin,dc=gebogebo,dc=com";
    string pwd = $"password";

    DirectoryEntry entry = new DirectoryEntry(lserver, domainAndUsername, pwd, AuthenticationTypes.None);

    var ou = entry.Children.Add("ou=testou", "OrganizationalUnit");
    ou.CommitChanges();

    message = "OUの作成に成功しました";

} catch (Exception ex) {
    message = ex.Message;
}
MessageBox.Show(message);
```

###CNの作成
DirectoryEntryを生成した後に、Children.Add()するのですが、DirectoryEntryのコンストラクタに指定するpahは先ほどのサンプルで指定したtestouを指定します。
こうすることで、testouの下にCNを作成することになります。
Add()の結果で得られたオブジェクトでCommitChanges()しないといけないところが注意です。

このサンプルでは`testcn`というinetOrgPerson型のCNを作成し、uid,sn,displayName,homePhone,homePostalAddress属性を設定しています。

```cs:CNの作成
string message = "";
try {
    string lserver = $"LDAP://{LDAPサーバーのIPアドレス}/ou=testou,dc=gebogebo,dc=com";
    string domainAndUsername = $"cn=admin,dc=gebogebo,dc=com";
    string pwd = $"password";

    DirectoryEntry ou = new DirectoryEntry(lserver, domainAndUsername, pwd, AuthenticationTypes.None);

    string uid = "testcn";

    var user = ou.Children.Add("cn=testcn", "inetOrgPerson");
    user.Properties["uid"].Value = uid;
    user.Properties["sn"].Value = uid;
    user.Properties["displayName"].Value = "なまえ";
    user.Properties["homePhone"].Value = "????";
    user.Properties["homePostalAddress"].Value = "xxxxx";

    user.CommitChanges();

    message = "CNの作成に成功しました";

} catch (Exception ex) {
    message = ex.Message;
}
MessageBox.Show(message);
```

###OUの削除
Find()で削除対象のオブジェクトを取得してから、Remove()で削除します。
Remove()の場合はCommitChanges()がいらないようです（*いちいちわかりにくいんだよなぁ*)

以下サンプルはtestouを削除します。

```cs:OUの削除
string message = "";
try {
    string lserver = $"LDAP://{LDAPサーバーのIPアドレス}/ou=testou,dc=gebogebo,dc=com";
    string domainAndUsername = $"cn=admin,dc=gebogebo,dc=com";
    string pwd = $"password";

    DirectoryEntry ou = new DirectoryEntry(lserver, domainAndUsername, pwd, AuthenticationTypes.None);

    var cn = ou.Children.Find("ou=testou");

    ou.Children.Remove(cn);

    message = "OUの削除に成功しました";

} catch (Exception ex) {
    message = ex.Message;
}
MessageBox.Show(message)
```

###CNの削除
Find()で削除対象のオブジェクトを取得してから、Remove()で削除します。

以下サンプルはtestcnを削除します。

```cs:CNの削除
string message = "";
try {
    string lserver = $"LDAP://{LDAPサーバーのIPアドレス}/ou=testou,dc=gebogebo,dc=com";
    string domainAndUsername = $"cn=admin,dc=gebogebo,dc=com";
    string pwd = $"password";

    DirectoryEntry ou = new DirectoryEntry(lserver, domainAndUsername, pwd, AuthenticationTypes.None);

    var cn = ou.Children.Find("cn=testcn");

    ou.Children.Remove(cn);

    message = "CNの削除に成功しました";

} catch (Exception ex) {
    message = ex.Message;
}
MessageBox.Show(message);
```

これらのソースは[GitHub](https://github.com/gebogebogebo/LDAPConnector)にもアップしています。
[LDAPConnector](https://github.com/gebogebogebo/LDAPConnector)


#おつかれさまでした
LDAP以外と情報少ない。