らくがきちょう

なんとなく

CentOS7 に OpenLDAP をインストールし LDAPS を有効化する

CentOS7 に OpenLDAP をインストールし、SSL/TLS サーバ証明書を設定して LDAPS を設定する手順をメモしておきます。

テスト環境

今回は CentOS 7.4.1708 にインストールしました。

$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)

OpenLDAP 関連パッケージは標準リポジトリから以下のバージョンをインストールしました。

OpenLDAP サーバのインストール

OpenLDAP 関連のパッケージは標準リポジトリから yum でインストールします。

yum -y install openldap-clients openldap-servers

設定ファイルをコピーします。 OpenLDAP の設定には動的データベースを使います。

cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
chown ldap. /var/lib/ldap/DB_CONFIG

OpenLDAP サーバを起動します。 併せて自動起動設定も実施しておきます。

systemctl start slapd
systemctl enable slapd

OpenLDAP サーバは標準で 389/TCP を Listen します。

# lsof -i:389
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
slapd   16494 ldap    8u  IPv4 778840      0t0  TCP *:ldap (LISTEN)
slapd   16494 ldap    9u  IPv6 778841      0t0  TCP *:ldap (LISTEN)

管理者パスワードを設定する

管理者パスワードを設定します。 まず、slappasswd で管理者用パスワードを生成します。

slappasswd

実際の実行例は以下の通りです。

# slappasswd
New password:
Re-enter new password:
{SSHA}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

管理者パスワードを変更する為に change-root-password.ldif という LDIF ファイルを作成します。 olcRootPW の値は slappasswd で生成したハッシュ値を指定します。

dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

ldapadd で動的データベースに反映します。

ldapadd -Y EXTERNAL -H ldapi:/// -f change-root-password.ldif

基本的なスキーマの読み込み

基本的なスキーマを読み込んでおきます。

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif

ドメインの設定

次はドメインの設定を行います。 まず、ドメインマネージャ用のパスワードを slappasswd で生成します。

slappasswd

管理者パスワードを生成した時と同様、実行例は以下の通りです。

# slappasswd
New password:
Re-enter new password:
{SSHA}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

ドメインの設定を実施する為に change-domain.ldif という LDIF ファイルを作成します。 dc=example,dc=com の部分は OpenLDAP で管理したいドメイン名に併せて修正します。 olcRootPW の値は slappasswd で生成したハッシュ値を指定します。

dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth"
  read by dn.base="cn=Manager,dc=example,dc=com" read by * none

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=example,dc=com

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=example,dc=com

dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange by
  dn="cn=Manager,dc=example,dc=com" write by anonymous auth by self write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by dn="cn=Manager,dc=example,dc=com" write by * read

ldapmodify で動的データベースに反映します。

ldapmodify -Y EXTERNAL -H ldapi:/// -f change-domain.ldif

ベースドメインと OU の設定

ベースドメインを設定し、その中に OU を作成していきます。 以下の内容で set-base-domain.ldif というファイルを新規作成します。 dc=example,dc=como=EXAMPLE-NETdc: EXAMPLE の部分は自身の環境に併せて変更します。

dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectclass: organization
o: EXAMPLE-NET
dc: EXAMPLE

dn: cn=Manager,dc=example,dc=com
objectClass: organizationalRole
cn: Manager
description: Directory Manager

dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=example,dc=com
objectClass: organizationalUnit
ou: Group

ldapadd で動的データベースに反映します。 dc=example,dc=com の部分は自身の環境に併せて変更します。

ldapadd -x -D cn=Manager,dc=example,dc=com -W -f set-base-domain.ldif

LDAPS を有効化する

LDAP 通信を保護する為、SSL/TLS サーバ証明を用いて LDAPS の設定を行います。 証明書は以下、いずれかの方法を用いて用意します。

  1. 自己証明書を用意する
  2. Let's Encrypt で証明書を取得する

自己証明書を利用する

ここでは自己証明書を作成します。 まず、秘密鍵を作成します。 秘密鍵の新規作成時は必ず、パスフレーズを設定する必要がありますが、以降の手順でパスフレーズは削除します。

cd /etc/pki/tls/certs
make server.key

パスフレーズを削除します。

openssl rsa -in server.key -out server.key

CSR を作成します。 Common Name は LDAPS で公開したい FQDN を指定します。

make server.csr

実際の実行例は以下の通りです。 自身の環境に併せて値は変更します。

# make server.csr
umask 77 ; \
/usr/bin/openssl req -utf8 -new -key server.key -out server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:Chiyoda-ku
Organization Name (eg, company) [Default Company Ltd]:Default Company Ltd
Organizational Unit Name (eg, section) []:Server Division
Common Name (eg, your name or your server's hostname) []:LDAP.EXAMPLE.COM
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

作成した秘密鍵 / CSR を使って証明書を発行します。 証明書の有効期間は 10 年(3,650 日)としました。

openssl x509 -in server.csr -out server.crt -req -signkey server.key -days 3650

作成した証明書は OpenLDAP サーバからアクセス出来る位置にコピーし、所有者も ldap ユーザへ変更します。

cp /etc/pki/tls/certs/server.key \
   /etc/pki/tls/certs/server.crt \
   /etc/pki/tls/certs/ca-bundle.crt \
   /etc/openldap/certs/
chown ldap. \
   /etc/openldap/certs/server.key \
   /etc/openldap/certs/server.crt \
   /etc/openldap/certs/ca-bundle.crt

以下の内容で enable-ldaps.ldif という、証明書関連の設定を行う LDIF ファイルを作成します。

dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/openldap/certs/ca-bundle.crt
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/server.crt
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/server.key

ldapmodify で動的データベースに反映します。

ldapmodify -Y EXTERNAL -H ldapi:/// -f enable-ldaps.ldif

OpenLDAP 自体が LDAPS を Listen 出来るよう、設定ファイルを修正します。 設定ファイルは /etc/sysconfig/slapd です。

  設定
変更前 SLAPD_URLS="ldapi:/// ldap:///"
変更後 SLAPD_URLS="ldapi:/// ldap:/// ldaps:///"

今回は sed で設定変更します。

sed -i -e "s/^SLAPD_URLS=\"ldapi:\/\/\/ ldap:\/\/\/\"/SLAPD_URLS=\"ldapi:\/\/\/ ldap:\/\/\/ ldaps:\/\/\/\"/g" /etc/sysconfig/slapd

設定変更が完了したら OpenLDAP サーバを再起動し、LDAPS の設定は完了です。

systemctl restart slapd

Let's Encrypt で取得した証明書を利用する

Let's Encrypt で取得した証明書を利用することも可能です。 Let's Encrypt で証明書を取得するには Web 認証を用いることも可能ですが、サーバを OpenLDAPディレクトリサービスとしてしか利用せず、Web サーバは有効化しない場合、DNS 認証で証明書を取得した方が余計なソフトウェアを追加せずに済みます。 以前に Let's Encrypt で DNS 認証を使って証明書を発行するというエントリーを書きましたが、DNS 認証で証明書を取得するには、まず certbot-auto をインストールします。 curlcertbot-auto を取得し、実行権限を付与しておきます。

curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto
chmod 700 /usr/bin/certbot-auto

必要なオプションを指定して certbot-auto を実行します。 自身の環境に併せて --email--domain を修正します。 以下を実行すると途中で該当の DNS ゾーンに TXT レコードを作成するように要求されますので、指定の値で TXT レコードを作成し、証明書を取得します。

certbot-auto certonly \
  --debug \
  --manual \
  --email mail@example.com \
  --agree-tos \
  --manual-public-ip-logging-ok \
  --preferred-challenges dns \
  --domain LDAP.EXAMPLE.COM

以下の内容で enable-ldaps.ldif という、証明書関連の設定を行う LDIF ファイルを作成します。 証明書関連のパスは(実体である /etc/letsencrypt/archive では無く)シンボリックリンクである /etc/letsencrypt/live/ を指定しておきます。

dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/letsencrypt/live/LDAP.EXAMPLE.COM/chain.pem
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/letsencrypt/live/LDAP.EXAMPLE.COM/cert.pem
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/letsencrypt/live/LDAP.EXAMPLE.COM/privkey.pem

ldapmodify で動的データベースに反映します。

ldapmodify -Y EXTERNAL -H ldapi:/// -f enable-ldaps.ldif

但し、このままでは OpenLDAP から証明書を参照出来ず、LDAPS 接続が出来ません。 但し、OpenLDAP サーバとしては起動し、LDAP 接続は出来てしまいます… 個人的には「秘密鍵や証明書の読み込みに失敗したのであれば、エラーとなり、サーバは起動に失敗すべき」と思うのですが、OpenLDAP はこのような動きをせず、起動出来てしまうようです…

OpenLDAPldap というユーザで動作する為、Let's Encrypt で取得した証明書のディレクトリを chown ldap. ~ しても良いのですが、こうしてしまうと以下の問題について考慮する必要が出て来ると思われます。

  1. 本来とは異なる所有者に変更した状態で Let's Encrypt の証明書更新処理を行った際、何がしかの不都合が出ないか?(※ 「問題がある」と断定出来るわけでは無いが、「試したことが無い」為に不安)
  2. OpenLDAP 以外のアプリケーションからも同じ証明書を参照させる必要が出てきた場合、所有者を ldap に変更したことによって「他のアプリケーション」から証明書を参照出来なくなってしまう

そこで今回はファイルシステムACL を利用して所有者は root のまま、ldap ユーザからも証明書にアクセス出来るようにします。 ACL を利用する前に、現状を getfacl で確認しておきます。 /etc/letsencrypt/{archive,live} いずれのディレクトリも所有者は root になっており、その他、特別に追加されたユーザやグループはありません。

$ getfacl /etc/letsencrypt/{archive,live}
getfacl: Removing leading '/' from absolute path names
# file: etc/letsencrypt/archive
# owner: root
# group: root
user::rwx
group::---
other::---

# file: etc/letsencrypt/live
# owner: root
# group: root
user::rwx
group::---
other::---

setfacl を使って /etc/letsencrypt/{archive,live}ldap ユーザに「読み取り実行」権限を付与します。

setfacl -m u:ldap:rx /etc/letsencrypt/{archive,live}

改めて getfaclACL の設定を確認します。 ldap ユーザに「読み取り実行」(r-x)権限が追加されていることが分かります。

$ getfacl /etc/letsencrypt/{archive,live}
getfacl: Removing leading '/' from absolute path names
# file: etc/letsencrypt/archive
# owner: root
# group: root
user::rwx
user:ldap:r-x
group::---
mask::r-x
other::---

# file: etc/letsencrypt/live
# owner: root
# group: root
user::rwx
user:ldap:r-x
group::---
mask::r-x
other::---

自己証明書を利用する場合と同様、OpenLDAP 自体が LDAPS を Listen 出来るよう、設定ファイルを修正します。 設定ファイルは /etc/sysconfig/slapd です。

  設定
変更前 SLAPD_URLS="ldapi:/// ldap:///"
変更後 SLAPD_URLS="ldapi:/// ldap:/// ldaps:///"

今回は sed で設定変更します。

sed -i -e "s/^SLAPD_URLS=\"ldapi:\/\/\/ ldap:\/\/\/\"/SLAPD_URLS=\"ldapi:\/\/\/ ldap:\/\/\/ ldaps:\/\/\/\"/g" /etc/sysconfig/slapd

設定変更が完了したら OpenLDAP サーバを再起動し、LDAPS の設定は完了です。

systemctl restart slapd

参考

/etc/sysconfig/slapd

# OpenLDAP server configuration
# see 'man slapd' for additional information

# Where the server will run (-h option)
# - ldapi:/// is required for on-the-fly configuration using client tools
#   (use SASL with EXTERNAL mechanism for authentication)
# - default: ldapi:/// ldap:///
# - example: ldapi:/// ldap://127.0.0.1/ ldap://10.0.0.1:1389/ ldaps:///
SLAPD_URLS="ldapi:/// ldap:///"

# Any custom options
#SLAPD_OPTIONS=""

# Keytab location for GSSAPI Kerberos authentication
#KRB5_KTNAME="FILE:/etc/openldap/ldap.keytab"