Ansible 剧本配置 SSH 互信密钥的认证
原理
这个脚本生成 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
- 使用
ssh-keygen命令生成了一对SSH密钥,包括私钥和公钥。私钥被保存在/root/.ssh/access_authen文件中,而公钥则保存在/root/.ssh/access_authen.pub文件中。 - 通过使用
fetch模块,将公钥文件从远程主机复制到本地主机的/tmp目录下。 - 使用
cat命令提取本地主机上复制的公钥文件内容,并将结果保存在public_key_output变量中。 - 检查目标主机上是否存在
/root/.ssh/authorized_keys文件,如果不存在,则使用file模块创建一个空的authorized_keys文件。 - 使用
lineinfile模块将公钥内容追加到目标主机的authorized_keys文件中,确保每个公钥以新行的形式添加。 - 最后,通过使用
shell模块,在本地主机上删除临时文件/tmp/access_authen-*。
使用
- 如果没有
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
- 创建
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
- 测试
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"}
- 执行
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:~#