SSH(CentOS標準リポジトリのOpenSSH)の公開鍵認証でLDAP認証を利用する手順です。
LDAPにはCentOS標準リポジトリのOpenLDAPを利用しました。
※CentOS 5系ではこの手順ではうまくいきません。
目次
前提知識
LDAPはDNSやファイルシステムのディレクトリ(フォルダ)/ファイル構成と同じような、ツリー型にデータ(エントリ)を保持します。
各エントリは属性をもち、そのエントリが持つ属性の定義(スキーマ)も objectClass という属性としてそのエントリ内に格納しています。
特定のエントリを識別する表記(識別子)を DN(Distinguished Name)といいます。
※DNSでいうFQDN。
参考 http://www.turbolinux.co.jp/products/server/11s/user_guide/openldapdirtree.html
RDBのイメージに近づけると LDAPディレクトリ全体をデータベース、エントリをテーブル(ただし常に1レコードのみ)、スキーマをテーブル定義、属性を各フィールド、と考えると理解しやすいかもしれません。
Web系のエンジニアであればDOM構造を考えればほぼそのままです。
想定する環境
- LDAPサーバのホスト名
- ldap.example.com
- LDAPのBASE DN
- dc=example,dc=com
- 管理者のDN
- cn=ldapadmin,dc=example,dc=com
- 管理者のパスワード
- secret
- 認証対象のユーザ
- user1
LDAPサーバの準備
インストール
必要なパッケージは openldap-servers、 openssh-ldap です。
※実際には openssh-ldap はSSHサーバ側の動作に必要なものでありLDAPサーバ側には不要ですが、後に述べるスキーマが含まれるため合わせて入れてしまいます。
yum install openldap-servers openssh-ldap
初期設定
OpenLDAPサーバが動作するサービスは slapd です。
初期インストール状態でslapdは動き始めていますが、諸々クリアにするために一度とめ、デフォルトのデータ類を削除します。
service slapd stop cd /etc/openldap # 一応バックアップ mkdir ../openldap_orig/etc_openldap mkdir ../openldap_orig/var_lib_ldap cp -rf * ../openldap_orig/etc_openldap cp -rf /var/lib/ldap/* ../openldap_orig/var_lib_ldap # デフォルトデータ削除 rm -rf /etc/openldap/slapd.d rm -rf /var/lib/ldap/*
設定に必要な各種ファイルを準備します。
# 雛形となる各種ファイルコピー cp /usr/share/openldap-servers/slapd.conf.obsolete slapd.conf cp /usr/share/doc/openssh-ldap-5.3p1/openssh-lpk-openldap.schema schema/openssh-lpk-openldap.schema cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
slapd.conf の編集
slapd.conf を編集します。
スキーマファイルのインクルードが並んでいる最後あたりに下記を追記。
include /etc/openldap/schema/openssh-lpk-openldap.schema
# Sample access control policy: とか言ってる後あたりに下記を追記。
管理者アカウントの設定と、誰でも読み込めて本人のみ編集化として権限設定。
access to attrs=userPassword by dn="cn=ldapadmin,dc=example,dc=com" write by self write by anonymous auth by * none access to * by self write by * read
# database definitions 以下で利用するDBの設定(今回は bdb)
database bdb suffix "dc=example,dc=com" checkpoint 1024 15 rootdn "cn=ldapadmin,dc=example,dc=com" rootpw secret
※rootpw は実際はプレインテキストではなく、slappasswd コマンドでパスワードを入力した結果出てくるハッシュを入れるべき。
この状態で slapd サービスを起動すると、自動的に slapd.d 以下および /var/lib/ldap 以下に関連ファイルが作成される(はず)。
service slapd start
データ登録
本来はOUとかを合わせて考える方がいいですが、今回は簡略のためベース直下に直接ユーザを配置するつもりで。
LDAPのツリー構造のルートと、管理アカウントのエントリをまず作るための LDIFファイル(仮に init.ldif とします)を作成します。
dn: dc=example,dc=com objectClass: dcObject objectClass: organization dc: example o: example dn: cn=ldapadmin,dc=example,dc=com objectclass: organizationalRole cn: ldapadmin
これをLDAPに登録します。
ldapadd -x -h localhost -D "cn=ldapadmin,dc=example,dc=com" -w secret -f init.ldif
[help]
【参考】実用 Apache 2.0運用・管理術(7):Apacheで作るファイルサーバ(LDAP認証編) (1/4) - @IT
http://www.atmarkit.co.jp/ait/articles/0601/17/news096.html
[/help]
LDAP認証を利用するユーザのエントリ登録
前提知識
この手順の場合、LDAP認証の際に実際に使われているコマンドは /usr/libexec/openssh/ssh-ldap-wrapper [ユーザ名]
、ssh-ldap-wrapper の実態は ssh-ldap-helper -s $1
、実際に検索に使っているのは (&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=ユーザ名))
のようでした。
→ posixAccountスキーマ かつ ldapPublicKeyスキーマ のエントリの属性 uid でチェック。
しかし、posixAccountスキーマ、ldapPublicKeyスキーマはどちらも AUXILIARY なスキーマであり、LDAPのエントリには STRUCTURAL なスキーマが1つは必要なため、accountスキーマを利用します。
また、ldapPublickey スキーマは uid と sshPublicKey しか属性を持っていませんが、accountスキーマ、posixAccount スキーマは下記の属性を含みます。
- account
-
- [必須属性]
-
- userid(uidと同義)
- [任意属性]
-
- description
- seeAlso
- localityName
- organizationName
- organizationalUnitName
- host
- posixAccount
:
- [必須属性]
-
- cn
- uid
- uidNumber
- gidNumber
- homeDirectory
- [任意属性]
-
- userPassword
- loginShell
- gecos
- description
※今回の手順の場合、pam等で認証をしているわけではなく、OpenSSHの公開鍵認証の際の公開鍵の取得先をLDAPにしているだけなので、uid、sshPublicKey 以外は何を書いていても動作に影響しません。
LDIFファイル作成→LDAPに登録
これらを踏まえて、認証ユーザのエントリを下記のようなファイル(LDIFファイル:仮に user1.ldif というファイルとして)に作成します。
user1.ldif
dn: uid=user1,dc=example,dc=com objectClass: account objectClass: posixAccount objectClass: ldapPublickey uid: user1 cn: user1 uidNumber: 1001 gidNumber: 1001 homeDirectory: /home/user1 sshPublicKey: [公開鍵テキストを1行で貼り付ける]
※空白行を区切りにすることで、複数エントリを1ファイルに作ることができます。
user1.ldif を利用して、LDAPサーバにエントリを登録します。
ldapadd -x -D 'cn=ldapadmin,dc=example.dc=com' -f user1.ldif -W >(パスワード入力)
問題がなければ正常に取り込まれるはずです。
SSHサーバ側(LDAP認証を利用するサーバ)の設定
前提条件として、LDAP認証を行いたいサーバ側から上記で用意したLDAPサーバに接続できる必要があります。
iptablesなどの設定を確認しておきましょう。
また、認証ユーザのアカウントが存在する必要があります。
事前準備:アカウント作成
既にアカウントがある場合は次の[インストール]に進んで構いません。
useradd user1
インストール
必要なパッケージは openssh-ldap です。
※LDAPサーバと同一サーバで、上記の手順で構築した場合は既にインストールされています。
yum install openssh-ldap
初期設定
/etc/ssh/ldap.conf として下記を作成。
uri ldap://ldap.example.com/ base dc=example,dc=com ssl no
/etc/ssh/sshd_config に下記を追記
AuthorizedKeysCommand /usr/libexec/openssh/ssh-ldap-wrapper
一旦動作テスト
sshdの再起動(設定反映)をする前にこの時点で一旦動作テストをします。
上記の sshd_config の設定で /usr/libexec/openssh/ssh-ldap-wrapper を使って公開鍵を取得するように設定したので、そのコマンドを手動で叩いてみるということです。
/usr/libexec/openssh/ssh-ldap-wrapper user1
正常に動作すればuser1の公開鍵がLDAPから取得されて表示されます。
何も表示されないとか何かエラーが表示される場合はどこかに間違いがあるので、messegeログなどを参考にトラブルシューティングします。
sshd に設定反映
sshd は再起動しても既につながれているセッションを切断しないので、現在接続している環境で再起動し、そのセッションをつないだまま別のターミナルなどからSSH接続のテストをします。
テストで接続できないときは既につないでいる方のセッションでなんとかします。
(なんとかできないと大変なことになります。)
service sshd restart
テストの際は、user1の .ssh/authorized_keys を一度どこかに移動するなど、公開鍵が設定されていない状態にしてから行うと確かにLDAPから取得しているのかがわかりやすいです。
注意事項
本来はSSL対応や iptables などの接続制限など様々考慮する必要がありますが、この投稿の範囲では割愛しています。
(この投稿の範囲でネットワーク上を流れるのは「公開鍵」だし・・・とか言い訳。)
また、素直にLDAP検索をするようなクライアントツールは openldap-client をインストールすることで利用できます。