debian8のベースイメージをベースにopenLDAPコンテナを構築する手順をまとめました。
openLDAP(オープン・エルダップ)とは
LDAP(Lightweight Directory Access Protocol, エルダップ)
- ディレクトリデータベース(アカウント管理に特化した専用データベース)へアクセスするためのプロトコル
LDAPとは何をするもの? | Think IT(シンクイット)
openLDAP(オープン・エルダップ)
- オープンソースのLDAP(Lightweight Directory Access Protocol)サーバ
- SSO(シングルサインオン)の認証基盤となり、redmineやGitLabなどのサービスを一つのアカウントでまとめて管理することができます。
- ライセンス:OpenLDAP Public License(独自BSDライセンス)
OpenLDAP, Public License for 2.4.45
DockerでopenLDAPコンテナを作成する
ディレクトリ構成
.
├── Dockerfile
├── config
│ └── custom_inetorgperson.ldif
├── docker-compose.yml
└── entrypoint.sh
custom_inetorgperson.ldif
独自スキーマを定義したLDAP設定ファイル
entrypoint.sh
パッケージをインストールするときにコマンド入力が必要となるインタラクティブな項目(管理者パスワード等)を自動設定するためのラッパー・スクリプト
DockerFile
FROM debian:8
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y \
slapd=2.4.40+dfsg-1+deb8u3 \
ldap-utils=2.4.40+dfsg-1+deb8u3 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
COPY ./config/custom_inetorgperson.ldif /etc/ldap/schema/
COPY ./entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
ENV DEBIAN_FRONTEND noninteractive
ENV DEBIAN_FRONTEND
はインストーラのユーザーインターフェースを制御する環境変数です。slapdパッケージはインストールの際にインタラクティブな回答が必要となるため、
DEBIAN_FRONTEND=noninteractive
と設定することで、インタラクティブな設定をしなくなり(=入力待ちでブロックしなくなる)、自動インストールができます。
5.3. ブートパラメータ
DEBIAN_FRONTEND=noninteractive ってなんだ - Qiita
RUN apt-get update && apt-get install
apt-getの記述はDocker公式ドキュメントのベストプラクティスで推奨された記法に従います。
RUN apt-get update && apt-get install -y を使うことで、最新バージョンのパッケージを、追加の記述や手動作業なく利用できます。
バージョンを指定すると、何がキャッシュされているか気にせずに、特定バージョンを取得した上での構築を強制します。このテクニックは、必要なパッケージの予期しない変更によって引き起こされる失敗を減らします。
apt キャッシュをクリーンにし、 /var/lib/apt/lits を削除することで、イメージのサイズを減らします。 RUN 命令は apt-get update から開始されるので、 apt-get install でインストールされるパッケージは、常に新鮮なものです。
Dockerfile のベストプラクティス — Docker-docs-ja 1.9.0b ドキュメント
slapd
OpenLDAPサーバのパッケージ。
Debian -- stretch の slapd パッケージに関する詳細
ldap-utils
ローカルまたはリモートの LDAP サーバにアクセスできます。LDAP サーバへのアクセスに必要なクライアントプログラムのすべてが含まれます。
Debian -- jessie の ldap-utils パッケージに関する詳細
entrypoint.sh
echo "slapd slapd/internal/adminpw password ${LDAP_ADMIN_PASSWORD}" | debconf-set-selections
echo "slapd slapd/internal/generated_adminpw password ${LDAP_ADMIN_PASSWORD}" | debconf-set-selections
echo "slapd slapd/password1 password ${LDAP_ADMIN_PASSWORD}" | debconf-set-selections
echo "slapd slapd/password2 password ${LDAP_ADMIN_PASSWORD}" | debconf-set-selections
echo "slapd slapd/domain string ${LDAP_DOMAIN}" | debconf-set-selections
echo "slapd shared/organization string ${LDAP_ORGANISATION}" | debconf-set-selections
dpkg-reconfigure -f noninteractive slapd
service slapd start
#add custom schema
ldapadd -Y EXTERNAL -H ldapi:// -f /etc/ldap/schema/custom_inetorgperson.ldif
/bin/bash
entrypoint.shに実行権限を与える
$ chmod +x entrypoint.sh
$ ls -alt entrypoint.sh
-rwxrwxr-x. 1 centos centos 710 7月 30 08:36 entrypoint.sh
debconf-set-selections
- debconf-set-selectionsはパッケージをインストールするときにインタラクティブに設定する項目を事前に設定するコマンドです。
- debconf-set-selectionsはdebconfパッケージに含まれており、 debconfパッケージはDebianのデフォルトでインストールされています。
# dpkg -S /usr/bin/debconf-set-selections
debconf: /usr/bin/debconf-set-selections
docker-compose.yml
version: '3'
services:
web:
build: .
tty: true
container_name: openldap
environment:
- LDAP_ADMIN_PASSWORD=admin
- LDAP_DOMAIN=example.org
- LDAP_ORGANISATION=Example Inc.
networks:
- ldap_nw
ports:
- "389:389"
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
volumes:
- '/srv/ldap:/var/lib/ldap'
networks:
ldap_nw:
external: true
tty
コンテナ内の標準入出力をDockerホストのコンソールにアタッチするための設定です。
logging
ログファイルのサイズと世代管理を指定しないと、ログが溜まりつづけてホスト側のディスクを圧迫する恐れがあるので必ず設定します。
Compose file version 3 reference | Docker Documentation
docker logs で表示されるログの保存場所とローテート方法 - Qiita
networks
以下のコマンドを入力し、OpenLDAPコンテナと連携するその他のコンテナ(phpLDAPadmin, GitLab, redmineなど)をUNIXソケットで通信できるようにするためのコンテナ・ネットワーク(ブリッジ)を作成します。
network create — Docker-docs-ja 1.13.RC ドキュメント
Docker公式によるコマンドラインリファレンス(日本語版)
$ docker network create --driver bridge ldap_nw
コンテナ・ネットワークを作成することで、同一ネットワーク上のコンテナに コンテナ名でアクセスすることができる ようになります。 ネットワーク名は任意ですが、ここではldap_nw
としました。
作成したコンテナ・ネットワークは以下のコマンドで確認できます。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
45d08214f6c2 ldap_nw bridge local
Compose のネットワーク機能 — Docker-docs-ja 1.13.RC ドキュメント
docker-compose で別の docker-compose.yml で作ったコンテナとリンクする (ネットワークを繋げる) - Qiita
以下のコマンドを入力し、コンテナを生成します。
$ docker-compose up -d
以下のコマンドを入力し、コンテナが起動しているか確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
375e6ed11be8 openldap_web "/entrypoint.sh" 44 minutes ago Up 44 minutes 0.0.0.0:389->389/tcp openldap
動作確認をする
openldapコンテナにログインします。
$ docker exec -it openldap bash
データベースの中身を確認します。
# slapcat
dn: dc=example,dc=org
objectClass: top
objectClass: dcObject
objectClass: organization
o: Example Inc.
dc: example
structuralObjectClass: organization
entryUUID: 04a6e1de-0918-1037-9448-af08113323d1
creatorsName: cn=admin,dc=example,dc=org
createTimestamp: 20170730021035Z
entryCSN: 20170730021035.599610Z#000000#000#000000
modifiersName: cn=admin,dc=example,dc=org
modifyTimestamp: 20170730021035Z
dn: cn=admin,dc=example,dc=org
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9K1JCRG1NT0Y3UGEyNWdPZ25hQVR2N3ZmVy9mU0pwN3c=
structuralObjectClass: organizationalRole
entryUUID: 04a8fb72-0918-1037-9449-af08113323d1
creatorsName: cn=admin,dc=example,dc=org
createTimestamp: 20170730021035Z
entryCSN: 20170730021035.613439Z#000000#000#000000
modifiersName: cn=admin,dc=example,dc=org
modifyTimestamp: 20170730021035Z
# ldapsearch -x -D "cn=admin,dc=example,dc=org" -w "admin"
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# search result
search: 2
result: 32 No such object
# numResponses: 1
- -x SASL の代わりに簡易認証を使う
- -D LDAP ディレクトリにバインドする識別名 binddn を指定
- -w 簡易認証のためのパスワードを指定
スキーマの確認
# ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn
dn: cn=config
dn: cn=module{0},cn=config
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
dn: cn={4}custom_inetorgperson,cn=schema,cn=config
dn: olcBackend={0}mdb,cn=config
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}mdb,cn=config
付録:Dockerで使用した設定ファイルについての補足
entrypoint.sh
entrypoint.shでdebconf-set-selections
を使用して設定したslapd slapd/internal/adminpw password
などの項目ですが、ウェブで検索してもなかなかヒットしません。設定値を調べるにあたって、以下のコマンドを使用しました。
debconf-get-selections
debconf-get-selectionsはパッケージをインストールするときにインタラクティブに設定する項目を調べるコマンドです。debconf-get-selectionsはdebconf-utilsパッケージに含まれていますが、 debconf-utilsパッケージはDebianのデフォルトではインストールされていない ため、別途インストールする必要があります。
# dpkg -S /usr/bin/debconf-get-selections
debconf-utils: /usr/bin/debconf-get-selections
debconf-get-selectionsコマンドを使うことで、以下のように
slapdをインストールするときにインタラクティブに設定できる項目を調べることができます。今回作成したentrypoint.shではopenLDAPを構築する上で最低限必要となる下記の赤字の項目を設定しました。
# debconf-get-selections | grep slapd
slapd slapd/internal/generated_adminpw password
slapd slapd/password1 password
slapd slapd/internal/adminpw password
slapd slapd/password2 password
# Do you want the database to be removed when slapd is purged?
slapd slapd/purge_database boolean false
slapd slapd/backend select MDB
slapd slapd/no_configuration boolean false
slapd slapd/dump_database_destdir string /var/backups/slapd-VERSION
slapd slapd/dump_database select when needed
slapd slapd/upgrade_slapcat_failure error
slapd slapd/domain string nodomain
slapd slapd/allow_ldap_v2 boolean false
slapd shared/organization string nodomain
slapd slapd/invalid_config boolean true
slapd slapd/password_mismatch note
# Potentially unsafe slapd access control configuration
slapd slapd/unsafe_selfwrite_acl note
slapd slapd/move_old_database boolean true
Debconf-utilsを使ってインストール時の質問に自動で答える - Qiita
custom_inetorgperson.ldif
デフォルトのinetOrgPersonクラスではsn(Sir Name:姓)
とcn(Common Name:名)
のみが必須入力項目に定義されています。そこでinetOrgPersonクラスで既に定義されているuserPassword
とmail
を新たに必須入力項目とするLDAP設定ファイル(ldifファイル)を作成します。
LDIFとは LDIF(LDAP Data Interchange Format)は、ディレクトリのエントリをテキスト形式で記述するための標準の書式で、RFC2849で定義されています。 リポジトリにエントリを追加したり、リポジトリ内のエントリ情報を変更したりするために使用します。
スキーマ定義を作成する
任意のディレクトリにcustom_inetorgperson.schemaを作成します。ここではinetOrgPersonを継承し、userPasswordとmailを新たに入力が必須な項目として設定しています。
/etc/ldap/schema/custom_inetorgperson.schema
objectclass ( 1.1.2.2.2
NAME 'customInetOrgPerson'
DESC 'Custom Internet Organizational Person'
SUP ( inetOrgPerson )
STRUCTURAL
MUST (
givenName $ userPassword $ mail )
)
任意のディレクトリにinclude.confを作成します。
/etc/ldap/include.conf
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/inetorgperson.schema
include /etc/ldap/schema/custom_inetorgperson.schema
以下のコマンドを入力し、ldifファイルを作成します。
etc/ldap# slaptest -f /etc/ldap/include.conf -F /etc/ldap/slapd.d
config file testing succeeded
成功していれば、以下のように新たにldifファイルが作成されているはずです。
etc/ldap/slapd.d# tree
.
|-- cn=config
| |-- cn=module{0}.ldif
| |-- cn=schema
| | |-- cn={0}core.ldif
| | |-- cn={1}cosine.ldif
| | |-- cn={2}nis.ldif
| | |-- cn={3}inetorgperson.ldif
| | `-- cn={4}custom_inetorgperson.ldif
| |-- cn=schema.ldif
| |-- olcBackend={0}mdb.ldif
| |-- olcDatabase={-1}frontend.ldif
| |-- olcDatabase={0}config.ldif
| `-- olcDatabase={1}mdb.ldif
`-- cn=config.ldif
cn={4}custom_inetorgperson.ldifを以下のように書き換えます。
cn={4}custom_inetorgperson.ldif(修正後)
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 29881081
dn: cn=custom_inetorgperson,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: custom_inetorgperson
olcObjectClasses: {0}( 1.1.2.2.2 NAME 'customInetOrgPerson' DESC 'Custom Int
ernet Organizational Person' SUP inetOrgPerson STRUCTURAL MUST ( givenName
$ userPassword $ mail ) )
cn={4}custom_inetorgperson.ldif.origin(修正前)とcn={4}custom_inetorgperson.ldif(修正後)の差分
# diff -u cn\=\{4\}custom_inetorgperson.ldif.origin cn\=\{4\}custom_inetorgperson.ldif
--- cn={4}custom_inetorgperson.ldif.origin 2017-07-30 10:08:05.024987637 +0000
+++ cn={4}custom_inetorgperson.ldif 2017-07-30 10:10:16.848343049 +0000
@@ -1,15 +1,8 @@
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 29881081
-dn: cn={4}custom_inetorgperson
+dn: cn=custom_inetorgperson,cn=schema,cn=config
objectClass: olcSchemaConfig
-cn: {4}custom_inetorgperson
+cn: custom_inetorgperson
olcObjectClasses: {0}( 1.1.2.2.2 NAME 'customInetOrgPerson' DESC 'Custom Int
ernet Organizational Person' SUP inetOrgPerson STRUCTURAL MUST ( givenName
$ userPassword $ mail ) )
-structuralObjectClass: olcSchemaConfig
-entryUUID: 8a096328-095a-1037-9504-4b6d37bb3025
-creatorsName: cn=config
-createTimestamp: 20170730100646Z
-entryCSN: 20170730100646.165408Z#000000#000#000000
-modifiersName: cn=config
-modifyTimestamp: 20170730100646Z
上記の手順で作成したcn={4}custom_inetorgperson.ldifをcustom_inetorgperson.ldifとしてDockerでコンテナを作成する際に使用しました。
参考文献
- OpenLDAPの設定(IdPv3) - GakuNinShibInstall - meatwiki
- OpenLDAP 2.2 Administrator's Guide: Schema Specification
- CentOS6 OpenLDAPのスキーマ管理
- OpenLDAPサーバーで、属性をスキーマに追加 - Qiita
- OpenLDAP再構築 - 備忘録
- LDAPでのオブジェクト・クラスの管理 - Oracle Directory Server Enterprise Edition管理ガイド
- Docker: DockerfileでExpectスクリプトを使うと複雑になる例 - Narrow Escape
- Linuxの対話がめんどくさい?そんな時こそ自動化だ!-expect編- - Qiita
- Mistoreaa Blog [Shell]対話的シェルを自動実行させる方法
- linux - How to do an initial setup of slapd OLC with ldapmodify - Stack Overflow
- [SOLVED] Script install slapd with admin ldap password
- docker-openldap/startup.sh at stable · osixia/docker-openldap
- CentOS 7 : OpenLDAP : LDAPサーバーの設定 : Server World
- OpenLDAP サーバ
- ldapsearch コマンド - IBM Knowledge Center
- ldapsearch の使用例 - IBM Knowledge Center
- 【LDAP環境構築:6】 コマンドまとめ - Qiita
- LDAP - もわの書斎