Ansible 剧本配置 SSH 互信密钥的认证

778 阅读3分钟

Ansible 剧本配置 SSH 互信密钥的认证

image.png

原理

这个脚本生成 SSH 密钥对,并将公钥添加到目标主机的 authorized_keys 文件中。这样,通过配置密钥认证,可以实现无需密码的 SSH 登录和自动化运维操作。

剧本

这个 Playbook 对实现集群管理或主备互访非常有用。

---
- name: Configure SSH key-based authentication
  hosts: all
  gather_facts: no

  vars:
    filename: "access_authen" # 默认是 "id_rsa"
    ssh_directory: "/root/.ssh"
    gen_keys_file: "{{ ssh_directory }}/{{ filename }}"
    pub_keys_file: "{{ ssh_directory }}/{{ filename }}.pub"
    authorized_keys_file: "{{ ssh_directory }}/authorized_keys"

  tasks:
    - name: Generate SSH Key Pair
      shell: yes | ssh-keygen -t rsa -N "" -C "{{ hostvars[inventory_hostname]['environment'] }}" -f "{{ gen_keys_file }}"
      register: ssh_keygen_output
      changed_when: ssh_keygen_output.stdout != ''

    - name: Fetch Public Key From Server
      fetch:
        src: "{{ pub_keys_file }}"
        dest: "/tmp/{{ filename }}-{{ inventory_hostname }}"
        flat: yes

    - name: Extract Public Key
      shell: "cat /tmp/{{ filename }}*"
      register: public_key_output
      connection: local
      run_once: true

    - name: Check If Authorized_Keys File Exists
      stat:
        path: "{{ authorized_keys_file }}"
      register: file_stat

    - name: Create Authorized_Keys File If Not Existing
      file:
        path: "{{ authorized_keys_file }}"
        state: touch
      when: file_stat.stat.exists == False

    - name: Append Public Key To Authorized_Keys File
      lineinfile:
        path: "{{ authorized_keys_file }}"
        line: "{{ public_key_output.stdout }}\n"

    - name: Clean Up Temporary Files
      shell: rm -rf /tmp/{{ filename }}*
      connection: local
      run_once: true
  1. 使用 ssh-keygen 命令生成了一对 SSH 密钥,包括私钥和公钥。私钥被保存在 /root/.ssh/access_authen 文件中,而公钥则保存在 /root/.ssh/access_authen.pub 文件中。
  2. 通过使用 fetch 模块,将公钥文件从远程主机复制到本地主机的 /tmp 目录下。
  3. 使用 cat 命令提取本地主机上复制的公钥文件内容,并将结果保存在 public_key_output 变量中。
  4. 检查目标主机上是否存在 /root/.ssh/authorized_keys 文件,如果不存在,则使用 file 模块创建一个空的 authorized_keys 文件。
  5. 使用 lineinfile 模块将公钥内容追加到目标主机的 authorized_keys 文件中,确保每个公钥以新行的形式添加。
  6. 最后,通过使用 shell 模块,在本地主机上删除临时文件 /tmp/access_authen-*

使用

  1. 如果没有 ansible.cfg,可以从 github dump 一份(我这里就随便写点配置):
root@AnsibleServer:/etc/ansible# cat ansible.cfg
[defaults]
inventory = /etc/ansible/hosts
remote_user = root
host_key_checking = False         # 注意:这个要关闭主机密钥检查
retry_files_enabled = False
command_warnings = False

[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False

[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s
pipelining = True
  1. 创建 inventory 文件:
root@AnsibleServer:/etc/ansible# cat hosts 
[all]
10.0.80.1 ansible_ssh_user=root ansible_ssh_port=10022 ansible_ssh_pass="Mo4#Qt4)Bf1}Vz0@" environment=master
10.0.80.2 ansible_ssh_user=root ansible_ssh_port=10022 ansible_ssh_pass="Yq0)Di9}Uu0-Vw7+" environment=slave
  1. 测试 ping 连通性:
root@AnsibleServer:/etc/ansible# ansible all -m ping -o
10.0.80.1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"}
10.0.80.2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"ping": "pong"}
  1. 执行 playbook 剧本:
# 下面是 fork 主机数量的并行进程数
root@AnsibleServer:/etc/ansible# ansible-playbook -i hosts -f $(ansible hdfs --list-hosts | grep -cP '\d\.+') setup_ssh_keys.yml 

PLAY [Configure SSH key-based authentication] ***********************************************************

TASK [Generate SSH Key Pair] ****************************************************************************
changed: [10.0.80.1]
changed: [10.0.80.2]

TASK [Fetch Public Key From Server] ******************************************************************
changed: [10.0.80.2]
changed: [10.0.80.1]

TASK [Extract Public Key] *******************************************************************************
changed: [10.0.80.1]

TASK [Check If Authorized_Keys File Exists] *****************************************************************************
ok: [10.0.80.2]
ok: [10.0.80.1]

TASK [Create Authorized_Keys File If Not Existing] ******************************************************************
skipping: [10.0.80.1]
changed:  [10.0.80.2]

TASK [Append Public Key To Authorized_Keys File] ***************************************************************************
changed: [10.0.80.1]
changed: [10.0.80.2]

TASK [Clean Up Temporary Files] ***************************************************************************
changed: [10.0.80.1]

PLAY RECAP **********************************************************************************************
10.0.80.1       : ok=6    changed=5    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
10.0.80.2       : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

验证

两台 Node 节点可实现免密互访。

root@Node02:~# ssh -i ~/.ssh/access_authen root@10.0.80.1 -p 10022
Linux Node01 5.19.0-0.deb11.2-amd64 #1 SMP PREEMPT_DYNAMIC Debian 5.19.11-1~bpo11+1 (2022-10-03) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Jun 16 20:49:27 2023 from 10.0.85.41
root@Node01:~#