Ansible playbookでのroleごとのユーザ切替を試す

こんにちは、インフラ担当の天津です。今日はAnsibleでの小ネタをご紹介します。

TL;DR

roleごとにユーザを切り替えが可能かを調べ、可能であることを確認しました。

モチベーション

ユーザ作成とそのユーザでの構築作業を実施したいことがありましたので調べました。
例えば下記のようの状況です。

  • ec2-userで接続
  • rootでansible実行用ユーザを作成
  • 以降の処理はansible実行用ユーザで実施する

やってみた

マニュアルを読む

公式マニュアルを参照します。
https://docs.ansible.com/ansible/latest/user_guide/become.html
変数を指定することで設定できそうです。

実装してみる

一回目

下記のようなplaybookを作成してみました。
ansible実行用ユーザをwheelグループに作成します。
パスワードやssh公開鍵も設定します。(値は適当なものです)

sample-playbook.yml

-
  hosts: sample
  roles:
    - role: adduser
      vars:
        - ansible_become: yes
        - ansible_become_user: root
        - uid: 444
        - pub_key: hogehoge
    - role: test-role
      vars:
        - ansible_become: yes
        - ansible_become_user: ansible

roles/adduser/tasks/main.yml

--
- name: user create
  user:
    name: ansible
    group: wheel
    system: yes
    uid: {{uid}}
    password: "hogehoge"
- name: set authorized_keys
  authorized_key:
    user: ansible
    state: present
    key: {{pub_key}}

test-role/tasks/main.yml

---
# tasks file for test-role
- name: setup
  setup:
- name: sample
  shell: echo `id`

ロールはadduserとtest-roleです。
adduserロールでansible実行用ユーザを作成し、test-roleはidコマンドの結果をechoするものです。
EC2を対象にして、動かしてみましょう。

$ ansible-playbook --private-key ~/.ssh/hoge.pem -u ec2-user -i inventory/production sample-playbook.yml -v
PLAY [sample] ********************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************************************************************************************************************************************
fatal: [ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com]: FAILED! => {"msg": "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 1, err: chown: ユーザ指定が不正: `ansible'\n}). For information on working around this, see https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user"}
PLAY RECAP ***********************************************************************************************************************************************************************************************************************************
ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com : ok=0    changed=0    unreachable=0    failed=1

Gathering Factsでエラーになりました。
ユーザ指定が不正と言われています。
これは存在しないユーザをbecome_userで指定しているからと思われます。

二回目

ではGathering Factsをオフにしてみましょう。

sample-playbook.yml

-
  hosts: sample
  gather_facts: no
  roles:
    - role: adduser
      vars:
        - ansible_become: yes
        - ansible_become_user: root
        - uid: 444
        - pub_key: "ssh-rsa hogehoge"
    - role: test-role
      vars:
        - ansible_become: yes
        - ansible_become_user: ansible

実行してみます。

$ ansible-playbook --private-key ~/.ssh/hoge.pem -u ec2-user -i inventory/production sample-playbook.yml -v
PLAY [sample] ********************************************************************************************************************************************************************************************************************************
TASK [adduser : user create] *****************************************************************************************************************************************************************************************************************
changed: [ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com] => {"changed": true, "comment": "", "create_home": true, "group": 10, "home": "/home/ansible", "name": "ansible", "password": "NOT_LOGGING_PASSWORD", "shell": "/bin/bash", "state": "present", "system": true, "uid": 444}
TASK [adduser : set authorized_keys] *********************************************************************************************************************************************************************************************************changed: [ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com] => {"changed": true, "comment": null, "exclusive": false, "follow": false, "key": "ssh-rsa hogehoge", "key_options": null, "keyfile": "/home/ansible/.ssh/authorized_keys", "manage_dir": true, "path": null, "state": "present", "unique": false, "user": "ansible", "validate_certs": true}
TASK [test-role : sample] ********************************************************************************************************************************************************************************************************************
 [WARNING]: Module remote_tmp /home/ansible/.ansible/tmp did not exist and was created with a mode of 0700, this may cause issues when running as another user. To avoid this, create the remote_tmp dir with the correct permissions
manually
changed: [ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com] => {"changed": true, "cmd": "echo `id`", "delta": "0:00:00.003924", "end": "2018-11-20 02:24:54.110334", "rc": 0, "start": "2018-11-20 02:24:54.106410", "stderr": "", "stderr_lines": [], "stdout": "uid=444(ansible) gid=10(wheel) groups=10(wheel)", "stdout_lines": ["uid=444(ansible) gid=10(wheel) groups=10(wheel)"]}
PLAY RECAP ***********************************************************************************************************************************************************************************************************************************
ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com : ok=4    changed=3    unreachable=0    failed=0

最後まで実行されましたがWARNINGが出てしまいました。
Ansibleは実行先にマシンにスクリプトファイルを送って実行するのでその際の置き場所が無いので出ています。
解決策としては下記がありますが、今回はそのままとします。

  • remote_tmpで作成しておく
  • 初回のみなので何もしない

さて、これで終わりかと思いますが、このままですとfactsを使用できない状態です。  

三回目

factsをとるロールを追加してみましょう。
   fact-role/tasks/main.yml

---
# tasks file for fact-role
- name: setup
  setup:

setupモジュールを呼ぶだけです。
roleをplaybookに追加します。

sample-playbook.yml

-
  hosts: sample
  gather_facts: no
  roles:
    - role: adduser
      vars:
        - ansible_become: yes
        - ansible_become_user: root
        - uid: 444
        - pub_key: "ssh-rsa hogehoge"
    - role: fact-role
      vars:
        - ansible_become: yes
        - ansible_become_user: root
    - role: test-role
      vars:
        - ansible_become: yes
        - ansible_become_user: ansible
PLAY [sample] ********************************************************************************************************************************************************************************************************************************
TASK [adduser : user create] *****************************************************************************************************************************************************************************************************************
changed: [ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com] => {"changed": true, "comment": "", "create_home": true, "group": 10, "home": "/home/ansible", "name": "ansible", "password": "NOT_LOGGING_PASSWORD", "shell": "/bin/bash", "state": "present", "system": true, "uid": 444}
TASK [adduser : set authorized_keys] *********************************************************************************************************************************************************************************************************
changed: [ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com] => {"changed": true, "comment": null, "exclusive": false, "follow": false, "key": "ssh-rsa hogehoge", "key_options": null, "keyfile": "/home/ansible/.ssh/authorized_keys", "manage_dir": true, "path": null, "state": "present", "unique": false, "user": "ansible", "validate_certs": true}
TASK [fact-role : setup] *********************************************************************************************************************************************************************************************************************
ok: [ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com]
TASK [test-role : sample] ********************************************************************************************************************************************************************************************************************
 [WARNING]: Module remote_tmp /home/ansible/.ansible/tmp did not exist and was created with a mode of 0700, this may cause issues when running as another user. To avoid this, create the remote_tmp dir with the correct permissions
manually
changed: [ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com] => {"changed": true, "cmd": "echo `id`", "delta": "0:00:00.003836", "end": "2018-11-20 02:38:43.022517", "rc": 0, "start": "2018-11-20 02:38:43.018681", "stderr": "", "stderr_lines": [], "stdout": "uid=444(ansible) gid=10(wheel) groups=10(wheel)", "stdout_lines": ["uid=444(ansible) gid=10(wheel) groups=10(wheel)"]}
PLAY RECAP ***********************************************************************************************************************************************************************************************************************************
ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com : ok=4    changed=3    unreachable=0    failed=0

WARNINGは出ていますが、無事factsも取得できました。

まとめ

Ansibleでのroleごとのユーザ使い分けを試してみましたが、意外と簡単にできました。
varsに指定できるので、playbookではなくhost_vars/group_varsで指定したり、roleのdefaultに指定もできますね。
最後までお読みいただき有難うございました。