ansible playbook批量改ssh配置文件,远程用户Permission denied
最近手里的数百台服务器需要改/etc/ssh/sshd_config的参数,禁止root直接登陆,也就是说
[root@t0 ~]# cat /etc/ssh/sshd_config | grep Root #PermitRootLogin yes
得改成
[root@t1 ~]# cat /etc/ssh/sshd_config| grep ^PermitRoot PermitRootLogin no
一台台登上去改简直要死,ansible自动化运维工具听说还不错,之前就会用命令直接使用shell模块执行sed 替换配置文件里面的参数
[root@t0 ansible]# ansible all -b --become-method=su --become-user=root -m shell -a "sed 's/PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config" | grep -E "Root|10.0" [WARNING]: Consider using the replace, lineinfile or template module rather than running sed. If you need to use command because replace, lineinfile or template is insufficient you can add warn=False to this command task or set command_warnings=False in ansible.cfg to get rid of this message. 10.0.0.52 | CHANGED | rc=0 >> # $OpenBSD: sshd_config,v 1.93 2014/01/10 05:59:19 djm Exp $ PermitRootLogin no # the setting of "PermitRootLogin without-password". 10.0.0.53 | CHANGED | rc=0 >> # $OpenBSD: sshd_config,v 1.93 2014/01/10 05:59:19 djm Exp $ PermitRootLogin no # the setting of "PermitRootLogin without-password".
大概看个效果,这样做不仅效率低,而且你不能保证每台服务器的配置文件都是
#PermitRootLogin yes
也有可能是PermitRootLogin yes
所以不一定能达到自己的要求
然后根据提示信息,我看到了
replace, lineinfile template这三个模块
感兴趣的朋友可以自行研究一下
我今天用的是playbook用正则表达式匹配要更改的项
首先自己写一个playbook
[root@t0 playbook]# cat change_ssh.yml --- - hosts: test gather_facts: false # become: yes # become_method: su remote_user: root tasks: - name: "change file" lineinfile: path: /etc/ssh/sshd_config regexp: '^PermitRootLogin' line: 'PermitRootLogin yes' state: present # notify: restart sshd # handlers: # - name: restart sshd # service: name=sshd state=restarted
之前写的是没有注释的那些,注释的内容是我后来加上去的,待会再解释注释的意思
然后我的hosts文件
[root@t0 playbook]# cat ../hosts #[localhost] #127.0.0.1 [test] 10.0.0.52 10.0.0.53 [test:vars] ansible_ssh_pass=123456 ansible_ssh_user=test ansible_become_pass=123456
执行以下命令
[root@t0 playbook]# ansible-playbook change_ssh.yml PLAY [test] ************************************************************************************************************ TASK [change file] ***************************************************************************************************** fatal: [10.0.0.53]: FAILED! => {"changed": false, "module_stderr": "Shared connection to 10.0.0.53 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/test/.ansible/tmp/ansible-tmp-1555555638.07-154814815296297/AnsiballZ_lineinfile.py\", line 113, in <module>\r\n _ansiballz_main()\r\n File \"/home/test/.ansible/tmp/ansible-tmp-1555555638.07-154814815296297/AnsiballZ_lineinfile.py\", line 105, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/home/test/.ansible/tmp/ansible-tmp-1555555638.07-154814815296297/AnsiballZ_lineinfile.py\", line 48, in invoke_module\r\n imp.load_module('__main__', mod, module, MOD_DESC)\r\n File \"/tmp/ansible_lineinfile_payload_1q9ATP/__main__.py\", line 524, in <module>\r\n File \"/tmp/ansible_lineinfile_payload_1q9ATP/__main__.py\", line 515, in main\r\n File \"/tmp/ansible_lineinfile_payload_1q9ATP/__main__.py\", line 257, in present\r\nIOError: [Errno 13] Permission denied: '/etc/ssh/sshd_config'\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1} fatal: [10.0.0.52]: FAILED! => {"changed": false, "module_stderr": "Shared connection to 10.0.0.52 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/test/.ansible/tmp/ansible-tmp-1555555638.06-7599860498373/AnsiballZ_lineinfile.py\", line 113, in <module>\r\n _ansiballz_main()\r\n File \"/home/test/.ansible/tmp/ansible-tmp-1555555638.06-7599860498373/AnsiballZ_lineinfile.py\", line 105, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/home/test/.ansible/tmp/ansible-tmp-1555555638.06-7599860498373/AnsiballZ_lineinfile.py\", line 48, in invoke_module\r\n imp.load_module('__main__', mod, module, MOD_DESC)\r\n File \"/tmp/ansible_lineinfile_payload_5xlcxo/__main__.py\", line 524, in <module>\r\n File \"/tmp/ansible_lineinfile_payload_5xlcxo/__main__.py\", line 515, in main\r\n File \"/tmp/ansible_lineinfile_payload_5xlcxo/__main__.py\", line 257, in present\r\nIOError: [Errno 13] Permission denied: '/etc/ssh/sshd_config'\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1} to retry, use: --limit @/etc/ansible/playbook/change_ssh.retry PLAY RECAP ************************************************************************************************************* 10.0.0.52 : ok=0 changed=0 unreachable=0 failed=1 10.0.0.53 : ok=0 changed=0 unreachable=0 failed=1
结果是失败的,根据报错信息
IOError: [Errno 13] Permission denied: '/etc/ssh/sshd_config'
怀疑是权限的问题,因为根据我的hosts文件,默认是普通用户test去执行,所以在playbook里面加上两行
# become: yes # become_method: su
意思就是,我ansible远程操作的时候,用户使用的时管理员的权限,然后再次执行
[root@t0 playbook]# ansible-playbook change_ssh.yml PLAY [test] ************************************************************************************************************ TASK [change file] ***************************************************************************************************** changed: [10.0.0.52] changed: [10.0.0.53] PLAY RECAP ************************************************************************************************************* 10.0.0.52 : ok=1 changed=1 unreachable=0 failed=0 10.0.0.53 : ok=1 changed=1 unreachable=0 failed=0
查看远程主机的配置文件
[root@t1 ~]# cat /etc/ssh/sshd_config| grep ^PermitRoot PermitRootLogin no
说明已经改成功了,但是如果配置文件有其他的设置,我们还需要其他的正则,而且sshd的配置文件改完之后需要重启才能生效,所以需要一个触发器,playbook需要做一下调整
--- #- hosts: 'test:!c2'
- hosts: c2
#- hosts: "`hosts`" gather_facts: false become: yes become_method: su remote_user: root tasks: - name: 'change sshd_config' lineinfile: dest: /etc/ssh/sshd_config regexp: "{{ item.regexp }}" line: "{{ item.line }}" state: present with_items: #In this way # - { regexp: "^#PermitRootLogin yes",line: "PermitRootLogin no" } #or # - regexp: "^#PermitRootLogin yes" # line: "PermitRootLogin no" #Both methods have the same effect - { regexp: "PermitRootLogin yes",line: "PermitRootLogin no" } notify: restart sshd handlers: - name: restart sshd service: name=sshd state=restarted
总结:1. ansible如果hosts文件写的ansible_user时普通用户的时候,远程操作需要管理员权限,需要become的
become: yes become_method: su
或者是
become: yes become_method: sudo remote_user: test
2. 执行完操作之后,利用触发器notify重启sshd服务
3. 需要继续学习,谢谢