お世話になっております、SIOS 那賀です。
先日掲載した「SIOS OSS Tech: RHEL6 系での OpenLDAP サーバと PAM 認証」で、slapd.conf 型から cn=config 型への移行を頑張ろうと決意したのですが、「Convert schema files for import - OpenLdap: Switch to dynamic config backend (cn=config) - Zarafa wiki」を読んでアホらしくなってしまい、slapd.conf へ戻すことにしました。今回の主題は OpenLDAP を使った SSH キーの配布なのですが、その前段として、前回の手順一通りを、slapd.conf を用いるものに書き換えて再掲しようと思います。cn=config 方式にも有用な場面は(多分)あるかと思われますので、既存の記事も、そのまま残しておきます。
ディレクトリ・サーバの設定
まずはいつものように、SELinux と iptables の無効化です。実運用のサーバでは、運用ポリシーに従って、それぞれ適切に設定してください。
[root@dirserv ~]# setenforce permissive [root@dirserv ~]# getenforce Permissive [root@dirserv ~]# service iptables stop iptables: ファイアウォールルールを消去中: [ OK ] iptables: チェインをポリシー ACCEPT へ設定中filter [ OK ] iptables: モジュールを取り外し中: [ OK ] [root@dirserv ~]#
サーバと、操作用のクライアントをインストールします。
[root@dirserv ~]# yum install -y openldap-clients openldap-servers
もし動いているようであれば、slapd サービスを停止させてから、slapd.d/ ディレクトリを削除します。これで、slapd は slapd.conf から設定を読むようになります。
[root@dirserv ~]# service slapd status slapd は停止しています [root@dirserv ~]# rm -fr /etc/openldap/slapd.d/ /var/lib/ldap/*
"Obsolete" のファイルを元に、slapd.conf を作成します。
[root@dirserv ~]# slappasswd -s secret2
{SSHA}Z42Qdb/r/YAw0QRD8vI/SYcLgoxtzF4l
[root@dirserv ~]# cp \
/usr/share/openldap-servers/slapd.conf.obsolete \
/etc/openldap/slapd.conf
[root@dirserv ~]# chown ldap.ldap /etc/openldap/slapd.conf
[root@dirserv ~]# chmod 0600 /etc/openldap/slapd.conf
[root@dirserv ~]# vi /etc/openldap/slapd.conf
[root@dirserv ~]# diff -uNr \
/usr/share/openldap-servers/slapd.conf.obsolete \
/etc/openldap/slapd.conf
--- /usr/share/openldap-servers/slapd.conf.obsolete
+++ /etc/openldap/slapd.conf
@@ -64,9 +64,9 @@
# /etc/pki/tls/certs, running "make slapd.pem", and fixing permissions on
# slapd.pem so that the ldap user or group can read it. Your client software
# may balk at self-signed certificates, however.
-# TLSCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
-# TLSCertificateFile /etc/pki/tls/certs/slapd.pem
-# TLSCertificateKeyFile /etc/pki/tls/certs/slapd.pem
+TLSCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
+TLSCertificateFile /etc/pki/tls/certs/slapd.pem
+TLSCertificateKeyFile /etc/pki/tls/certs/slapd.pem
# Sample security restrictions
# Require integrity protection (prevent hijacking)
@@ -95,14 +95,26 @@
#
# rootdn can always read and write EVERYTHING!
+access to attrs=userPassword
+ by dn="cn=Manager,dc=example,dc=com" write
+ by self write
+ by anonymous auth
+ by * none
+
+access to *
+ by dn.exact="cn=Manager,dc=example,dc=com" write
+ by self write
+ by * read
+
#######################################################################
# ldbm and/or bdb database definitions
#######################################################################
database bdb
-suffix "dc=my-domain,dc=com"
+suffix "dc=example,dc=com"
checkpoint 1024 15
-rootdn "cn=Manager,dc=my-domain,dc=com"
+rootdn "cn=Manager,dc=example,dc=com"
+rootpw {SSHA}Z42Qdb/r/YAw0QRD8vI/SYcLgoxtzF4l
# Cleartext passwords, especially for the rootdn, should
# be avoided. See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
起動します。今回はテストですので、インデックスも BDB の設定も、そのまま放置します。実運用では、パフォーマンスやバックアップにも気をつかってあげてください。
[root@dirserv ~]# service slapd start slapd を起動中: [ OK ]
以下は任意ですが、サーバの挙動が分かりやすいように、ログの出力も設定しておきます。slapd は local4 のファシリティで syslog 出力をするのですが、せっかくの RHEL6 系の rsyslog ですので、アプリケーション名 ("slapd") でログを振り分けるようにしてみます。実運用では、ログが溢れないように、ローテートの設定もしておいてください。
[root@dirserv ~]# cp /etc/rsyslog.conf /etc/rsyslog.conf.orig [root@dirserv ~]# vi /etc/rsyslog.conf [root@dirserv ~]# diff -uNr /etc/rsyslog.conf.orig /etc/rsyslog.conf --- /etc/rsyslog.conf.orig +++ /etc/rsyslog.conf @@ -76,3 +76,6 @@ # remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional #*.* @@remote-host:514 # ### end of the forwarding rule ### + +!slapd +*.* /var/log/slapd.log [root@dirserv ~]# service rsyslog reload Reloading system logger... [ OK ]
アクセスできるかどうか、試してみます。
[root@dirserv ~]# ldapsearch -x -D "cn=Manager,dc=example,dc=com" \ -b "dc=example,dc=com" -w secret2 # extended LDIF # # LDAPv3 # basewith scope subtree # filter: (objectclass=*) # requesting: ALL # # search result search: 2 result: 32 No such object # numResponses: 1
良いようであれば、認証用のデータを入れて行きます。根元から作って行きます。
[root@dirserv ~]# ldapadd -x -D "cn=Manager,dc=example,dc=com" \ -w secret2 <<EOF dn: dc=example,dc=com dc: example objectClass: dcObject objectClass: organization o: Example Corp. dn: cn=Manager,dc=example,dc=com cn: Manager objectClass: organizationalRole dn: o=Users,dc=example,dc=com o: Linux Users objectClass: organization dn: ou=People,o=Users,dc=example,dc=com ou: People objectClass: organizationalUnit dn: ou=Group,o=Users,dc=example,dc=com ou: Group objectClass: organizationalUnit EOF adding new entry "dc=example,dc=com" adding new entry "cn=Manager,dc=example,dc=com" adding new entry "o=Users,dc=example,dc=com" adding new entry "ou=People,o=Users,dc=example,dc=com" adding new entry "ou=Group,o=Users,dc=example,dc=com"
ちょっと間違うと、途中まで作ったところでエラーになり、そこまでの分が半端に残ります。failure atomic ではありません…、トランザクションがあればいいのにね。今回はテストですので、そんな時は、以下のように根元からガバッと再帰で消してしまってください。
[root@dirserv ~]# ldapdelete -v -x -D "cn=Manager,dc=example,dc=com" \ -w secret2 -r "dc=example,dc=com"
ユーザ (foo と bar) を追加します。OpenLDAP のクライアント側 (SSSD, pam_ldap, nss-pam-ldapd 等) は、文書にはあまりキチンと書かれていないのですが (せいぜい /usr/share/doc/nss-pam-ldapd-0.7.5/README くらいか)、デフォルトで、クラス "posixAccount" や "posixShadow" を持つノードを、ユーザ情報として取りにきます。ですので、実はツリー構造は割と恣意的に決めてしまっても問題ありません。
[root@dirserv ~]# pass=$(slappasswd -s secret3) [root@dirserv ~]# ldapadd -x -D "cn=Manager,dc=example,dc=com" \ -w secret2 <<EOF dn: uid=foo,ou=People,o=Users,dc=example,dc=com objectClass: top objectClass: posixAccount objectClass: account gecos: ldap system users cn: foo uid: foo uidNumber: 1000 gidNumber: 1000 homeDirectory: /home/foo loginShell: /bin/bash userPassword: $pass EOF adding new entry "uid=foo,ou=People,o=Users,dc=example,dc=com" [root@dirserv ~]# pass=$(slappasswd -s secret4) [root@dirserv ~]# ldapadd -x -D "cn=Manager,dc=example,dc=com" \ -w secret2 <<EOF dn: uid=bar,ou=People,o=Users,dc=example,dc=com objectClass: top objectClass: posixAccount objectClass: account gecos: ldap system users cn: bar uid: bar uidNumber: 1001 gidNumber: 1001 homeDirectory: /home/bar loginShell: /bin/bash userPassword: $pass EOF adding new entry "uid=bar,ou=People,o=Users,dc=example,dc=com"
グループ (foo と bar) を追加します。こちらも同様に、クライアントはデフォルトで、クラス "posixGroup" を持つノードを探索に来ます。今回は、昨今の Linux ディストリビューションの構成と同様に、UPG (User Private Group) 式で、ユーザごとに個別に同名のグループを割り当てますが、LDAP 的には、共通のグループを割り当てる方が一般的かも知れません。
[root@dirserv ~]# ldapadd -x -D "cn=Manager,dc=example,dc=com" \
-w secret2 <<EOF
dn: cn=foo,ou=Group,o=Users,dc=example,dc=com
cn: foo
objectClass: posixGroup
gidNumber: 1000
userPassword: {CRYPT}x
EOF
adding new entry "cn=foo,ou=Group,o=Users,dc=example,dc=com"
[root@dirserv ~]# ldapadd -x -D "cn=Manager,dc=example,dc=com" \
-w secret2 <<EOF
dn: cn=bar,ou=Group,o=Users,dc=example,dc=com
cn: bar
objectClass: posixGroup
gidNumber: 1001
userPassword: {CRYPT}x
EOF
adding new entry "cn=bar,ou=Group,o=Users,dc=example,dc=com"
一般ユーザから、他人のパスワードが見えないことを確認しておきます。
[root@dirserv ~]# ldapsearch -x \ -D "uid=foo,ou=People,o=Users,dc=example,dc=com" \ -b "dc=example,dc=com" -w secret3 "(objectClass=posixAccount)" [root@dirserv ~]# ldapsearch -x \ -D "uid=bar,ou=People,o=Users,dc=example,dc=com" \ -b "dc=example,dc=com" -w secret4 "(objectClass=posixAccount)"
認証依頼元の Linux ホストの設定
こちらも同様に、SELinux と iptables の無効化です。実運用のサー (以下テンプレ略)。
[root@linhost ~]# setenforce permissive [root@linhost ~]# getenforce Permissive [root@linhost ~]# service iptables stop iptables: ファイアウォールルールを消去中: [ OK ] iptables: チェインをポリシー ACCEPT へ設定中filter [ OK ] iptables: モジュールを取り外し中: [ OK ] [root@linhost ~]#
RHEL5 系の nss_ldap から、RHEL6 系では PAM は pam_ldap に、NSS は nss_ldap からフォークした nss-pam-ldapd へと分離しており、また、それらを束ねる SSSD 抽象化レイヤ (詳細) が入っていたりと、設定ファイルが多岐に渡り、もはや手作業では手に負えなくなっているので、authconfig コマンドを使用します。
同時に、TLS (389 番ポートでの "STARTTLS" による接続) も設定します。authconfig では、認証局ナシでの TLS 設定ができないので、設定をした後で、ちょっとだけ手を入れる必要があります。
SSSD を用いる手順:
[root@linhost ~]# authconfig --disableforcelegacy --enablemkhomedir \ --enableldap --enableldapauth --enableldaptls \ --ldapserver=dirserv.vnat --ldapbasedn="dc=example,dc=com" \ --update sssd を起動中: [ OK ] oddjobd を起動中: [ OK ] [root@linhost ~]# cat <<EOF >> /etc/sssd/sssd.conf ldap_tls_reqcert = never EOF [root@linhost ~]# cat <<EOF >> /etc/nslcd.conf tls_cacertfile /etc/pki/tls/certs/ca-bundle.crt tls_checkpeer no EOF [root@linhost ~]# service sssd restart sssd を停止中: [ OK ] sssd を起動中: [ OK ]
旧来の (legacy な) 手順:
[root@linhost ~]# authconfig --enableforcelegacy --enablemkhomedir \ --enableldap --enableldapauth --enableldaptls \ --ldapserver=dirserv.vnat --ldapbasedn="dc=example,dc=com" \ --update nslcd を起動中: [ OK ] oddjobd を起動中: [ OK ] [root@linhost ~]# cat <<EOF >> /etc/nslcd.conf tls_cacertfile /etc/pki/tls/certs/ca-bundle.crt tls_reqcert no EOF [root@linhost ~]# service nslcd restart nslcd を停止中: [ OK ] nslcd を起動中: [ OK ] [root@linhost ~]# cat <<EOF >> /etc/pam_ldap.conf tls_cacertfile /etc/pki/tls/certs/ca-bundle.crt tls_checkpeer no EOF
では、動作を確認してみます。
[root@linhost ~]# id foo uid=1000(foo) gid=1000(foo) 所属グループ=1000(foo) [root@linhost ~]# su - foo Creating home directory for foo. [foo@linhost ~]$ su - bar パスワード: secret4 Creating home directory for bar. [bar@linhost ~]$ id uid=1001(bar) gid=1001(bar) 所属グループ=1001(bar) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 [bar@linhost ~]$
良いようです。
SSH キー配布の設定
ディレクトリサーバに、SSH のキーを保持する LDAP スキーマが必要なので、oepnssh-ldap をインストールします。
[root@dirserv ~]# yum install -y openssh-ldap
slapd の設定を修正し、スキーマを追加します。キーへのアクセス権限の設定も追加しておきます。
[root@dirserv ~]# cp /etc/openldap/slapd.conf \ /etc/openldap/slapd.conf.orig [root@dirserv ~]# vi /etc/openldap/slapd.conf [root@dirserv ~]# diff -uNr /etc/openldap/slapd.conf.orig \ /etc/openldap/slapd.conf --- /etc/openldap/slapd.conf.orig +++ /etc/openldap/slapd.conf @@ -15,6 +15,7 @@ include /etc/openldap/schema/openldap.schema include /etc/openldap/schema/ppolicy.schema include /etc/openldap/schema/collective.schema +include /usr/share/doc/openssh-ldap-5.3p1/openssh-lpk-openldap.schema # Allow LDAPv2 client connections. This is NOT the default. allow bind_v2 @@ -101,6 +102,11 @@ by anonymous auth by * none +access to attrs=sshPublicKey + by dn="cn=Manager,dc=example,dc=com" write + by self write + by * none + access to * by dn.exact="cn=Manager,dc=example,dc=com" write by self write [root@dirserv ~]# service slapd restart slapd を停止中: [ OK ] slapd を起動中:
ここでキーを作成し、登録します。
[root@dirserv ~]# ssh-keygen -f ~/.ssh/id_rsa -N "" Generating public/private rsa key pair. Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: (中略) [root@dirserv ~]# key=$(cat ~/.ssh/id_rsa.pub) [root@dirserv ~]# ldapmodify -x -D "cn=Manager,dc=example,dc=com" \ -w secret2 <<EOF dn: uid=foo,ou=People,o=Users,dc=example,dc=com changetype: modify add: objectClass objectClass: ldapPublicKey - add: sshPublicKey sshPublicKey: $key EOF
以上で、LDAP サーバ側は終了です。
sshd サーバの設定
sshd サーバが LDAP サーバから、対象ユーザの公開鍵を取得できるように設定します。まずは、sshd の外部プログラムを追加でインストールします。
[root@linhost ~]# yum install -y openssh-ldap
sshd が、外部プログラムからキーを取得するように設定します。上記パッケージに含まれる HOWTO.ldap-keys では "AuthorizedKeysCommand" のパラメータをダブルクォートでくくっていますが、そのように記述すると、パーサはこれを処理しないため、動きません。クォートせずに、"/" で始まる絶対パスを指定してください。なお、stat(2) でファイルの有無を確認しているので、行末にスペース等が入っていると、これまた動きません。総じて不親切です。あまり使われていないのか。
[root@linhost ~]# cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig [root@linhost ~]# vi /etc/ssh/sshd_config [root@linhost ~]# diff -uNr \ /etc/ssh/sshd_config.orig \ /etc/ssh/sshd_config --- /etc/ssh/sshd_config.orig +++ /etc/ssh/sshd_config @@ -45,10 +45,10 @@ #MaxSessions 10 #RSAAuthentication yes -#PubkeyAuthentication yes +PubkeyAuthentication yes #AuthorizedKeysFile .ssh/authorized_keys -#AuthorizedKeysCommand none -#AuthorizedKeysCommandRunAs nobody +AuthorizedKeysCommand /usr/libexec/openssh/ssh-ldap-wrapper +AuthorizedKeysCommandRunAs root # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #RhostsRSAAuthentication no
上記の外部プログラムが利用する設定を記述します。パスワードを含むので、パーミッションに注意してください。設定後、"/usr/libexec/openssh/ssh-ldap-wrapper foo" のように実行してキーが返って来ないようであれば、設定をしくじっています。(※注意: openssh-ldap-5.3p1-52 の ssh-ldap-wrapper には、設定ファイルのパーサにバグがあり、"tls_checkpeer" の設定が効きません。直すか、ちゃんとした証明書を用意するか、TLS をオフにするしかないようです。下記では、オフにしています)
# TLS が使えなくとも、公開鍵ならば平文で飛んでも問題ありませんから、なまじ rootdn のパスワードを指定するよりも、anonymous でキーを取得できるようにした方が良いかも知れません
[root@linhost ~]# cat > /etc/ssh/ldap.conf <<EOF uri ldap://dirserv.vnat/ base dc=example,dc=com binddn cn=Manager,dc=example,dc=com bindpw secret2 host dirserv.vnat ssl no #ssl start_tls tls_cacertdir /etc/openldap/cacerts tls_cacertfile /etc/pki/tls/certs/ca-bundle.crt tls_checkpeer no EOF [root@linhost ~]# chmod 600 /etc/ssh/ldap.conf
sshd を再起動します。
[root@linhost ~]# service sshd restart sshd を停止中: [ OK ] sshd を起動中: [ OK ]
以上です。試しに、~/.ssh/id_rsa.pub を持っているホストからログインしてみます。
[root@dirserv etc]# ssh -o RSAAuthentication=yes \ -o PasswordAuthentication=no -l foo linhost.vnat Last login: Thu Dec XX 15:54:49 2011 from dirserv.vnat [foo@linhost ~]$
良いようですね。では。
0 コメント:
コメントを投稿