Linuxサーバーのアカウント管理について
少人数でサービス開発をしていると、サーバーのアカウント管理を疎かにしてしまいがちです。良くないことだとわかっていながらも、共用ユーザーのログイン情報を数人で共有していたりだとか、rootばかり使っているなんてこともあるのではないでしょうか。
それだとオペレーターが増えたり、退職者がでたりした時に困ることになるので、最初からルールと仕組みを決めておいた方がトータルで楽になります。
前提
- パスワードやログイン鍵の共用、ダメ!絶対!
- rootを常用するの(・A・)イクナイ!!
パスワードやログイン鍵を共用していると、人数が増えた時に誰が作業しているのか把握するのが大変になりますし、退職者が出た時に一斉変更をせざるを得なくなって混乱してしまいます。逆に一部のスタッフを別扱いして権限を制限したユーザーをアドホックに作ったりしてしまうのも管理が煩雑になります。じゃあどうすればよいかというと、個人ごとに普通にアカウントを作れば良いのです。
また、rootユーザーを常用するとミスオペの際のダメージが大きくなる可能性が高まって危険なので、適切にsudoを使うのとオペレーション用の共用アカウントを作ると良いでしょう。
考え方
- SSHログインは個人アカウントで鍵認証のみ
- 個人アカウントにはパスワード付きsudo権を与える
- sudo su - app とかで共用ユーザーになる
- rootパスワードは一部の人は知っている
SSHログインは個人アカウントで鍵認証のみ
サーバーに各ユーザーのアカウントを作成し、そのアカウントでのみサーバーにログインします。ログインは鍵認証のみにしておいたほうが安心でしょう。ユーザーはいつも使っている公開鍵をauthorized_keysに書いておけは、いつものアカウントや鍵でログインできるので、余計な接続情報を覚える必要がありません。
ホストの情報だけを教えてもらい、
% ssh hostname.example.com
などとするだけで、僕の場合だと、サーバーに設定してあるSongmuというユーザーにログインすることができることになります。
また、サーバー上で作業する場合、突然の切断を嫌って、ターミナルマルチプレクサを立てて作業するかと思いますが、個人アカウントの~/に .screenrcや.tmux.confを好きに置いておけるのも便利です。
個人アカウントにはパスワード付きsudo権を与える
個人アカウントでログインしたところで、そのユーザーのままで作業をするわけではありません。アプリケーションの実行やdeployを担当する共用ユーザーになって作業をすることが多いでしょう。そういったユーザーには僕は慣例的にappという名前をつけることが多いです。
% sudo su - app
などとすれば、appユーザーになることが可能です。sudoなので自分のパスワードを入力すればappになれるところがポイントです。個人アカウントはsudoにパスワード入力が必要な設定にしておいたが良いんじゃないかと思います。
appにはそれほど強い権限を与えず、必要最低限の決まりきったコマンドしか実行できないようにしておいた方が良いでしょう。アプリケーションの再起動などsudoが必要な場合もありますがsudoersの設定で一部のコマンドだけNOPASSで実行できるように設定しておくとよいでしょう。
ちなみに、
% sudo su -
とやれば、誰でもrootになることができてしまいます。その辺をSU_WHEEL_ONLYだとかpamだとかsudoersの設定とかで色々頑張ってもいいとは思いますが、僕はそのへん詳しくないのと、そこでそこまで頑張るメリットを感じないので「あんま不用意にrootにならないようにしようね」くらいのお約束でいいかなと思っています。
ちなみに、当然のことながらrootやappはSSHでログインすることはできません。Private Network上でのSSHログインは許容して良いんじゃないかと思います。また、appにはパスワードは必要ないので設定しません。
とにかく外部からログイン可能なのは個人アカウントのみで、権限が必要な作業も個人アカウントでsudoするという原則を忘れなければOKです。
appユーザーでPrivate Network上を渡り歩いている時にちょっと権限が必要な操作をしたくなる時があるかもしれません。その場合は、
% su - Songmu
などとして、この場合はsudoを使わずにsuを使えば自分のパスワードを使って個人アカウントに変更することが可能です。
このへんのsuとsudoの組み合わせは言われてみると当たり前ですが、案外言われてみないと気づかないことも多いんじゃないでしょうか。
rootパスワードは一部の人は知っている
rootユーザーをどの程度直接使うか、rootにパスワードを設定するかどうかはポリシーの違いがあるかと思いますが、個人的にはrootのパスワードは一応設定しておいた方が良いと思います。
なるべくsudoを使うようにするのが良いとは思いますが、/etc/sudoersをぶっ壊して、sudo不能になる悲劇とかごくたまに起こったりするので、sudoを使わずにrootに昇格できる最終手段があったほうが良いんじゃないかと思います。
rootのパスワードは各サーバー共通のものを設定して、一部の人が知っておくようにすると良いかと思います。rootパスワードが共有されていたところで、それがファーストログインに使えるわけではないので特に大きな問題ではありません。
実現方法
最近はサーバー設定に何らかのプロビジョニングツールを使い、そのcookbookなりplaybookなりをリポジトリ管理していることが多いと思うので、アカウント情報もそこで管理してしまえば良いと思います。具体的にはユーザーの以下の情報を管理します。
- 公開鍵
- shadow password
- uid
公開鍵はいつも使っている公開鍵です。最近だとhttps://github.com/username.keysとかで簡単に見られるので便利ですね。
shadow passwordはLinuxユーザーであれば/etc/shadowにあるやつをコピペするなりすればいいと思いますが、Macユーザーだったら、unix-crypt
というgemについてくるmkunixcrypt
というコマンドが今ならお手軽な感じがしました。
% gem install unix-crypt
% mkunixcrypt
uidは各サーバーでユーザー名が同じなのにuidが異なっていたりすると悲しいので一意になるように管理したほうが良いでしょう。
chefだと以下の様なファイルを作って、新たにスタッフが入った時はそのファイルの追加をp-rする運用になってると良いんじゃないかと思います。
% cat songmu.rb
username = "songmu"
user "#{username}" do
uid 1099
gid "wheel"
password "$6$aaaaaaaa$aaaaaaaa..."
end
directory "/home/#{username}/.ssh" do
mode 0700
owner username
end
file "/home/#{username}/.ssh/authorized_keys" do
mode 0600
owner username
content "ssh-rsa ..."
end
で、実際にサーバーを構築するときは必要なユーザーを指定してユーザーアカウントの作成をするという具合です。
今、ansibleで同じことをやろうとしているのですが、ansibleにはauthorized_key moduleというのが標準であるのが良いですね。
アカウントの削除方法
各サーバーからユーザー情報を消すだけでOKです。
% sudo userdel -r songmu
rootパスワードを知っていたところでrootにアクセスする方法はなくなりますが、念のためrootのパスワードも定期的に変更した方が良いかもしれません。
個人的にはこういう感じで、Linuxサーバーのアカウント管理を考えていますが、他にもやり方などあると思うので、他のやり方や考え方があったらぜひ教えて下さい。