Ansibleを触ってみよう その1

By | 2022年8月1日

今回はUbuntu、Debian、RHEL、CentOS、Alma、Rockyと用意して実行してみます。
Ubuntu18.04,20.04,22.04、Debin9,10、CentOS7、AlmaLinux8,9、RockyLinux8,9、RHEL8と11種類のOSを用意しました。

Debianでsudoが実行できるよう準備

Debianを最小でインストールした場合はsudoがインストールされていないので
sudoをインストールして、sudoのグループに所属させます。

$ apt -y install sudo
$ usermod -aG sudo xxxxxx

パスワードなしでのSSHログイン準備

後でAnsibleでのパスワードログインもやっていきますが
通常のシーケンスである鍵交換をしていきます。

まず、サーバー側のSSH鍵を作成します。

$ cd ~/.ssh
$ ssh-keygen -t rsa -f id_rsa
$ chmod 600 ~/.ssh/id_rsa
$ chmod 700 ~/.ssh

鍵配布を行っていきます、
ここからクライアントの数だけループを行います。

$ ssh-copy-id 192.168.1.50
$ ssh 192.168.1.50
$ ssh-copy-id 192.168.1.51
$ ssh 192.168.1.51
.........................................

Playbookの準備

現時点ではロールを使いませんが
Ansbileのロールを作成します。

$ ansible-galaxy init --offline test
$ tree test
test
├── README.md
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
└── main.yml

鍵を登録したクライアントを記載します。

$ vi test/inventory
[dnf]
localhost
192.168.1.55
192.168.1.56
192.168.1.57
192.168.1.58
192.168.1.59
[apt]
192.168.1.50
192.168.1.51
192.168.1.52
192.168.1.53
192.168.1.54

登録したホストが認識されているか確認します。

$ ansible-inventory --graph -i test/inventory
@all:
|--@apt:
|  |--192.168.1.50
|  |--192.168.1.51
|  |--192.168.1.52
|  |--192.168.1.53
|  |--192.168.1.54
|--@dnf:
|  |--192.168.1.55
|  |--192.168.1.56
|  |--192.168.1.57
|  |--192.168.1.58
|  |--192.168.1.59
|  |--localhost
|--@ungrouped:

Ansible Vaultでパスワードを暗号化します

sudoに必要なパスワードを変数ansible_sudo_passに登録します。

$ cd test
$ mkdir vars/main
$ vi vars/main/sudo_pass.yml
ansible_sudo_pass: hogehoge

暗号化用のパスワードを記載します。
場所はどこでもいいのですが、.sshディレクトリに格納してます。

$ vi ~/.ssh/sudo_pass

ansible-vaultでsudo_pass.ymlで暗号化します。
@の前のsudoがvault-idになり、
@の後のファイル名がパスワード格納ファイルになります。

$ ansible-vault encrypt --vault-id sudo@~/.ssh/sudo_pass vars/main/sudo_pass.yml
Encryption successful

sudo_pass.ymlが暗号化されたことを確認します。

$ cat vars/main/sudo_pass.yml
$ANSIBLE_VAULT;1.2;AES256;sudo
36633337366438316536346238633862666431653066303537663836666236626232376631306262
3239643862663036323232306238356232663836363430640a343137373135376262386436353033
65393763363963346232656536326136353239353435336565343530633964306464623432663661
3730643661613862370a326631613933343531306433616138343139363836633538323234643861
30303930373165316231623136326465343430313366656161383131666139363863383931356363
3936343530306432666337386135303630646564633064313261

Playbookの作成と実行(SSHパスワード不要、sudoパスワード入力不要)

各サーバにSSH鍵でログインして、sudoしてwhoamiを実行するPlaybookを作成します。
xxxxは任意のユーザに変えてください

$ vi test.yml
---
- name: test
  hosts: all
  user: xxxxxx
  become: true
  gather_facts: false
  vars_files:
  - vars/main/sudo_pass.yml
  tasks:
  - name: whoami
    command: whoami

実行します。場合によっては以下のエラーが起きるかもしれません。

$ ansible-playbook --vault-id sudo@~/.ssh/sudo_pass test.yml  -i inventory

fatal: [192.168.0.53]: FAILED! => {"ansible_facts": {}, "changed": false, "failed_modules": {"ansible.legacy.setup": {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "failed": true, "module_stderr": "Shared connection to 192.168.0.53 closed.\r\n", "module_stdout": "/bin/sh: 1: sudo: not found\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 127}}, "msg": "The following modules failed to execute: ansible.legacy.setup\n"}
fatal: [192.168.0.54]: FAILED! => {"ansible_facts": {}, "changed": false, "failed_modules": {"ansible.legacy.setup": {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "failed": true, "module_stderr": "Shared connection to 192.168.0.54 closed.\r\n", "module_stdout": "/bin/sh: 1: sudo: not found\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 127}}, "msg": "The following modules failed to execute: ansible.legacy.setup\n"}

Python3の実行エラー回避

対象のDebianのサーバで確認した所
原因は/usr/bin/python3が存在しないようです。

$ whereis python
python: /usr/bin/python /usr/bin/python3.7 /usr/bin/python3.7m /usr/bin/python2.7 /usr/lib/python3.7 /usr/lib/python2.7 /etc/python /etc/python3.7 /etc/python2.7 /usr/local/lib/python3.7 /usr/local/lib/python2.7 /usr/share/python /usr/share/man/man1/python.1.gz
$ whereis python
python: /usr/bin/python3.9 /usr/lib/python2.7 /usr/lib/python3.9 /etc/python3.9 /usr/local/lib/pyth

inventoryにPythonのパスを記載します。

$ vi inventory
[dnf]
localhost
192.168.1.55
192.168.1.56
192.168.1.57
192.168.1.58
192.168.1.59
[apt]
192.168.1.50
192.168.1.51
192.168.1.52
192.168.1.53 ansible_python_interpreter=/usr/bin/python3.7
192.168.1.54 ansible_python_interpreter=/usr/bin/python3.9

再度実行します。エラーが起きないはずです。

$ ansible-playbook --vault-id sudo@~/.ssh/sudo_pass test.yml  -i inventory

RoleでのPlaybookの作成(SSHパスワード入力、sudoパスワード不要)

今度はsudoが可能なスポットのユーザを作成します。
また、ロール化も行います。
今回はパスワードログインで行ってみます。
また、sudoができるようディストリビューションごとに異なるグループに所属させます。
また、ログが表示できるようhandlerで捕捉します。
特にエラー処理していないため実行ごとにパスワードハッシュが変わり常にchangedになります。

処理部分を記載

$ vi tasks/main.yml
---
# tasks file for test
- name: RedHat Create User
  user:
    user: test1
    group: wheel
    password: "{{ 'hogehoge'|password_hash('sha512') }}"
  when:
  - ansible_distribution != "Ubuntu"
  - ansible_distribution != "Debian"

- name: Debian Ubuntu Create User
  user:
    user: test1
    group: sudo
    password: "{{ 'hogehoge'|password_hash('sha512') }}"
  when:
  - ansible_distribution == "Ubuntu" or ansible_distribution == "Debian"

- name: User Check
  command: "id test1"
  notify: handler
  register: result

ハンドラーを記載します。

$ vi handlers/main.yml
---
# handlers file for test
- name: handler
  debug: var="result"

ロールを実行するPlaybookを記載します。

$ cd ../
$ vi test.yml
---
- name: test
  hosts: all
  become: true
  gather_facts: true

  roles:
  - test

varsのmain.ymlがあるとmainディレクトリを読み込まないため削除します。
今回は変数ファイルが一つなのでmain.ymlを暗号化する場合は本来必要ない処理になります。

$ rm -rf test/vars/main.yml

RoleでのPlaybookの実行(SSHパスワード入力、sudoパスワード不要)

実行を行います。vault-idを変数に埋め込んで実行することはどうにもうまくいきませんでした。

$ ansible-playbook --vault-id sudo@~/.ssh/sudo_pass test.yml -i test/inventory

sudoで昇格できるか先程のPlaybookでは確認していないため
必要に応じてログインしてsudoでスーパーユーザになれるか確認して下さい。
最初のPlaybookの実行ユーザをtest1に書き換えます。

$ cd test
$ vi test.yml
---
- name: test
  hosts: all
  user: test1
  become: true
  gather_facts: false
  vars_files:
  - vars/main/sudo_pass.yml
  tasks:
  - name: whoami
    command: whoami
    notify: handler
    register: result
  handlers:
  - name: handler
    debug: var="result"

-kでパスワード入力を求められるようにします。

$ ansible-playbook --vault-id sudo@~/.ssh/sudo_pass test.yml -i inventory -k
SSH password: hogehoge