はじめに
LDAPの勉強をしたまとめです。
Azure上の仮想マシンにUbuntuを構築して、OpenLDAPをインストールしてから、
Windows10からOpenLDAPにアクセスするC#プログラムサンプルプログラムを作成するところまでです。
以下のことが書いてあります
- Azure上でのUbuntuの構築
- OpenLDAPのインストール
- C#プログラムからLDAPへのアクセス
以下のことは書いていません
- 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でやる のいずれかです。
- TeraTermでキーペアを作成する
- 仮想マシン(Ubuntu)を作成する
- Ubuntuに接続
- OpenLDAPのセットアップ
- UbuntuのLDAPポート開放
- WindowsからLDAPに接続
- OpenLDAPのDN変更
- LDAPにアクセスするC#プログラム
1. TeraTermでキーペアを作成する
※Windowsでの作業です※
操作するWindowsPCにTeraTermを入れてSSH接続用のキーペア(秘密鍵、公開鍵)を作成します。
TeraTermのインストール
以下のサイトからTeraTermをダウンロードしてインストールします。
鍵生成
UbuntuにはSSH-公開鍵認証方式で接続します。
キーペア(秘密鍵を公開鍵)を生成してUbuntu側に公開鍵を設定、TeraTerm側に秘密鍵を設定する必要があります。
今回はTeraTermでキーペアを生成します。
- TeraTermを起動してメニューから[鍵生成]を実行

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

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

次はAzure上に仮想マシンを構築します。
2. Azureに仮想マシン(Ubuntu)を作成する
※Azureでの作業です※
Azureへの登録、ログインは完了していて、リソースがまだ作成されていない状態から始めます。
リソースグループの作成
Azureの左メニュの[リソース グループ]からリソースを作成します。
TESTという名前でリソースグループを作成します。
(リージョンは東日本にしました)
仮想マシンの作成
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-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)大阪、札幌、東京 |
※私の環境では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]で接続

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

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

接続ができたら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のインストール)
gebo@Ubuntu:~$ sudo apt install slapd ldap-utils
Reading package lists... Done
Building dependency tree
OpenLDAPの管理者パスワードの入力の画面が出てくるので、パスワードを入力します。
slapd -V
(正常にインストールされたかどうか確認)
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のディレクトリデータを出力するコマンドです)
実行すると、ダラダラと出てきます。
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
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)それ以外はそのままで作成
これでポート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 日本語情報トップページからダウンロードします。
※インストールは不要です。LdapAdmin.exeをクリックで起動します。
LDAP Adminで接続
- メニューから[Connect]で[New Connecttion]を実行します。
- パラメータを入力して、[OK]で接続します。
- ConnectionNameは接続名なんで、任意の文字列でOK
- HostはUbuntuのIPアドレス
- BaseはLDAPの接続情報をGETで①ルートDNとしてメモっておいたもの
- UsernameはLDAPの接続情報をGETで②アドミンCNとしてメモっておいたもの
- Passwordは4. OpenLDAPのセットアップで登録したAdministrator password
- こんな感じでLDAPディレクトリの内容が表示されればOk
7. OpenLDAPのDN変更
※Ubuntuでの作業です※
①ルートDNとしてメモっておいたもの
dc=etnxy3denhdednurc4eny0pxja,dc=lx,dc=internal,dc=cloudapp,dc=net
なんだか長くて嫌なので
dc=gebogebo,dc=com
に変更してみます。
ルートDNの設定変更はdpkgコマンドで行います。
このコマンドはOpenLDAPの設定全般の設定変更をするコマンドです。以降の手順はルートDN以外の設定変更はしません。
以下のコマンドを実行します。
gebo@Ubuntu:~$ sudo dpkg -reconfigure slapd
そうするとこんな画面が出てきます。
Noで先に進む、Yesでキャンセルです。
この画面のDNS dmain nameでルートDNを変更します。
gebogebo.comと入力してOK
Organization name。組織名でしょうか、gebogeboと入れてOK
Administrator password。変えるつもりはないので同じものを入力。
BDB、HDB、MDBの選択。LDAPのDB形式の指定のようです、最初から選択されているMDBのままでOK。
databese removeとかナントカ...Noにします。
Move old database?よくわからないのでデフォルトで選択されているYesを選択。
以上で設定は終了です。doneとログが出て終了です。
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してみてみましょう。
(ちゃんと変わっています)
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;
を追加します。
LDAPへの接続
DirectoryEntryクラスを生成し、NativeObjectを取得することで接続を確認することができますが、DirectoryEntryクラスのコンストラクタに指定する引数がわかりずらいので注意です。
public DirectoryEntry(string path, string username, string password, AuthenticationTypes authenticationType);
path
接続するDNをURL形式で指定します。
ldap:// < LDAPホスト名 > : < LDAPポート番号 > / <検索ベース>
username
OpenLDAPに登録されているユーザー名をDN形式で指定します。
password
usernameで指定したユーザーのパスワードをそのまま指定します。
authenticationType
この引数が今一つわからないのですが、以下で接続できます。
AuthenticationTypes.None
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で実際に生成されていることを確認してみましょう。
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属性を設定しています。
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を削除します。
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を削除します。
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にもアップしています。
LDAPConnector
おつかれさまでした
LDAP以外と情報少ない。