プロジェクトでローカルに使うユーザーを作って管理したく、LDAPサーバーを立ち上げてみました。
今回LDAPを触るのが初めてだったので、LDAPのざっくりとした解説と使い方、および、Ubuntu18にLDAPをインストールする手順をメモしました。
LDAPはOpenLDAPを使用し、LDAPのインストール・設定は、phpLDAPadminが動くようにし、ドメイン名を独自のものに変更するまで行いました。
まずはじめに、LDAPについての簡単な説明です。
LDAPとは?
LDAPとは、ユーザー・PC・メールアドレス・住所等のデータ向けのデータベースです。
そういったデータは、主に参照用途に使われることが多く、データは「企業名->部門名->部署名」や「国->都道府県->市区町村」など、大分類から中分類、小分類へと、任意の深さで分類・細分化されて登録されるため、通常のデータベースと違い、下記のような特徴を持っています。
- 高速にデータを検索して取得するのに特化している(逆に、頻繁にデータを登録・更新するのには向いていない)
- データはテーブル形式ではなく、ツリー形式で登録される。
用語説明
エントリー
データは、PCのディレクトリ・ファイルのツリーの様なものをイメージしてもらうと分かりやすいかと思います。
各データをエントリーとよび、エントリーに複数の属性がデータとして登録されています。
ディレクトリ・ファイルの様な区別はなく、エントリーの中に子エントリーを持つことができます。つまり、ディレクトリの様な分類項目もエントリーの1つです。
例
下記のユーザー「cn=user-01」の場合
- ルートの「dc=test,dc=internal」の中に分類エントリー「ou=users」があり、その中にユーザーエントリー「cn=user-01」があります。
- ユーザーエントリー「cn=user-01」は、「createtimestamp」「creatorsName」…の属性を持ちます。
また、前述の通り、エントリーは子エントリーが持てるので、任意の位置にエントリーを追加し、分類していくことが可能です。
分類用のエントリーだけでなく、上記のようなユーザーエントリーの中にも、子エントリーを持たせることができます。
そうして、エントリーを入れ子にすることにより、エントリーツリーのデータベースを作っていきます。
dn
エントリーの絶対パスをdn(Distinguish Name)と呼びます。
dnはインターネットのURLと同様、一番上の親から始まり、右から順にカンマ区切りで書いていきます。
前述の「cn=user-01」の場合dnは「cn=user-01,ou=users,dc=test,dc=internal」となります。
ObjectClass(schema)
前述の通り、エントリーには属性としてデータを登録できるのですが、使える属性の名前とフォーマットは事前に登録しておきます。
また、属性のセットをObjectClassとして登録することができます。「schema」という用語も出てきますが「ObjectClass」と同じものです。
ObjectClassは、エントリーを追加する際に設定することができ、エントリーがどういうオブジェクトかを表し、エントリー追加時に属性の設定漏れを防ぎます。 また、エントリーは複数のObjectClassを設定することができます。
属性とObjectClassはユーザーが独自に定義・登録できるのですが、LDAPサーバーの設定で、一般的なテンプレートが読み込まれるように設定されているので、多くの場合、テンプレートを利用することになります。
rdn
dnの一番左はエントリーの自分の名前になり、それをrdn(Relative Distinguished Name)と呼びます。
rdnはエントリーが持つ属性で決まり、どの属性をrdnとするかは、ObjectClassで定義されています。
例えば前述のユーザー「cn=user-01,ou=users,dc=test,dc=internal」は、rdnに属性「cn=user-01」を使っています。
よく使う属性
ドメイン分類名には「dc(Domain Component)」、組織分類名には「o(Organization)」、部署分類名には「ou(Organization Unit)」、ユーザー分類名には「cn(Common Name)」がよく使われます。
しかし、それらはデフォルトで読み込まれたObjectClassテンプレートで定義されているだけで、LDAPの仕様上で特別な意味を持つものではありません。
LDAP設定
config
LDAPの設定も、LDAPのデータベースとしてLDAPに登録されています。そして、その登録値を変更すると、リアルタイムにLDAPの設定が反映されます。
LDAPの設定データは、dnが「cn=config」のデータベースに登録されています。
つまり、LDAPは、LDAPの設定を登録するデータベース「config」と、実際のデータを登録していくデータベースから構成されています。
今回はデータを登録するデータベースは1つしか作りませんでしたが、1つのLDAPで複数のデータベースを作ることが可能です。
slapd.conf
LDAPの設定ファイルは「/usr/share/slapd/slapd.conf」ですが、Ubuntu18のパッケージでインストールした場合、「slapd.conf」は使われず、「config」データベースが直接構築されます。
なので、LDAPインストール後は、configのエントリーを直接編集して設定を行います。
「slapd.conf」から「config」データベースのエントリーを登録する初期設定コマンドもありますが、今回は使っていません。
「slapd.conf」は設定ファイルというより、「config」を設定するためのテンプレートと言った方が正しいです。
Ubuntu18にLDAPをインストールする手順
OpenLDAPインストール
OpenLDAPのサービスは「slapd」で、slapdとLDAPユーティリティーをインストールします。
sudo apt-get install slapd sudo apt-get install ldap-utils
インストールが終わるとサービスが起動されます。
サービス確認
systemctl status slapd
サービス自動起動
sudo systemctl enable slapd
phpLDAPadminインストール
UbuntuのパッケージにphpLDAPadminがあるので、それをインストールできれば一番楽だったのですが、php7.2以降だとエラーが出るため、下記の記事を参考に、phpLDAPadminのフォークを使いました。
php関連インストール
phpLDAPadminを動かすには、php拡張パッケージ「php-ldap」「php-xml」をインストールする必要があります。
sudo apt-get install php-ldap sudo apt-get install php-xml
Webサーバーインストール
Webサーバーをインストールして、phpが動くようにします。
やり方はここでは割愛します。ちなみにUbuntuのパッケージでphpLDAPadminをインストールすると、WebサーバーとしてApache2がインストールされます。
phpLDAPadminインストール
GitHubから、phpLDAPadminのphp7.2以降対応版forkのzipを持ってきて、Webのディレクトリに展開します。
phpLDAPadmin設定
phpLDAPadminの中の「config/config.php.example」を「config/config.php」にコピーして設定ファイル作成します。
設定ファイルの中身は変更無しでOKです。
phpLDAPadminアクセス
下記URLを開きます。
「http://localhost/phpLDAPadmin-master/index.php」
するとphpLDAPadminのフロントページが立ち上がります。
phpLDAPadminログイン
UbuntuのパッケージでLDAPをインストールすると、管理者ユーザー(rootDN)が適当に作成されます。
phpLDAPadminにログインするには、その管理者ユーザーのdnが必要なのですが、インストール時に適当に作成されているのでdnが分かりません。
そこで、検索コマンドを使って、configの内容を表示し、そこから管理者ユーザーのdnを確認します。
sudo ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b cn=config ... olcRootDN: cn=admin,dc=xxxx,dc=xxxx,dc=xxxx ...
上記の「olcRootDN」をphpLDAPadminのログイン画面に入力してログインします。パスワードはLDAPをインストールした時に設定したものです。
以上で、LDAPとphpLDAPadminがインストールされ、phpLDAMadminでLDAPのエントリーの編集ができるようになります。
後はphpLDAPadminを使って作業をしていくことになるのですが、 今回はドメイン名(suffix)を変更したかったため、configを編集する必要がありました。
configの編集はphpLDAPadminでは行えず、LDAPコマンドを使う必要があったため、LDAPコマンドの簡単な説明と、suffixの変更手順を記載します。
LDAPコマンド
エントリー検索
sudo ldapsearch -LLL -Y EXTERANL -H ldapi:/// -b <bn> [検索条件]
- LLL
- 結果の表示形式を指定します。「LLL」は一番シンプルな出力になります。
- Y EXTERNAL
- 通常、コマンドを使うユーザーはLDAPに登録されたユーザーを指定するのですが、「-Y EXTERANAL」とすると、コマンドを実行しているLinuxのユーザーになります。
- 上記の場合「sudo」で実行しているので、Linxuユーザーは「root」になります。
- rootユーザーなら必ずアクセスできるわけではなく、どのLinxuユーザーにどのアクセス権限を与えるかは「config」の「olcAccess」で設定します。
- 例えば「olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external」などのアクセス権限の設定があるのですが、gid・uidが0、つまりrootユーザーのアクセス権限を設定しています。
- H
- LDAPのホストを指定します。「-H ldapi:///」とすると、同じサーバー上でソケットで直接アクセスになります。
- b
- 検索対象のルートdnを指定します。
- 例えば、設定configの値を見る場合は「-b cn=config」となります。
- 例えば、先程ログインしたphpLDAPadminのツリーのルートdnにする場合は「-b dc=xxxx,dc=xxxx,dc=xxxx」となり、ルートdn配下の全エントリーが表示されます。
- 検索条件
- 省略可能です。
- 「'(cn=user-0*)'」など、属性の値を絞って検索できます。
エントリー追加
sudo ldapadd -Y EXTERANL -H ldapi:/// -f <ldif_file>
追加するエントリーをldifファイルに記載します。
ldif
dn: <dn> <属性名>: <属性値> <属性名>: <属性値> …
エントリー削除
sudo ldapdelete -Y EXTERANL -H ldapi:/// <dn> sudo ldapdelete -Y EXTERANL -H ldapi:/// -f <ldif_file>
dnを直接指定するか、削除するdnをldifファイルに記載します。
ldif
dn: <dn>
エントリー属性編集
sudo ldapmodify -Y EXTERANL -H ldapi:/// -f <ldif_file>
編集する属性をldifファイルに記載します。
複数の属性を編集するには、属性間を「-」で区切ります。
ldif
# 属性追加 dn: <dn> changetype: modify add: <属性名> <属性名>: <属性値> - # 属性削除 dn: <dn> changetype: modify delete: <属性名> - # 属性値変更 dn: <dn> changetype: modify replace: <属性名> <属性名>: <属性値>
suffix変更
データベースのツリーのルートdnをsuffixと呼ぶのですが、Ubuntuのパッケージでインストールした場合、適当に設定されてしまいます。
任意の名前にしたかったので、下記の手順で変更しました。
suffix変更・suffixにLinux rootユーザーへのアクセス権付与
sudo ldapmodify -Y EXTERANL -H ldapi:/// -f <ldif_file>
ldif
# suffix変更 dn: olcDatabase={1}mdb,cn=config changetype: modify replace: olcSuffix olcSuffix: dc=xxx,dc=yyy - # 管理者ユーザー(rootDN)のdn変更 dn: olcDatabase={1}mdb,cn=config changetype: modify replace: olcRootDN olcRootDN: cn=admin,dc=xxx,dc=yyy - # データベースのアクセス権を一旦削除 dn: olcDatabase={1}mdb,cn=config changetype: modify delete: olcAccess - # データベースのアクセス権追加 # Linuxのrootユーザーに全権限付与 dn: olcDatabase={1}mdb,cn=config changetype: modify add: olcAccess olcAccess: to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break - # デフォルトのデータベースのアクセス権をコピー dn: olcDatabase={1}mdb,cn=config changetype: modify add: olcAccess olcAccess: to attrs=userPassword by self write by anonymous auth by * none - # デフォルトのデータベースのアクセス権をコピー dn: olcDatabase={1}mdb,cn=config changetype: modify add: olcAccess olcAccess: to attrs=shadowLastChange by self write by * read - # デフォルトのデータベースのアクセス権をコピー dn: olcDatabase={1}mdb,cn=config changetype: modify add: olcAccess olcAccess: to * by * read
LDAPコマンドでデータベースにエントリーを追加したかったため、Linuxのrootユーザーにデータベースへの管理者権限を付与しました。
suffix追加
configのsuffixを変更しただけではダメで、データベースのルートとなるエントリー(suffixのdnのエントリー)を追加する必要があります。
sudo ldapadd -Y EXTERANL -H ldapi:/// -f <ldif_file>
ldif
dn: dc=xxx,dc=yyy objectClass: top objectClass: dcObject objectClass: organization dc: xxx o: xxx.yyy
以上でsuffixの変更および、suffixが指すルードdnのエントリーが追加され、suffixが使えるようになります。
rootDN「cn=admin,dc=xxx,dc=yyyx」でphpLDAPadminにログインすると、 新しいsuffix「dc=xxx,dc=yyy」のデータベースにアクセスできるようになります。
configメモ
LDAPの設定は、configデータベースの値を直接編集する形になるのですが、最初いきなりldapsearchでconfigを見ても何のことやらさっぱり分かりませんでした。
configの設定は「slapd.conf」から行うこともできるので、「slapd.conf」を使わないとしても、先に「slapd.conf」をざっくり見ておくと、configの意味が把握しやすくなるかなと思います。
以下、configの設定に関するざっくりとした説明の箇条書きです。
- 「{}」について
- 1つのエントリーに複数の同じ属性が設定されると、属性値の頭に「{<数字>}」という文字が付きます。
- 数字は登録順に0から始まり、属性を区別するのに用いられます。
- 属性値を指定する場合は、「{<数字>}」を含めて記載します。「{<数字>}」は属性登録時に自動で付与されるので、属性を登録する時には属性値に「{<数字>}」は付けません。
- データベースの種類について
- データベースの種類はbdb、mdbなどが選べ、backendと呼ばれます。
- 以前はbdbがデフォルトでしたが、最近はmdbがデフォルトになっています。
- ObjectClass・属性について
- ObjectClass・属性は、LDAPに元々あるものではなく、「dn: cn=schema,cn=config」等で登録されています。
- 「slapd.conf」の「include」を見れば分かるように、デフォルトのテンプレート「/etc/ldap/schema/*.schema」から作成されています。
- 「dn: olcDatabase={1}mdb,cn=config」が通常使うデータベースを指しています。
- 「ocAccess」でconfigやデータベースへのアクセス権限を設定しています。
- 「to <対象属性> by <対象者> <権限> [by <対象者> <権限>]...」で対象属性毎にセットします。
感想等
初めて見た時は、「cn・dc・o・ou」など、すごい意味があるものだと思っていました。一見難しそうに見えるのですが、慣例的に付けられた名前に過ぎずホッとしました。
ツリーも、初めはどういう条件で入れ子になっているのか不明で難しく感じましたが、「どこでも入れ子可能でルールなし」でした。
一方、属性やObjectClassは、プログラム言語のデータ型とクラスのような、シンプルなものかと思ってたのですが、結構複雑でした。色々テンプレートがあるので、あるものを使っていった方が楽そうです。
独特で初見者には取っ付きにくいのですが、先にphpLDAPadmin立てて色々触ってから情報に当たった方が、分かりやすいかと思いました。