ansibleでLinuxユーザーの作成と鍵認証を設定する


[Hamee Advent Calendar](http://qiita.com/advent-calendar/2015/hamee)18日目の記事です。
[Ansible Advent Calendar](http://qiita.com/advent-calendar/2015/ansible)18日目の記事です。

## はじめに
インフラエンジニアをやっています。
元々アプリケーション側をやっていましたが、中途入社と同時にインフラに転身し半年ぐらい経ちました。
infracture as codeということで構成管理ツールに触れてみようかと思います。
業務ではchefを使っていますが、シンプルそうなansibleも使ってみたいなーと思っていたのでフィーチャリングしてみます。

ansibleは構成管理以外にも開発補助的な使い方もできて、対象のホストにchefの様にクライアントを入れる必要もないので割とシンプルに触れる印象です。

今回はよくLinuxのユーザを作成して鍵認証を設定するのでそれを題材としてansibleを使って行う方法を紹介していきます。


## ansibleとは
今更ですが、ansibleは[chef](https://www.chef.io/chef/),[puppet](https://puppetlabs.com/)とかと同じプロビジョニングツールの１つです。

できることはchef,puppetと大きな相違はないですが、
inventoryファイルとplaybookファイルの最低2ファイルがあれば動作するぐらいシンプルです。


## 通常のコマンドでlinuxユーザー作成して鍵認証を設定する場合

testuserという名前のユーザを作成します。


・認証鍵がなければローカル上で公開鍵と秘密鍵を作成

```
ssh-keygen -t rsa
```

秘密鍵：id_rsa
公開鍵：id_rsa.pub
の2ファイルが生成される


対象ホストにログイン後、

・ユーザ作成

```
useradd testuser
```


・ディレクトリ作成、パーミッション変更

```
mkdir -p home/testuser/.ssh/
chmod 700 home/testuser/.ssh
chmod 600 home/testuser/.ssh/authorized_keys
```

・/authorized_keysに公開鍵を貼付け

```
echo id_rsa.pub >> .ssh/authorized_keys
```


sudo権限を与えるなら

```
visudo
```


```:visudo
testuser ALL=(ALL) NOPASSWD:ALL

```

今回この手順をansibleで簡略化する。


##ansibleで書いてみる

### ansibleのインストール

epelのインストール

```
wget https://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
```

```
rpm -Uvh epel-release-6-8.noarch.rpm
```


ansibleをインストールする

```
yum install ansible
```


### 初期設定

inventoryファイルが必要です。
接続先のホストの情報等を書いてあげましょう。
慣習的にhostsというファイル名で作成します。


```:hosts
[web]
#ここに対象のIPアドレスを入れてください
```


### サーバにpingをうつ・疎通確認
まずは対象のサーバに疎通できているかの確認をしましょう。


```
ansible （対象のIPアドレス） -m ping -i hosts -u （サーバへのログインユーザ） --private-key="（秘密鍵のパス）"
```

※この時のユーザと秘密鍵は対象サーバへ既にログインできるアカウントにて行ってください。

下記のようにpongが返ってきたら成功です。

```
(対象のIPアドレス) | success >> {
    "changed": false,
    "ping": "pong"
}
```


### 実行ファイル（playbook）の記述

ymlファイルに記述します。
このファイル（playbook.yml）に書かれている事が実行されます。
taskに実行内容を定義します。
nameは必須ではないですが、実行内容を書いておきます。
あとは[Module](http://docs.ansible.com/ansible/modules_by_category.html)を駆使して定義します。


```playbook.yml
- hosts: all
  sudo: true
  tasks:
    - name: add a new user      #Linuxユーザの作成
      user: name=testuser2 state=present

    - name: mkdir .ssh          #.sshフォルダの作成
      file: dest=/home/testuser2/.ssh/ state=directory owner=testuser2 group=testuser2 mode=700

    - name: add authorized keys #.ssh以下にauthorized_keysファイルの作成
      file: dest=/home/testuser2/.ssh/authorized_keys state=touch owner=testuser2 group=testuser2 mode=600

    - name: copy publickey     #公開鍵を貼付け
      copy: src=~/id_rsa.pub dest=/home/testuser2/.ssh/authorized_keys

```



### 実行

下記のコマンドで実行できます。

```
ansible-playbook -i hosts playbook.yml -u （サーバへのログインユーザ） --private-key="（秘密鍵のパス）"
```
※この時のユーザと秘密鍵も対象サーバへ既にログインできるアカウントにて行ってください。


実行結果

```
PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [52.69.41.106]

TASK: [add a new user] ********************************************************
changed: [52.69.41.106]

TASK: [mkdir .ssh] ************************************************************
changed: [52.69.41.106]

TASK: [add authorized keys] ***************************************************
changed: [52.69.41.106]

TASK: [copy publickey] ********************************************************
changed: [52.69.41.106]

PLAY RECAP ********************************************************************
52.69.41.106               : ok=5    changed=4    unreachable=0    failed=0
```

これにて成功です！



下記のhostsファイルのように書き加えてあげると、実行時のコマンドが楽になります。

```:hosts
[web]
(対象のIPアドレス) 

[all:vars]
ansible_ssh_user=（サーバへのログインユーザ）
ansible_ssh_private_key_file=（秘密鍵のパス）

```

実行コマンド

```
ansible-playbook -i hosts playbook.yml
```


### 変数を使ってみる
ファイルに数カ所ユーザ名を記述していくのはしんどいので
変数で持たせて、ファイル実行時に変数に定義すればいいようにします。
varsで定義して、{{}}で囲うと変数として扱えます。


```playbook.yml
- hosts: all
  sudo: true

  vars:
    - username:  #put username
    - homedir:   /home/{{username}}
  tasks:
    - name: add a new user
      user: name={{username}} state=present home={{homedir}}

    - name: mkdir .ssh
      file: dest={{homedir}}/.ssh/ state=directory owner={{username}} group={{username}} mode=700 

    - name: add authorized keys
      file: dest={{homedir}}/.ssh/authorized_keys state=touch owner={{username}} group={{username}} mode=600

    - name: copy publickey
      template: src=public.j2 dest={{homedir}}/.ssh/authorized_keys
```


### templateモジュールを使ってみる

秘密鍵のファイルのパスを指定してコピーするのはめんどくさいので
[template](http://docs.ansible.com/ansible/template_module.html)モジュールを使ってみます。
この場合、playbook.ymlと同じ階層にpublic.j2というファイルを作成し、公開鍵を貼付けます。
j2は[jinja2](http://jinja.pocoo.org/docs/dev/)の拡張子です。


```playbook.yml
    - name: copy publickey #公開鍵を貼付け
      copy: src=~/id_rsa.pub dest=/home/testuser2/.ssh/authorized_keys
```
↓

```playbook.yml
    - name: copy publickey #公開鍵を貼付け
      template: src=public.j2 dest={{homedir}}/.ssh/authorized_keys
```


## まとめ

今回は題材がシンプルだったのでansibleの便利な機能を紹介しきれていません。
まだ改善の余地がたくさんありそうなので、随時更新していきたいと思います。




[komitomo/linux-useradd-playbook](https://github.com/komitomo/ansible-ssh-keygen/tree/master)

## 参考

[ansible Documentaion > Module Index](http://docs.ansible.com/ansible/modules_by_category.html)
[Ansible Tutorial](http://yteraoka.github.io/ansible-tutorial/#best-practices-directory)
[Ansibleでよく使うファイル操作モジュール](http://dev.classmethod.jp/server-side/ansible/ansible-file-modules-intro/)
[Ansibleのドキュメントを読んでみたメモ](http://qiita.com/okochang/items/f264825e538dbce5dfac)
[Ansible ～fileモジュール～](http://qiita.com/moiwasaki/items/e2c843e255c81a65746c)
[Ansibleでsshユーザを指定する](http://qiita.com/kiarina/items/397b12c56aea83669286)
[Ansibleを使ってリモートでコマンドを実行する](http://tdoc.info/blog/2014/01/22/ansible_adhoc_commands.html?utm_source=zenback&utm_medium=http%3A//turubee.hatenablog.com/entry/2014/07/17/015908&utm_campaign=zb_related_links)