Linuxユーザーと公開鍵を統合管理するサーバ&クライアントを書いた[更新]
皆様、明けましておめでとうございます。
ホリデープロジェクトでgoを用いたサーバ&クライアントSimple Toml Name Serviceを書きました。
このサーバ&クライアントを導入するとLinuxサーバのSSHの公開鍵認証に利用する鍵とユーザー、グループをtoml設定ファイルで管理できるようになります。
はじめに
ご存知の通りLinuxはユーザー名とユーザーIDを保持しており、各々の値から双方を解決出来る仕組みがあります。
$ id pyama
uid=1001(pyama) gid=1001(pyama) groups=1001(pyama)
この場合、ユーザー名はpyama
、ユーザーIDは1001
です。実際にはid pyama
コマンドを実行すると、ユーザー名pyama
を元に、ユーザーIDやグループ名、グループIDが取得されています。通常この値は/etc/passwd
に書くか(user add foo)、LDAPなどの外部サービスで管理することが多いと思います。
しかし、昨今はサーバインフラのクラウド化、DevOps文化によるアプリケーションエンジニアのインフラ進出により、以前よりもより多くのサーバ、ユーザーを管理する必要が生まれています。その中でchefなどを用いたプロビジョニングでのユーザー管理や、LDAPでのユーザー管理が煩雑になってきており、それをもっとシンプルに出来ないかという思いで、開発に至りました。シンプルにするために下記の設計思想を反映しています。
1.多くをやらずに一つをやる
2. シンプルなインターフェースを実装し、組み合わせを可能とする
できるようになること
- SSH接続に利用する公開鍵、ユーザー情報をtoml設定ファイルで管理できるようになる
- シンプルなインターフェースを用いて色々なミドルウェアと組み合わせることが出来る
インストール
追記:最新のインストール手順はこちらをご確認下さい。
システムの構成はリクエストに対して、jsonでレスポンスを返すstns
とOSからの呼び出しを元にstnsにリクエストを投げるlibnss_stns.so
をはじめとするクライアントで構成されています。このインターフェースで公開鍵、ユーザー情報を取得することが出来ます。
早速CentOSにインストールしてみましょう。
・サーバのインストール
リポジトリを利用してインストールが可能です。
GitHubのREADMEをご確認ください。
$ curl -fsSL https://repo.stns.jp/scripts/yum-repo.sh | sh
$ yum install stns
設定ファイルは/etc/stns/stns.conf
に配置されます。pyama
ユーザーを作成してみます。
# port = 1104
# include = "/etc/stns/conf.d/*"
[users.pyama]
id = 1001
group_id = 1001
directory = "/home/pyama"
shell = "/bin/bash"
keys = ["ssh xxxxxxx"]
[groups.pyama]
id = 1001
users = ["pyama"]
設定ファイルを編集した場合はreload
もしくはrestart
を実行してください。reload
はシステム無停止で設定ファイルを読み込み直しま
す。
# service stns restart
Reloading stns configuration (via systemctl): [ OK ]
stns-query-wrapper
を使用して動作を確認します。
$ /usr/local/bin/stns-query-wrapper /user/name/pyama
{
"pyama": {
"id": 1001,
"group_id": 1001,
"directory": "/home/pyama",
"shell": "/bin/bash",
"gecos": "",
"keys": [
"ssh-rsa xxxx"
]
}
}
以上でサーバの構築は完了です。設定ファイルの分割に対応しているので、組織グループごとに分割などの利用方法も可能です。
クライアントのインストール
まず最初に、名前解決のキャッシュを行うnscd
をインストールし、キャッシュを可能にします。
$ yum -y install nscd
この例でははpasswdとgroupをキャッシュするように設定しています。
enable-cache passwd yes
positive-time-to-live passwd 600
negative-time-to-live passwd 300
check-files passwd yes
shared group yes
enable-cache group yes
positive-time-to-live group 3600
negative-time-to-live group 300
check-files group yes
shared group yes
enable-cache hosts no
enable-cache services no
enable-cache netgroup no
設定が完了したら忘れずにrestartしておきましょう。
$ service nscd restart
続いてクライアントをインストールします。
サーバと同じくリポジトリを公開しています。
$ curl -fsSL https://repo.stns.jp/scripts/yum-repo.sh | sh
$ yum install libnss-stns
設定ファイルは/etc/stns/libnss_stns.conf
に配置されます。こちらは問い合わせ先のサーバのエンドポイントを指定してください。
api_end_point = "http://<server_ip>:1104"
続いて名前解決にstnsを利用するために、/etc/nsswitch.conf
を編集します。
passwd: files stns
shadow: files stns
group: files stns
上記のようにfilesの後ろにstnsを書いてあげてください。こうしておくと/etc/passwd,/etc/shadow,/etc/groupで対象のレコードがない場合に、stnsに問い合わせが行われます。ここまで設定するとpyamaユーザーの情報が取得できるようになります。
$ id pyama
uid=1001(pyama) gid=1001(pyama) groups=1001(pyama)
もしこのタイミングで確認できない場合、ネガティブキャッシュしている可能性があるので、nscdをrestartしてください。
続いてSSH公開鍵認証に用いる鍵をstns-key-wrapper
を利用して取得する設定を/etc/ssh/sshd_config
に設定します。
PubkeyAuthentication yes
AuthorizedKeysCommand /usr/local/bin/stns-key-wrapper
AuthorizedKeysCommandUser root
こちらも同じく設定後にsshdをrestartしてください。
$ service sshd restart
Redirecting to /bin/systemctl restart sshd.service
また下記をpamの設定に追加することによって、SSHログイン時にホームディレクトリを自動で作成してくれます。
echo 'session required pam_mkhomedir.so skel=/etc/skel/ umask=0022' >> /etc/pam.d/sshd
ここまでの設定で無事SSHログインが可能となります。
$ ssh 192.168.70.11 -l pyama
Last login: Mon Jan 11 15:39:32 2016 from 192.168.70.1
[pyama@client ~]$
sudo
を利用するならば、この例ですとgroupをpyamaとしているので、sudoersに下記のエントリを追加すればsudoが可能となります。
# suコマンドは抑制する
Cmnd_Alias NOTSU = /bin/su
%pyama ALL=(ALL) NOPASSWD: ALL,!NOTSU
以上で一通りの導入が可能となります。おそらくコード化せずにオペレーションしても5分もかからずにインストールすることが出来ると思います。
性能面
手元のMacBook AirのVagrantで立てたsntsのab結果です。(Core:2 Memory:512MB)
$ ab -c 100 -n 100000 http://172.16.0.14:11104/user/name/pyama
Server Software:
Server Hostname: 172.16.0.14
Server Port: 11104
Document Path: /user/name/pyama
Document Length: 605 bytes
Concurrency Level: 100
Time taken for tests: 14.626 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 75700000 bytes
HTML transferred: 60500000 bytes
Requests per second: 6837.32 [#/sec] (mean)
Time per request: 14.626 [ms] (mean)
Time per request: 0.146 [ms] (mean, across all concurrent requests)
Transfer rate: 5054.54 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.9 1 9
Processing: 0 13 7.6 12 182
Waiting: 0 12 7.5 11 180
Total: 0 15 7.5 14 184
Vagrant上でコア1、メモリ1Gのマシンでabを実行し、keepalive無しでRequests per second: 6837.32
なので十分実用に耐えうるのではないかと思います。
keepalivedを入れると10149.22rps程度までは処理が可能です。
最後に
導入が非常に容易であることに加え、実装はシンプルなjsonサーバ、クライアントです。例えばサーバ側をtomlではなくMySQLとRailsで実装したとしてもインターフェースさえ合わせておけば問題なく動作します。
対してクライアントもlibpam-mrubyなどからstnsのAPIを呼び出して利用するといったことも容易に可能です。そして、nginxと組み合わせてSSL対応、認証対応することも出来ますし、keepalivedと組み合わせて冗長を取ることも可能です。
こういった拡張性が高い理由は多くをやらず一つをやる
という思想のもとに構築されているからです。SSH公開鍵認証のためだけにLDAPに疲弊している方、試してみてはいかがでしょうか?
意見は要望は@pyama86にお願いします。