Linuxユーザーと公開鍵を統合管理するサーバ&クライアントのSTNSを書き直した
この度、Linuxユーザーと公開鍵を統合管理するサーバ&クライアントのSTNSをすべて書き直し、v2をリリースしたので、お知らせします。
v1リリース時の記事は下記にあります。
はじめに
STNS v2のリリースに当たり、改めてLinuxの名前解決について紹介します。
Linuxはファイルのパーミッションやログイン権限の管理にユーザー名やグループ名が使われています。しかし、実際にパーミッションに利用されている値はID値であり、それらを名前と紐付けるためにいわゆる名前解決が必要です。
$ id example uid=2000(example) gid=2000(example) groups=2000(example)
この例ですと、example
ユーザーはID 2000
を持つユーザーであることがわかります。
これらの名前解決を行うにあたり、Linux標準の仕組みですとuseradd
コマンドでユーザーを追加すると、通常は/etc/passwd
や/etc/group
、/etc/shadow
ファイルにユーザーやグループの情報が書き込まれるのですが、昨今、デザイナーによるデプロイのためのログインなど多くの職種がサーバにアクセスする機会が増えており、それらを手で管理したり、プロビジョニングツールで管理するのはあまりベターな仕組みとは言えません。また人材の流動性も上がっており、入退職もしやすくなったため、ワンストップでユーザー管理ができる必要があります。
このようなユーザー管理を行うにあたり、ある程度サービス規模が大きくなってくるとLDAPやDBを利用してユーザー管理を行うのが常であったと思いますが、LDAPやDBでの管理はWeb業界で好まれるコード管理やGitHub WorkFlowと必ずしも相性がよくありません。
それらを解決するために、筆者が開発したのがSimple Toml Name Serviceです。
v2のアーキテクチャはこちらの図のとおりです。
STNSを利用すると下記のようなシンプルな設定ファイルでユーザー・グループの統合管理を行うことができます。
[users.pyama] id = 1001 group_id = 1001 directory = "/home/pyama" shell = "/bin/bash" keys = ["ssh xxxxxxx"] [groups.pyama] id = 1001 users = ["pyama"]
筆者の所属するGMOペパボでは、この設定ファイルをThorスクリプトを利用して、GitHubAPIから自動で生成し、ユーザー・グループ管理を行っています。この運用の便利なところはGitHub上のチームとサーバのアクセス権が一致させやすいことや、GitHubには公開鍵情報があり、そのまま利用できること、GitHubの情報をもとにしているので権限の剥奪漏れが少ないことです。
一方でファイル生成の方法はユースケースによって異なると思うので、この記事ではインストールから名前解決までを解説し、v2の変更点を紹介したいと思います。
各種ドキュメントは下記のサイトをご確認ください。
サーバのインストール
Rhel系、Debian系ともにパッケージを提供しています。この手順はUbuntu xenialで進めます。まずクライアントからのクエリに応答するサーバをインストールします。まずはパッケージリポジトリを追加します。
$ curl -fsSL https://repo.stns.jp/scripts/apt-repo.sh | sh
リポジトリをインストールしたらサーバをインストールします。
$ apt install -qqy stns-v2
次に設定ファイルを編集し、このようにしてみました。
$ cat /etc/stns/server/stns.conf [users.example] id = 1001 group_id = 1001 keys = ["ssh-rsa XXXXX…"] [groups.example] id = 1001 users = ["example"]
設定を編集したらrestartしてください。
$ service stns restart
curlを利用して動作確認しましょう。
$ curl -s http://localhost:1104/v1/users | jq [ { "id": 1001, "name": "example", "password": "", "group_id": 1001, "directory": "", "shell": "", "gecos": "", "keys": [ "ssh-rsa XXXXX…" ] } ]
たったこれだけでサーバの構築は完了です。次にクライアントをインストールします。
クライアントのインストール
クライアントもサーバと同じくパッケージからインストール可能です。
$ apt install -qqy libnss-stns-v2
サーバと同じように設定ファイルを書きます。
$ cat /etc/stns/client/stns.conf api_endpoint = "http://localhost:1104/v1/"
STNS自体の設定はこれで完了です。次に nsswitch.conf
を下記のように編集し、Linuxの名前解決にSTNSを利用するようにします。下記のように passwd
, group
,shadow
にstns
を追加してください。
$ grep -e passwd -e shadow -e group /etc/nsswitch.conf passwd: compat stns group: compat stns shadow: compat stns
ここまでの作業でSTNSで名前解決ができるようになります。
$ id example uid=1001(example) gid=1001(example) groups=1001(example)
STNSを利用してSSHログインする
STNSはLinuxのユーザー、グループの名前解決だけではなく、SSHの公開鍵ログインもサポートしています。公開鍵ログインを行うには、 /etc/ssh/sshd_config
に下記の設定を行います。
PubkeyAuthentication yes AuthorizedKeysCommand /usr/lib/stns/stns-key-wrapper AuthorizedKeysCommandUser root
次にsshdをrestartします。
$ service ssh restart
テストするために公開鍵をSTNSに設定します。
$ mkdir /home/example && chown example /home/example $ su - example example@localhost:~$ ssh-keygen ... example@localhost:~$ cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkokLd+sFWbKuqepOVNhStZA55MYQ+RiXiS9Ub1PhS5aPDh06MHf80oLg9mKoG883ZsjD7zgYKunUnafG3NdFqHHTgMLS3By0IPi3ZNKVZStvjvCEahqoAs7gUEzOuNqa9hW9f7f5BfausSSuJ1s00WglrPmCMLvfBf9Y54o3xZm+/Uw8ehFHi8s1x5p/7I25WlEwbkL24CmugvvKuWh/bIcK84xRJO43m2Q/u3IArQjOum8Xim+Psj1xDc6DkbToHmoVCnFDoyMUM+VjnLPYpE4gh/8DBFlzNnRi4FrahJMJGbG/wGP6uovbcbmoj46/nYXGMlzBvU3WnhZbOskf/ example@localhost $ cat /etc/stns/server/stns.conf [users.example] id = 1001 group_id = 1001 # ★作成した公開鍵を設定する keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkokLd+sFWbKuqepOVNhStZA55MYQ+RiXiS9Ub1PhS5aPDh06MHf80oLg9mKoG883ZsjD7zgYKunUnafG3NdFqHHTgMLS3By0IPi3ZNKVZStvjvCEahqoAs7gUEzOuNqa9hW9f7f5BfausSSuJ1s00WglrPmCMLvfBf9Y54o3xZm+/Uw8ehFHi8s1x5p/7I25WlEwbkL24CmugvvKuWh/bIcK84xRJO43m2Q/u3IArQjOum8Xim+Psj1xDc6DkbToHmoVCnFDoyMUM+VjnLPYpE4gh/8DBFlzNnRi4FrahJMJGbG/wGP6uovbcbmoj46/nYXGMlzBvU3WnhZbOskf/"] [groups.example] id = 1001 users = ["example"] $ service stns restart
ここまででsshログインが可能になるので試してみます。
$ ssh localhost -l example Last login: Sun Sep 9 02:11:43 2018 from ::1 example@localhost:~$
無事ログインできましたね。このように比較的少ない手番でLinuxの統合ユーザー管理が可能になるので、中小規模でお困りの方がいたらぜひ利用してみてください。またサーバサイドは普通のHTTPサーバなのでnginxやkeepalivedと組み合わせて冗長化することも可能ですし、Basic認証やToken認証に対応しているのでHTTPS化してセキュアな運用も可能です。
さて次にv1からの変更点をいくつか紹介します。
v1からの変更点
nscdが不要
従来のv1ではSTNS自体にキャッシュ機構がなかったため、nscdを利用したキャッシュが必要だったのですが、v2からは独自のキャッシュ機構が組み込まれているためnscdなしで高速動作が可能です。
インターフェースがRESTfulに
v1ではmapのようなデータ構造であったのですが、Arrayデータ構造へ変更し、よりサーバ側の開発が行いやすくなりました。またエンドポイントも全て見直しています。
before
{ "pyama": { "id": 1001, "group_id": 1001, "directory": "/home/pyama", "shell": "/bin/bash", "gecos": "", "keys": [ "ssh-rsa xxxx" ] } }
afterr
[{ "name": "pyama", "id": 1001, "group_id": 1001, "directory": "/home/pyama", "shell": "/bin/bash", "gecos": "", "keys": [ "ssh-rsa xxxx" ] }]
libnss-stnsがGolangからC言語へ
v1では全てGolangで開発されて追ったのですがv2からはクライアントサイドはC言語で開発されています。理由としてはv1はCGOを利用してクライアントサイドの処理を行っていたのですが、clone時のメモリの持ち回り方などが怪しく、SEGVの要因になっていたので、C言語で書き直しています。
コードの見通しが良くなった
もともとSTNSは筆者が2年ほど前にGolangの学習用途で開発したプロダクトだったのでどちらかというとバッドノウハウの塊のようなコードになっていました。それらを今の力ですべて書き直したので以前よりだいぶ見通しが良くなっています。
パラメーター項目の変更
- api_end_point → api_endpoint
区切り文字の位置の変更及び、データが配列から、文字列へと変更されています。["http://xxxx"]
→ “http://xxxx”
v1からの移行パス
サーバ側はVirtualHostなりポートを変えるなりで起動すれば良さそうです。クライアント側は下記のように削除してから、インストールしてください。
$ apt remove libnss-stns $ apt install libnss-stns-v2
最後に
公開から2年ほど経過し、GitHub Starは180を超え、商用サービスからお声がかかるほど成長した反面、コードベースがあまり良くなくメンテナンスするモチベーションが低くなっていtので、C言語の勉強を兼ねてフルスクラッチで書き直しました。サーバサイドもlabstack/echoを採用し、ミドルウェアを利用した拡張を行いやすくしています。
今後についてはSlackを利用した2FAや監査の仕組みなど機能拡張を進めていく予定です。まだ利用されてない方は利用していただいて、既に利用中の方はv2への移行を進めていただければ幸いです。