【发布时间】:2022-01-08 01:56:25
【问题描述】:
我正在尝试让 playbook 运行一次以设置新用户并禁用 root ssh 访问。
目前,我通过两次申报所有库存来做到这一点。每个主机都需要一个以 root 用户访问的条目,用于创建新用户、设置 ssh 设置,然后禁用 root 访问。
然后,每个主机都需要另一个包含新用户的条目。
我目前的库存看起来像这样。目前只有一个主机,但如果库存更大,重复只会占用大量不必要的空间:
---
# ./hosts.yaml
---
all:
children:
master_roots:
hosts:
demo_master_root:
ansible_host: a.b.c.d # same ip as below
ansible_user: root
ansible_ssh_private_key_file: ~/.ssh/id_rsa_infra_ops
masters:
hosts:
demo_master:
ansible_host: a.b.c.d # same ip as above
ansible_user: infraops
ansible_ssh_private_key_file: ~/.ssh/id_rsa_infra_ops
有没有更简洁的方法来做到这一点?
这是一种反模式吗?它不是幂等的。如果以这样一种方式运行,即两次运行相同的剧本总是具有相同的输出 - “成功”或“没有变化”,那就太好了。
我正在使用 DigitalOcean,他们有一个功能可以在 VM 首次启动之前通过 bash 脚本完成此操作,但我更喜欢独立于平台的解决方案。
这是设置用户和 ssh 设置以及禁用 root 访问的剧本
---
# ./initial-host-setup.yaml
---
# References
# Digital Ocean recommended droplet setup script:
# - https://docs.digitalocean.com/droplets/tutorials/recommended-setup
# Digital Ocean tutorial on installing kubernetes with Ansible:
# - https://www.digitalocean.com/community/tutorials/how-to-create-a-kubernetes-cluster-using-kubeadm-on-debian-9
# Ansible Galaxy (Community) recipe for securing ssh:
# - https://github.com/vitalk/ansible-secure-ssh
---
- hosts: master_roots
become: 'yes'
tasks:
- name: create the 'infraops' user
user:
state: present
name: infraops
password_lock: 'yes'
groups: sudo
append: 'yes'
createhome: 'yes'
shell: /bin/bash
- name: add authorized keys for the infraops user
authorized_key: 'user=infraops key="{{item}}"'
with_file:
'{{ hostvars[inventory_hostname].ansible_ssh_private_key_file }}.pub'
- name: allow infraops user to have passwordless sudo
lineinfile:
dest: /etc/sudoers
line: 'infraops ALL=(ALL) NOPASSWD: ALL'
validate: visudo -cf %s
- name: disable empty password login for all users
lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^#?PermitEmptyPasswords'
line: PermitEmptyPasswords no
notify: restart sshd
- name: disable password login for all users
lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^(#\s*)?PasswordAuthentication '
line: PasswordAuthentication no
notify: restart sshd
- name: Disable remote root user login
lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin no'
notify: restart sshd
handlers:
- name: restart sshd
service:
name: sshd
state: restarted
此后的所有内容都将使用 masters 库存。
编辑
经过一些研究,我发现 AWS、GCP 和 DigitalOcean 可能通过 cloud-init 支持“初始化脚本”/“启动脚本”/“用户数据”脚本(这是 DigitalOcean 使用的,没有研究其他),这足以让我坚持使用 bash 初始化脚本解决方案。
如果有人为此提供了一个仅 Ansible 的杀手级解决方案,我仍然会感兴趣和好奇,尽管我不确定是否有一个很好的方法可以在没有预初始化脚本的情况下实现这一点。
不管有什么 ansible 限制,似乎如果不使用 cloud init 脚本,你就不能拥有这个。如果服务器以 root 或类似用户启动来执行这些操作,或者服务器启动时没有具有这些权限的用户,那么您将无法执行这些操作。
此外,我还看到了 Ansible 剧本和 bash 脚本,它们试图通过测试 root ssh 访问权限来解决所需的“幂等性”(即使 root 已被禁用也没有错误),然后回退给另一个用户,但是“我can't ssh with root”对于“是否禁用 root 用户”是一个糟糕的测试,因为即使服务器仍配置为允许 root 进行 ssh,您的 ssh 访问也有很多方法可能会失败。
EDIT 2 将其放在这里,因为我无法在回复评论时使用换行符:
β.εηοιτ.βε 回复了我的断言:
”但是“我不能使用 root 进行 ssh”对于“是否禁用 root 用户”来说是一个糟糕的测试,因为即使服务器仍然配置为允许 root,您的 ssh 访问也有很多方法可能会失败ssh
与
然后,尝试使用 infraops 进行 ssh 并断言 PermitRootLogin no 在 ssh 守护进程配置文件中?"
听起来建议是:
- attempt ssh with root
- if success, we know user/ssh setup tasks have not completed, so run those tasks
- if failure, attempt ssh with infraops
- if success, go ahead and run everything except the user creation again to ensure ssh config is as desired
- if failure... ? something else is probably wrong, since I can't ssh with either user
我不确定这种 if-then 故障恢复在 Ansible 脚本中实际上是什么样子的
【问题讨论】:
-
但是“我不能使用 root 进行 ssh”对于“是否禁用 root 用户”来说是一个糟糕的测试,因为即使服务器仍在运行,您的 ssh 访问也有很多方法可能会失败配置为允许root ssh > 然后,尝试使用
infraops和assertssh,PermitRootLogin no在 ssh 守护程序配置文件中? -
查看我的第二个帖子编辑,我试图在评论中回复,但需要换行符和格式来勾勒出来
标签: ssh ansible virtual-machine ansible-inventory