Ansible、ユーザーの登録

Tags : Ansible  

一つLinodeでサーバーを建てるために、設定をAnsibleで行おうとしています。

のっけから、ユーザー追加のパスワードでつまづきました。userモジュールで指定するパスワードはハッシュ済みなものを指定するそうですが、Ansible自身のFAQの説明では、mkpasswd --method=SHA-512(mkpasswdをインストールしなきゃ使えない)、python -c "from passlib.hash import sha512_crypt; print sha512_crypt.encrypt('<password>')(pipでpasslibをインストールしてから)をつかえと、なんだか満足出来ない記述でした。

pythonは別として、事前インストールが要らないコードは、python -c 'import crypt; print crypt.crypt("設定パスワード", "$1$ソルト値$")'でした。

まあ、分かります。使用できるパスワードハッシュはmd5だけでは無いので、ハッシュ済みの値を指定する仕様なんですね。

それと、設定パスワードはともかく、ソルト値がいつも一定なのは気持ちがよくありません。それをAnsibleで自動で生成しようとすると、ハッシュ値が毎回変わってしまうため、実行するたびに更新されることになり、設定しようとするパスワード自身が保存されるだろう、/etc/shadowファイルが更新されることになります。すると、ハード構成上では厳密な冪等性が保証できません。

でも、私の場合、個人で使用するだけですし、「指定したパスワードでログインできる」という機能的な部分は、変更されませんので、そこまで厳密な冪等性は入りません。利便性のほうがプライオリティー上なんです。

そこで、自分の欲しいuserロールを作成してみました。ほとんど自分でログインして使用するサーバーに対して使用するものです。

  • ユーザー名と同名のグループに所属させる。
  • Salt値をランダムに生成し、パスワードのハッシュ値を自動に設定する。コードをvarの値として指定する必要がなく、直接パスワードのみを指定する。
  • ローカルの公開キーをコピーする。

前記のように、厳密に言えば冪等性は保証されません。指定したパスワードでログインできるという機能的な意味合いで冪等性は保たれます。

roles/users/tasks/main.yml

- name: グループ作成
  group: name="{{user}}" state=present

- name: Salt値生成
  # 大文字小文字数字の割合もランダムにするため、mktempをdry runして生成
  shell: mktemp -d -u | awk -e '{ print substr($0, length($0)-8+1)}'
  register: salt

- name: ハッシュ化コマンド生成
  command: echo python -c \'import crypt; print crypt.crypt(\"{{password}}\", \"$1${{salt.stdout}}$\")\'
  register: hashCommand

- name: パスワードハッシュ化
  command: "{{hashCommand.stdout}}"
  register: hashedWord

- name: ユーザー登録
  user: name="{{user}}" state=present group="{{user}}" ext_groups="{{groups}}"
        password="{{hashedWord.stdout}}" comment="{{comment}}"
        shell="{{shell}}"

- name: 公開鍵の登録
  authorized_key: user="{{user}}" key="{{item}}"
  with_file: pubkey

いろいろ試した結果、一度echoでコマンド自身を書き出しvarの内容を反映させています。もっと旨い方法がありそうなので、見つけたら後で変更していおきます。

よくやる使用法は、自分のローカルのユーザーを作成し、sudoグループにも所属させることです。

  roles:
      - { role: users, user: hiro, password: test1234, ext_groups: "sudo", 
          comment: "Hirohisa Kawase", pubkey: /home/hiro/.ssh/id_foo.pub,
          shell: /bin/bash }

ext_groupsはuserモジュールに渡しているだけですので、複数指定する場合はカンマ区切りです。

  roles:
      - { role: users, user: hiro, password: test1234,
          ext_groups: "sudo,adm", shell: /bin/bash,
          comment: "Hirohisa Kawase", pubkey: /home/hiro/.ssh/id_foo.pub }

まだ、Ubuntu14.04でしか試していません。サーバーで使用するのはほとんどUbuntuになってしまいました。14.04だとPHPが黙っていても5.5ですから、当分このままで使用できるので、面倒がありません。情報も見つけやすいですしね。

追記:Ubuntuの場合、シェルを指定しないとdashが使用されるため、明示的に指定するように変更しました。