2022年9月3日土曜日

AnsibleからLinuxサーバに接続するための事前準備をするPlaybookを作ってみた

AnsibleでLinuxサーバに接続する際には、事前作業が必要となる。この事前作業については、以下の記事に記載した。

必要な作業内容は以下フローの通りとなる。

この事前の作業自体も手間なので、Ansibleで自動化できないかと考えてみた。

RHEL系ディストリビューション(RHEL 8以前)では、rootによるSSHログインがデフォルトで有効であり、Ansible用のユーザがなくともrootユーザを用いることでAnsibleから接続することが可能となる。そこで、Ansibleの事前作業はrootユーザにて接続して実行し、事前作業完了後は、Ansible用のユーザにて接続できるようにする。

本記事では、AnsibleからLinuxサーバに接続するための事前準備をするPlaybookを作ってみたので紹介する。

環境

今回の動作検証はAlmaLinux 8に対して実施した。ただし、Red Hat系のディストリビューションであるCentOSやRocky Linuxなどでも同様の手順で構築できるだろう。

  • OS : AlmaLinux 8.5
  • Ansible : ansible [core 2.13.1]

Playbookの説明

Playbookのファイルの記載内容は大きく以下のように構成される。

設定項目 説明
hosts 実行対象のサーバを記載する。サーバのリストは別ファイルで作成し、そのファイルの中で実行する対象のサーバやグループを指定する。
vars 変数を記載する。ここで記載した変数は{{ 変数名 }}という形で参照できる。また、変数は配列して複数の要素を持たせることもできる。
tasks Ansibleで実行するメインの処理を記載する。
handlers Ansibleでメイン処理実行状況に応じて実行する事後処理を記載する。例えば、設定ファイル更新がされた場合 (実行結果がchangedの場合) は設定反映のためにサービス再起動を行うといった使い方をする。今回のPlaybookではSSHD設定後のサービス再起動の処理を記載する。

vars

変数は以下表の通り設定する。

変数 説明
ansible_user rootを指定。
ansible_password rootのパスワードを平文またはAnsible Vaultで暗号化して指定する。
os_user.name 作成するAnsible接続用ユーザ名を指定する。今回はansibleuserという名前でユーザを作成する。
os_user.uid ansibleuserを作成する際のUIDを指定する。今回は2001を指定する。
os_user.password Ansible接続用ユーザに指定するパスワードを指定する。パスワードは平文ではなく暗号化されたものを記載する。作成方法は複数あるようだが、ansibleuserユーザを作成済みのサーバがある場合は、そのサーバの/etc/shadowから確認すると手っ取り早い。
control_node_ssh_key 事前にAnsibleコントロールノードにてssh-keygenコマンドで作成したSSH公開鍵である~/.ssh/id_rsa.pubの内容をそのまま指定する。

実際のPlaybookの抜粋を以下に記載する。SSH公開鍵はかなり長い文字列となるが、特に気にならなければ1行で記載しても問題ない。気になる場合は、ダブルクォートで囲んで\を末尾に記載することで、改行して記載することができる。

  vars:
    ansible_user: root
    ansible_password: [rootのパスワード]

    os_user:
      name: ansibleuser
      uid: 2001
      password: '$6$7yLTtwuuOp/T$P06CVjt/yz13CCnS2RDcXXMn/aFDng1n1VWXXnZ7asHR13AOXXqtbEKLprEHphmLjJuOtXXorUYWRprxNhAE2A0'

    control_node_ssh_key: "\
          ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCo/wii2sMw08gntc6OREkVvuuZSpiSUBULmksMdKXAnTqyndaUWDuuzm7hT78GAAAAFCL0/1TlAAAA44QMD5rOtkBQmR\
                    ~(中略)~
          AAAAA1+VbxBBBBy2FATUts9dqFaNpjg9cCt5my3nZe9x8UEXZZiP8ye/7Wev6lHSl2wVU7NPL5N08pCP4qV+MFEIhCcw7T72nAL01W8e4Woz0AwN7QRgKolQzS+z5PuYGFU\
          4LTbEEEEO1eUsOxGFFFFSVHYQM= root@t1025alma"

tasks

タスクは以下表の通りとなる。

タスク名 モジュール 設定
Create ansibleuser user Ansible接続用ユーザを作成。
Add /etc/sudoers lineinfile Ansible接続用ユーザのsudo設定を追加。validatevisudoによる構文チェックをするように構成している。
Copy ssh key lineinfile AnsibleコントロールノードのSSH公開鍵を実行対象サーバのAnsible接続用ユーザのauthorized_keysに追加。
Set sshd setting (PermitRootLogin yes -> no) lineinfile SSHDのPermitRootLoginの設定値を更新し、rootユーザのSSHログインを無効化する。
Check ping by ansible ping module ping Ansible接続用ユーザを用いて、Ansibleより接続ができることを確認する。このタスクはAnsible接続用ユーザで実行する必要があるため、varsを指定しansible_userの値を上書きしている。実行結果は「Show ping result」のタスクで表示する。

実際のPlaybookの記載内容は後述する。

handlers

ハンドラーは以下表の通りとなる。

タスク名 モジュール 設定
Restart sshd service SSHDの設定ファイル修正後にサービスを再起動する。

実際のPlaybookの記載内容は後述する。

Playbook全文

実際のPlaybook全文を以下に記載する。

---
- name: Setup linux ansible settings
  gather_facts: false
  hosts: linux_servers

  vars:
    ansible_user: root
    ansible_password: [rootのパスワード]

    os_user:
      name: ansibleuser
      uid: 2001
      password: '$6$7yLTtwuuOp/T$P06CVjt/yz13CCnS2RDcXXMn/aFDng1n1VWXXnZ7asHR13AOXXqtbEKLprEHphmLjJuOtXXorUYWRprxNhAE2A0'

    control_node_ssh_key: "\
          ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCo/wii2sMw08gntc6OREkVvuuZSpiSUBULmksMdKXAnTqyndaUWDuuzm7hT78GAAAAFCL0/1TlAAAA44QMD5rOtkBQmR\
                    ~(中略)~
          AAAAA1+VbxBBBBy2FATUts9dqFaNpjg9cCt5my3nZe9x8UEXZZiP8ye/7Wev6lHSl2wVU7NPL5N08pCP4qV+MFEIhCcw7T72nAL01W8e4Woz0AwN7QRgKolQzS+z5PuYGFU\
          4LTbEEEEO1eUsOxGFFFFSVHYQM= root@t1025alma"

  tasks:
    # Ansible実行用ユーザ作成
    - name: Create ansibleuser
      ansible.builtin.user:
        name: "{{ os_user.name }}"
        uid: "{{ os_user.uid }}"
        password: "{{ os_user.password }}"
        state: present

    # sudo設定
    - name: Add /etc/sudoers
      ansible.builtin.lineinfile:
        path: /etc/sudoers
        line: '{{ os_user.name }} ALL=(root) NOPASSWD:ALL'
        state: present
        validate: visudo -cf %s

    # SSH公開鍵をコピー
    - name: Copy ssh key
      ansible.builtin.lineinfile:
        path: /home/{{ os_user.name }}/.ssh/authorized_keys
        line: "{{ control_node_ssh_key }}"
        owner: "{{ os_user.name }}"
        group: "{{ os_user.name }}"
        mode: '0600'
        create: true
        state: present

    # rootによるSSHログイン拒否
    - name: Set sshd setting (PermitRootLogin yes -> no)
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^PermitRootLogin'
        line: 'PermitRootLogin no'
      become: true
      notify: Restart sshd

    # 接続確認
    - name: Check ping by ansible ping module
      ansible.builtin.ping:
      changed_when: false
      register: result
      vars:
        ansible_user: "{{ os_user.name }}"

    - name: Show ping result
      ansible.builtin.debug:
        msg: "{{ result }}"

  handlers:
    # SSHDサービス再起動
    - name: Restart sshd
      ansible.builtin.service: name=sshd state=restarted
      become: true
      changed_when: false

実行結果

実際にPlaybookを実行した結果は以下となる。Show ping resultにてpongが返ってきていれば問題ない。

# ansible-playbook -i hosts -l t1193alma linux/setup_linux_ansible_settings.yml 

PLAY [Setup linux ansible settings] ********************************************************************************

TASK [Create ansibleuser] ******************************************************************************************
changed: [t1193alma]

TASK [Add /etc/sudoers] ********************************************************************************************
changed: [t1193alma]

TASK [Copy ssh key] ************************************************************************************************
changed: [t1193alma]

TASK [Set sshd setting (PermitRootLogin yes -> no)] ****************************************************************
changed: [t1193alma]

TASK [Check ping by ansible ping module] ***************************************************************************
ok: [t1193alma]

TASK [Show ping result] ********************************************************************************************
ok: [t1193alma] => {
    "msg": {
        "changed": false,
        "failed": false,
        "ping": "pong"
    }
}

RUNNING HANDLER [Restart sshd] *************************************************************************************
ok: [t1193alma]

PLAY RECAP *********************************************************************************************************
t1193alma                  : ok=7    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

なお、本Playbook実行後、rootによるSSHログインは拒否されるようになるため、次回以降は本Playbookは処理を実行することができなくなる。
※厳密には、Playbook実行時にSSHの接続情報がキャッシュされるため、実行後60秒以内であればrootユーザによる本Playbookの再実行は可能となる。

# ansible-playbook -i hosts -l t1193alma linux/setup_linux_ansible_settings.yml 

PLAY [Setup linux ansible settings] **********************************************************************************************************************

TASK [Create ansibleuser] ********************************************************************************************************************************
fatal: [t1193alma]: UNREACHABLE! => {"changed": false, "msg": "Invalid/incorrect password: Permission denied, please try again.", "unreachable": true}

PLAY RECAP ***********************************************************************************************************************************************
t1193alma                  : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   

以上で、AnsibleからLinuxサーバに接続するための事前準備をするPlaybookの説明は完了となる。

0 件のコメント:

コメントを投稿

人気の投稿