0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Ansible Playbookで連番の複数ユーザーを一括作成する

Last updated at Posted at 2020-04-24

はじめに

Ansible Playbookでユーザーを複数作成する場合、あらかじめリスト変数にユーザー名、UID、グループ名等々を設定しておき、userモジュール+ループで一括作成、というのが通常かと思います。

ただ、あまりに大量のユーザーを作成する場合、そのリスト変数を用意するのが面倒です。

連番のユーザーをサクッと作成するPlaybookがあればいいのに、と思っていたところ、ようやくそれなりのものが出来たので、記念に残します。

想定ケース

例えば開発者向けなど、連番のユーザーを大量に作成する。

環境

VirtualBox (+ vagrant)
CentOS 7.7
ansible 2.9.6

Playbook

今回も記事を分かりやすくするため、1本のPlaybookusercreate.ymlに全て記載します。(ベストプラクティスを知らないわけではないです。念の為。)

まず冒頭で、各種変数を準備します。この例では、01から20までの連番のユーザーを作成します。詳しい説明はコメントを参照ください。

usercreate.yml
---
- name: Create many user
  hosts: localhost
  vars:
    # 1から20までをカンマで繋いだ文字列を作ります。最後はカンマで終わりますが、後でなんとかします。
    user_num_data: "{% for n in range(20) %}{{n+1}},{% endfor %}"
    # 上で作った変数をカンマで分割して、リスト変数に登録します。最後の要素は空ですが、後でなんとかします。
    user_num: "{{ user_num_data.split(',') }}"
    # 作成するユーザーの初期パスワードです
    initialpw: zaq12wsx
    # UID/GIDのプレフィックスです。5000番台を使います。
    pre_id: 50
    # ユーザー名のプレフィックスです。
    pre_name: devuser
    # 作成するユーザー全員を登録する共通グループです。
    common_group: devgroup

続いてタスク定義です。まずは共通グループを作成します。ユーザーで使用しない0番、GID=5000で作成します。

usercreate.yml
  tasks:
    - name: Common group is created
      group:
        name: '{{ common_group }}'
        gid: '{{ pre_id }}00'
        state: present

次は作成するユーザーごとのグループを作成します。ループするリスト変数を'{{ user_num[:-1] }}'とすることで、最後の空要素を除外します。そして、ユーザー名などに連番を使用する際、2桁に揃えるために、item.zfill(2)とします。

usercreate.yml
    - name: Groups are created
      group:
        name: '{{ pre_name }}{{ item.zfill(2) }}'
        gid: '{{ pre_id }}{{ item.zfill(2) }}'
        state: present
      with_items:
        - '{{ user_num[:-1] }}'

最後にユーザーを作成します。

usercreate.yml
    - name: Users are created
      user:
        name: '{{ pre_name }}{{ item.zfill(2) }}'
        group: '{{ pre_name }}{{ item.zfill(2) }}'
        groups: '{{ pre_name }}{{ item.zfill(2) }}, {{ common_group }}'
        uid: '{{ pre_id }}{{ item.zfill(2) }}'
        state: present
        password: "{{ initialpw | password_hash('sha512') }}"
        update_password: on_create
      with_items:
        - '{{ user_num[:-1] }}'
      register: usercreated

おまけで、初期パスワードの変更を促すために、パスワードを無効にします。前のタスクで、ユーザーが作成された時にのみ実行されるようにwhenで条件を指定します。あと、ansible-playbook実行時の出力を抑えるために、loop_controlのlabelを指定します。

usercreate.yml
    - name: Passwords are expired
      shell: |
        passwd -e '{{ item.invocation.module_args.name }}'
      with_items:
        - '{{ usercreated.results }}'
      when:
        - item.changed
        - item.invocation.module_args.state == "present"

      loop_control:
        label: "{{ item.invocation.module_args.name }}"

実行例

普通の実行結果です。

$ ansible-playbook -i inventories/test usercreate.yml 

PLAY [Create many user] ************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [localhost]

TASK [Common group is created] *****************************************************************************************
changed: [localhost]

TASK [Groups are created] **********************************************************************************************
changed: [localhost] => (item=1)
changed: [localhost] => (item=2)
changed: [localhost] => (item=3)
changed: [localhost] => (item=4)
changed: [localhost] => (item=5)
changed: [localhost] => (item=6)
changed: [localhost] => (item=7)
changed: [localhost] => (item=8)
changed: [localhost] => (item=9)
changed: [localhost] => (item=10)
changed: [localhost] => (item=11)
changed: [localhost] => (item=12)
changed: [localhost] => (item=13)
changed: [localhost] => (item=14)
changed: [localhost] => (item=15)
changed: [localhost] => (item=16)
changed: [localhost] => (item=17)
changed: [localhost] => (item=18)
changed: [localhost] => (item=19)
changed: [localhost] => (item=20)

TASK [Users are created] ***********************************************************************************************
changed: [localhost] => (item=1)
changed: [localhost] => (item=2)
changed: [localhost] => (item=3)
changed: [localhost] => (item=4)
changed: [localhost] => (item=5)
changed: [localhost] => (item=6)
changed: [localhost] => (item=7)
changed: [localhost] => (item=8)
changed: [localhost] => (item=9)
changed: [localhost] => (item=10)
changed: [localhost] => (item=11)
changed: [localhost] => (item=12)
changed: [localhost] => (item=13)
changed: [localhost] => (item=14)
changed: [localhost] => (item=15)
changed: [localhost] => (item=16)
changed: [localhost] => (item=17)
changed: [localhost] => (item=18)
changed: [localhost] => (item=19)
changed: [localhost] => (item=20)

TASK [Passwords are expired] *******************************************************************************************
changed: [localhost] => (item=devuser01)
changed: [localhost] => (item=devuser02)
changed: [localhost] => (item=devuser03)
changed: [localhost] => (item=devuser04)
changed: [localhost] => (item=devuser05)
changed: [localhost] => (item=devuser06)
changed: [localhost] => (item=devuser07)
changed: [localhost] => (item=devuser08)
changed: [localhost] => (item=devuser09)
changed: [localhost] => (item=devuser10)
changed: [localhost] => (item=devuser11)
changed: [localhost] => (item=devuser12)
changed: [localhost] => (item=devuser13)
changed: [localhost] => (item=devuser14)
changed: [localhost] => (item=devuser15)
changed: [localhost] => (item=devuser16)
changed: [localhost] => (item=devuser17)
changed: [localhost] => (item=devuser18)
changed: [localhost] => (item=devuser19)
changed: [localhost] => (item=devuser20)

PLAY RECAP *************************************************************************************************************
localhost                  : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

/etc/passwdを見ると、綺麗に連番で作成されています。

$ grep devuser /etc/passwd
devuser01:x:5001:5001::/home/devuser01:/bin/bash
devuser02:x:5002:5002::/home/devuser02:/bin/bash
devuser03:x:5003:5003::/home/devuser03:/bin/bash
devuser04:x:5004:5004::/home/devuser04:/bin/bash
devuser05:x:5005:5005::/home/devuser05:/bin/bash
devuser06:x:5006:5006::/home/devuser06:/bin/bash
devuser07:x:5007:5007::/home/devuser07:/bin/bash
devuser08:x:5008:5008::/home/devuser08:/bin/bash
devuser09:x:5009:5009::/home/devuser09:/bin/bash
devuser10:x:5010:5010::/home/devuser10:/bin/bash
devuser11:x:5011:5011::/home/devuser11:/bin/bash
devuser12:x:5012:5012::/home/devuser12:/bin/bash
devuser13:x:5013:5013::/home/devuser13:/bin/bash
devuser14:x:5014:5014::/home/devuser14:/bin/bash
devuser15:x:5015:5015::/home/devuser15:/bin/bash
devuser16:x:5016:5016::/home/devuser16:/bin/bash
devuser17:x:5017:5017::/home/devuser17:/bin/bash
devuser18:x:5018:5018::/home/devuser18:/bin/bash
devuser19:x:5019:5019::/home/devuser19:/bin/bash
devuser20:x:5020:5020::/home/devuser20:/bin/bash

/etc/groupも同様。

$ grep dev /etc/group
devgroup:x:5000:devuser01,devuser02,devuser03,devuser04,devuser05,devuser06,devuser07,devuser08,devuser09,devuser10,devuser11,devuser12,devuser13,devuser14,devuser15,devuser16,devuser17,devuser18,devuser19,devuser20
devuser01:x:5001:devuser01
devuser02:x:5002:devuser02
devuser03:x:5003:devuser03
devuser04:x:5004:devuser04
devuser05:x:5005:devuser05
devuser06:x:5006:devuser06
devuser07:x:5007:devuser07
devuser08:x:5008:devuser08
devuser09:x:5009:devuser09
devuser10:x:5010:devuser10
devuser11:x:5011:devuser11
devuser12:x:5012:devuser12
devuser13:x:5013:devuser13
devuser14:x:5014:devuser14
devuser15:x:5015:devuser15
devuser16:x:5016:devuser16
devuser17:x:5017:devuser17
devuser18:x:5018:devuser18
devuser19:x:5019:devuser19
devuser20:x:5020:devuser20

パスワードもexpireされてます。

$ sudo chage -l devuser01
Last password change					: password must be changed
Password expires					: password must be changed
Password inactive					: password must be changed
Account expires						: never
Minimum number of days between password change		: 0
Maximum number of days between password change		: 99999
Number of days of warning before password expires	: 7

ユーザーが足らなくなったら、以下のrange(20)のところをrange(40)などとして、Playbookを再実行すれば、作成済みのユーザーには影響なく、追加分のみ作成してくれます。

user_num_data: "{% for n in range(20) %}{{n+1}},{% endfor %}"

これで、数十人のメンバーがいるチームが複数立ち上がっても、ドンとこい!です。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?