Puppet4.xではじめるサーバ設定自動化 6（ユーザ・グループ）

Puppet4.xではじめるサーバ設定自動化の、ユーザ・グループ編です。
全体的な目次は、[ここ](http://qiita.com/kijibato/items/ae510dfa91884bdd9f61)を参照してください。
主にCentOS 7を例に紹介しているので、その他OSについては読み替えてください。

今回の内容は、Linuxのグループ設定、ユーザ設定の細かい項目を含んでいるので、必要な部分だけご参考に。

# グループ作成
まずはグループ作成の書き方です。

## 基本
グループを作成する場合、Puppetのマニフェストでgroupリソースで定義します。
developerグループを作る場合の例です。

```puppet:group01.pp
group { "developer" :
  ensure => "present",
  gid    => "1101",
}

```

- groupの右側のタイトルに、グループ名を指定
- ensure属性に、presentを指定
- gid属性は、グループIDを指定

なお、ensure属性にabsentを指定すると、グループの削除ができます。ただ、グループ削除する場合は慎重に。また、gidはグループごとのユニークなIDなので、すでに別のグループが同じGIDを使っているとエラーになります。

## 複数グループを作る
複数のグループを作る場合の書き方です。

### シンプルに列挙する
groupリソースを作りたいグループ分書けば、複数のグループを作る定義になります。シンプルな方法です。

```puppet:group02.pp
group { "developer" :
  ensure => "present",
  gid    => "1101",
}

group { "tester" :
  ensure => "present",
  gid    => "1201",
}

```

### ハッシュでループ
列挙が面倒な場合は、ハッシュでグループと属性を設定して、ハッシュでループさせる書き方もできます。Rubyぽい書き方です。**このループの文法は、Puppet4.xから使えます。**

```puppet:group03.pp
$groups_hash = {
  "developer" => {"ensure" => "present", "gid" => "1101"},
  "tester"    => {"ensure" => "present", "gid" => "1201"},
}

$groups_hash.each |$group, $attr| {
  group { $group :
    ensure => $attr["ensure"],
    gid    => $attr["gid"],
  }
}

```

# ユーザ
次にユーザ作成の書き方です。

## 基本
ユーザを作成する場合、Puppetのマニフェストでuserリソースで定義します。
developer01ユーザを作る場合の例です。

```puppet:user01.pp
user { "developer01" :
  ensure     => "present",
  uid        => "1101",
  gid        => "developer",
  home       => "/home/developer01",
  managehome => "true",
  shell      => "/bin/bash",
  password   => '$6$aqc3cun1$QpzeHomBlMEcKmCOkeDa9VItfbzi4R.NTyLm7r7ak6Mc9oxtQSzBlfgFtvQcvBNkr/OEZMXXu6XegP1g/p67O1',
}

```

※例にある属性すべてを指定しなくてもユーザ作成はできますが、ユーザの設定を同じにする場合、指定が必要そうな属性をあげています。

- userの右側のタイトルに、ユーザ名を指定
- ensure属性に、presentを指定
- uid属性は、ユーザIDを指定
- gid属性は、グループIDを指定、グループ名でも可
- home属性は、ホームディレクトリを指定
- managehomeは、ユーザ新規作成時に、ホームディレクトリを作る(true)/作らない(false)
- shell属性は、ログインシェルを指定
- password属性は、パスワードを指定（暗号化された値）

なお、ensure属性にabsentを指定すると、ユーザの削除ができます。ただ、ユーザ削除する場合は慎重に。また、uidはユーザごとのユニークなIDなので、すでに別のユーザが同じUIDを使っているとエラーになります。

## パスワードの値
パスワードの値を平文でそのまま書くと（セキュリティ的にも）だめなので、**password属性に指定する値は暗号化したパスワードです。**パスワードの暗号化方法は、いくつかあります。ちなみに、同じパスワードでも暗号化するたびに結果が変わるので、**実際にPuppetを使ってユーザを作成後、そのパスワードでログインできるか確認した方が良いです。**
また、**暗号化後の値に、\$が含まれるので、属性値の右側は`(シングルクォート)で囲みます。**

パスワードの暗号化方法です。

### grub-cryptコマンド
CentOS6であれば、grub-cryptコマンドで暗号化できます。
grubがインストールされていないとコマンドが使えないので、必要であればgrubをインストールします。ただ、**CentOS7ではgrub-cryptコマンドが使えません。**

```
# yum install grub

# grub-crypt --sha-512
Password: 
Retype password: 
$6$0.MRJr5Dfo5OUbQB$e2Jya9wl.mTV7Coa6F6zPaJF8fRAPXrWv3z4kmfXQNkLR15n7PSwNISwl16yCb232hQQNoGEEEjDjdhzsUGyB1
```

### 別サーバでパスワード設定して使う
grub-cryptコマンドが使えない場合、別のサーバでユーザを作って暗号化されたパスワードを得ることもできます。

- useraddコマンドでユーザを作成する
- 作ったユーザにpasswdコマンドでパスワードを設定
- puppet resource user <作ったユーザ名>でパスワード属性を表示

実行例です。※password属性の値だけ参考にする。

```
# useradd developer01

# passwd developer01
Changing password for user developer01.
New password: 
BAD PASSWORD: The password contains the user name in some form
Retype new password: 
passwd: all authentication tokens updated successfully.

# /opt/puppetlabs/bin/puppet resource user developer01
user { 'developer01':
  ensure           => 'present',
  gid              => '1000',
  home             => '/home/developer01',
  password         => '$6$SfMEeBwP$5gtgE/bSWA9d5gudbiqqrDBZCP2QYuSM.f7i4a.I8oi5ipNqUGOhpEjTKSM.eu7ajYVMJgnpopOCSSEeQ1gJS/',
  password_max_age => '99999',
  password_min_age => '0',
  shell            => '/bin/bash',
  uid              => '1000',
}
```

### たくさん作る場合はスクリプトで

複数ユーザのパスワードを暗号化する場合、Rubyスクリプトでも作れるみたいです。
※きちんと作れているかちょっと不安なので、間違っている場合はすみません。

```rb:mycrypt.rb
require 'securerandom'

# 暗号化するパスワードを配列で列挙(例なので簡単なパスワードです)
passwords = [
  'password',
  'developer01',
  'tester01',
]

passwords.each do |password|
  puts '----- ' + password
  puts password.crypt('$6$' + SecureRandom.random_number(36 ** 8).to_s(36))
end

```

実行例です。

```
# /opt/puppetlabs/puppet/bin/ruby mycrypt.rb
----- password
$6$929en8b5$e/4HLhCf7jemK6fpFEcGLOGNm2yKVLSWzxOMJK8WE/PLT8WPHPShIEaJ8u7pNx/13ZlzBY0/WisDmgrB3aZ8K/
----- developer01
$6$aqc3cun1$QpzeHomBlMEcKmCOkeDa9VItfbzi4R.NTyLm7r7ak6Mc9oxtQSzBlfgFtvQcvBNkr/OEZMXXu6XegP1g/p67O1
----- tester01
$6$uef4i20k$pUPeT97sshv76m1nz7MRsQPQAdZ4FdZ2KmOU3eYCa2SBAliksrmln.sR7YTkRsDMRxb8LPCdwSsgbss/5i6n30
```

## 複数ユーザを作る
複数のユーザを作る場合の書き方です。

### シンプルに列挙する
userリソースを作りたいユーザ分書けば、複数のユーザを作る定義になります。シンプルな方法です。

```puppet:user02.pp
user { "developer01" :
  ensure     => "present",
  uid        => "1101",
  gid        => "developer",
  home       => "/home/developer01",
  managehome => "true",
  shell      => "/bin/bash",
  password   => '$6$aqc3cun1$QpzeHomBlMEcKmCOkeDa9VItfbzi4R.NTyLm7r7ak6Mc9oxtQSzBlfgFtvQcvBNkr/OEZMXXu6XegP1g/p67O1',
}

user { "tester01" :
  ensure     => "present",
  uid        => "1201",
  gid        => "tester",
  home       => "/home/tester01",
  managehome => "true",
  shell      => "/bin/bash",
  password   => '$6$uef4i20k$pUPeT97sshv76m1nz7MRsQPQAdZ4FdZ2KmOU3eYCa2SBAliksrmln.sR7YTkRsDMRxb8LPCdwSsgbss/5i6n30',
}

```

### ハッシュでループ
列挙が面倒な場合は、ハッシュでユーザと属性を設定して、ハッシュでループさせる書き方もできます。Rubyぽい書き方です。**このループの文法は、Puppet4.xから使えます。**
同じ属性が縦に並んでい方が、編集は楽なはず…

```puppet:user03.pp
$users_hash = {
  "developer01" => {"ensure" => "present", "uid" => "1101", "gid" => "developer", "home" => "/home/developer01", "managehome" => "true", "shell" => "/bin/bash", "password" => '$6$aqc3cun1$QpzeHomBlMEcKmCOkeDa9VItfbzi4R.NTyLm7r7ak6Mc9oxtQSzBlfgFtvQcvBNkr/OEZMXXu6XegP1g/p67O1'},
  "tester01"    => {"ensure" => "present", "uid" => "1201", "gid" => "tester",    "home" => "/home/tester01",    "managehome" => "true", "shell" => "/bin/bash", "password" => '$6$uef4i20k$pUPeT97sshv76m1nz7MRsQPQAdZ4FdZ2KmOU3eYCa2SBAliksrmln.sR7YTkRsDMRxb8LPCdwSsgbss/5i6n30'},
}

$users_hash.each |$user, $attr| {
  user { $user :
    ensure     => $attr["ensure"],
    uid        => $attr["uid"],
    gid        => $attr["gid"],
    home       => $attr["home"],
    managehome => $attr["managehome"],
    shell      => $attr["shell"],
    password   => $attr["password"],
  }
}

```

## その他属性
その他属性で、比較的使いそうなものを紹介します。

### サブグループ設定

同じユーザを、複数グループに所属させたい場合は、サブグループの設定をします。
例えば、開発者は、開発者グループとテスターグループなど。

サブグループは、groups属性で指定します。複数指定する場合もあるので配列で指定できます。

```puppet:user04.pp
user { "developer01" :
  ensure     => "present",
  uid        => "1101",
  gid        => "developer",
  groups     => ["tester"],
  home       => "/home/developer01",
  managehome => "true",
  shell      => "/bin/bash",
  password   => '$6$aqc3cun1$QpzeHomBlMEcKmCOkeDa9VItfbzi4R.NTyLm7r7ak6Mc9oxtQSzBlfgFtvQcvBNkr/OEZMXXu6XegP1g/p67O1',
}

```

### ユーザの有効期限設定

ユーザの有効期限を設定する場合は、expiry属性を設定します。
2016/12/31の場合、2016-12-31で設定。

```puppet:user05.pp
user { "developer01" :
  ensure     => "present",
  uid        => "1101",
  gid        => "developer",
  home       => "/home/developer01",
  managehome => "true",
  shell      => "/bin/bash",
  password   => '$6$aqc3cun1$QpzeHomBlMEcKmCOkeDa9VItfbzi4R.NTyLm7r7ak6Mc9oxtQSzBlfgFtvQcvBNkr/OEZMXXu6XegP1g/p67O1',
  expiry     => "2016-12-31",
}

```

### パスワードの期限設定

ユーザに対して定期的にパスワード変更してもらいたい場合、パスワードの有効期限を設定します。

- password_max_age : パスワードの有効期限の日数
- password_min_age : パスワード再変更を、変更後何日後にできるようにするか

※目的に応じて設定。片方だけでも可。

```puppet:user06.pp
user { "developer01" :
  ensure     => "present",
  uid        => "1101",
  gid        => "developer",
  home       => "/home/developer01",
  managehome => "true",
  shell      => "/bin/bash",
  password_max_age => '90',
  password_min_age => '1',
}

```

# 参考
groupリソースの詳しい情報は、下記参照です。

- https://docs.puppet.com/puppet/latest/reference/type.html#group

userリソースの詳しい情報は、下記参照です。

- https://docs.puppet.com/puppet/latest/reference/type.html#user