LoginSignup
20
17

More than 5 years have passed since last update.

【Ansible】開発者ユーザー追加・削除のベスト・プラクティスを考える

Last updated at Posted at 2016-08-15

【Ansible】開発者ユーザー追加・削除のベスト・プラクティスを考える

開発メンバーが新たに加わるたびに、
サーバ全てで

  • ユーザを追加したり
  • グループに加えてやったり
  • 公開鍵を登録したり
  • パスワード設定したり

手動でやってるとすごく面倒ですよね...
そういうときには、やはりプロビジョニングツールの出番でしょう。

いろいろ調べて、いい感じかな、という所まできたので、メモ代わりに晒します。

利用するツールは,Ansibleです。

準備

AnsibleやPythonのインストール。
加えて、pipでインストールできる、libpassをインストールしておいてください。

$ pip install libpass

ファイル

配置

Ansibleドキュメントの、ベスト・プラクティスを参考にしています。
Best Practices — Ansible Documentation
ファイル配置は下記の通りです。

├── README.md
├── Vagrantfile # 検証用のVagrantfile
├── ansible.cfg # 設定ファイル
├── hosts # インベントリディレクトリ
│   ├── dev
│   │   └── inventory # インベントリファイル
│   └── prd # 今回は使わない
├── roles # Playbook用roleディレクトリ
│   └── user
│       ├── tasks
│       │   └── main.yml # タスク(実際の処理)
│       └── vars
│           └── main.yml # 変数(追加するユーザの情報など)
├── tools
│   └── password_hash.py
└── user.yml

Vagrantfile

検証にvagrantを利用するため、vagrantで立ち上げる検証環境の設定を記述しています。
Vagrantで仮想環境を構築するまでの内容は、以前に執筆した下記の記事を参考にしてください。
【チュートリアル】Ansible 基本のキ (インストールから複数サーバへの変更適用) - Qiita

Vagrantfile
# -*- mode:ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.ssh.insert_key = false
  config.vm.define "webserver1" do |webserver1|
    webserver1.vm.hostname = "webserver1"
    webserver1.vm.box = "bento/centos-6.7"
    webserver1.vm.network "private_network", ip: "192.168.11.21"
  end
  config.vm.define "webserver2" do |webserver2|
    webserver2.vm.hostname = "webserver2"
    webserver2.vm.box = "bento/centos-6.7"
    webserver2.vm.network "private_network", ip: "192.168.11.22"
  end
end

ansible.cfg

設定ファイル。
こちらも内容については以前の記事を参考にしてください。

ansible.cfg
[defaults]
hostfile=hosts/dev
remote_user=vagrant
private_key_file=~/.vagrant.d/insecure_private_key
retry_files_enabled=False

hosts/dev/inventory

Vagrantで立ち上げる仮想環境のインベントリを記述しています。

hosts/dev/inventory
[webservers]
192.168.11.21
192.168.11.22

roles/user/tasks/main.yml

ここが一つのメインですね。
実行していくタスクを記述しています。
with_itemsで、ループ処理を実行していますが、
with_itemsで指定されている内容は、roles/user/vars/main.ymlで記述しています。
各行の内容は、コメントで説明します。

roles/user/tasks/main.yml
---
# グループは先に作成しておく
- name: グループを追加
  group: name={{ item.name }}
  with_items:  '{{ add_groups }}'


# 追加するユーザのグループはwebmasterとする
# 追加するユーザは、全員sudoerとする
# パスワードハッシュは予め作成しておく
- name: ユーザを追加 
  user: >
    name={{ item.name }}
    group=webmaster
    groups=webmaster,wheel
    password={{ item.password_hash }}
  with_items:  '{{ add_users }}'

# authorized_keyモジュールを実行するのに必須
- name: libselinux-pythonインストール
  yum: name=libselinux-python state=present

# 今回は、追加するユーザ = SSHで接続可能とする。よって変数は、「ユーザを追加」と同じ物を利用
- name: 公開鍵の追加
  authorized_key: >
    user={{ item.name }}
    key={{ item.public_key }}
  with_items:  '{{ add_users }}'

# 今回は、削除対象のホームディレクトリごと削除するものとする
- name: ユーザを削除
  user: >
    name={{ item.name }}
    state=absent
    remove=yes
  with_items:  '{{ del_users }}'

roles/user/vars/main.yml

もう一つのメインです。
roles/user/tasks/main.ymlにある通り、
この変数ファイルには、公開鍵や、パスワードハッシュを含んでいます。
それらを平文のまま、バージョン管理に含めるのは、セキュリティ上好ましくないでしょう。
というわけで、ansible-vaultで暗号化してあります。

復号して...

$ ansible-vault decrypt roles/user/tasks/main.yml

平文だと、こんな内容です。

roles/user/tasks/main.yml
---
# 追加するユーザの名前,パスワードハッシュ,SSH接続用の公開鍵
add_users:
  - name: 'watashi'
    password_hash: '$6$hogehogehogehogehogehogehoge...'
    public_key: 'ssh-rsa AAAABbbbbbCCCCCCDDDdddEEEE...'

# 削除するユーザの名前
del_users:
  - name: 'aitsu'

# 追加するグループの名前
add_groups:
  - name: 'webmaster'

パスワードハッシュどうするの?という声が聞こえてきそうですが、
これは、tools/password_hash.pyで作成するものとします。
これについては、のちほど。

ユーザを追加するときは、下記の様に、add_usersに追記する形で編集します

roles/user/tasks/main.yml
 # 追加するユーザの名前,パスワードハッシュ,SSH接続用の公開鍵
 add_users:
   - name: 'watashi'
     password_hash: '$6$hogehogehogehogehogehogehoge...'
     public_key: 'ssh-rsa AAAABbbbbbCCCCCCDDDdddEEEE...'
+  - name: 'aitsu'
+    password_hash: '$6$piyopiyopiyopiyopiyopiyopiyo'
+    public_key: 'ssh-rsa AAAAHHHHHHOOOOOOGGGGGEEEEE...'

編集完了後、再び暗号化してください。

$ ansible-vault encrypt roles/user/tasks/main.yml

なお、暗号化された内容は、下記のような形になります

roles/user/tasks/main.yml
$ANSIBLE_VAULT;1.1;AES256
209384528435009238475029384570293485720349852430592874
(略)

tools/password_hash.py

/etc/shadowに記録されるパスワードハッシュを、取得する必要があります。
一度、どこかでshadowファイルに追記されていれば、同じパスワードハッシュを再利用するのも手ですが、
どこにも登録されていない場合は、コマンドなり、ツールなりでハッシュを生成しなければなりません。
そんなわけで、password_hashを生成するスクリプトを作成しました。

作成にあたって、下記のサイトを参考にさせて頂きました。
Python の passlib でパスワードをハッシュ化する | CUBE SUGAR STORAGE

tools/password_hash.py
from passlib.apps import custom_app_context as pwd_context
import getpass
if __name__ == '__main__':
    password = getpass.getpass()
    hashed_password = pwd_context.encrypt(password)
    print hashed_password

実行するには、このファイルを実行するだけです

$ ./tools/password_hash.py
Password: < ここで入力
$6$rounds=603084$XsVk8R0O3KVgHJEi$mp... < ハッシュが生成される

user.yml

実行するPlaybookです。
roleを実行するだけの内容です。
対象(hosts)は、一旦allとしていますが、
inventoryでグループ管理を行っているなら、適宜書き換えてください。

また、コメントで、大まかな説明をしています。

---
# Playbook user.ymlで実行するユーザー関連の変更
#
#  必要なライブラリ
#  - libpass
#    $ pip install libpass
#  vars
#    - add_users: 追加するユーザ
#    - del_users: 削除するユーザ
#    - add_groups: 追加するグループ
#
#
#    注意
#      - ユーザ削除時には、delete_usersに追加するだけではなく、add_usersからの削除も行う。
#        特に影響はでないが、無駄に作成と削除するのは好ましくない。
#
#
#    パスワードハッシュを取得方法
#
#      0. 同じパスワードが使われているサーバがあれば、/etc/shadowから取得可能
#
#      1. ツールを利用
#        $ ./tools/password_hash.py
#        Password: {{ プロンプトでパスワードを入力 }}


- hosts: all
  become: True
  roles:
    - user

実行コマンド

念のため。

ansible-playbook user.yml --ask-vault-pass

インベントリやsshユーザなどは、
ansible.cfgにデフォルトの値を記載しているので、
ここでは指定しません。

オプションに設定している --ask-vault-passは、
ansible-vaultで暗号化したファイルを復号するのに利用します。

おわりに

パスワードハッシュなど、バージョン管理に入れたくないファイルがあったり、
繰り返しの処理だったり、
Ansibleの便利機能に助けられますね。

もちろん、セキュリティ的にクリティカルな内容(秘密鍵など)は、
暗号化したとしてもバージョン管理に含めるべきではないですが。

とはいえ、Ansibleはまだ絶賛勉強中なので、
鋭い突っ込みをお待ちしております。

20
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
17