使用Ansible为多用户批量管理并移除指定authorized_keys
多用户SSH公钥的Ansible自动化管理问题
我是Ansible新手,目前需要实现:当存储多用户SSH公钥的YAML配置文件中移除某个用户的公钥时,自动从服务器对应用户的authorized_keys文件中删除该公钥。
现有YAML公钥配置文件内容
client: - key: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3 Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx NrRFi9wrf+M7Q== name: user1 - key: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3 Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx NrRFiefwwefew4w223e3e== name: user1 - key: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3 Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIku3hrbfwejw4ur4hfjewf4wkjr3434== name: user2 - key: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3 Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01Qrao3rj32hirbk2jewf239r232e3== name: user2
尝试过的方法及问题
方法1:使用authorized_key的exclusive参数循环
尝试循环处理每个密钥,但exclusive=True会导致每次循环都清空用户的authorized_keys只保留当前循环的密钥,最终用户只会剩下最后一个循环的密钥,无法保留该用户的所有有效密钥:
- name: Set authorized key for user become: yes authorized_key: user: "{{ item.name }}" state: present key: "{{ item.key }}" exclusive: True with_items: - "{{ client }}"
方法2:拼接所有密钥后批量设置
将所有用户的密钥拼接成字符串后为每个用户设置,导致所有用户的authorized_keys都包含所有密钥,完全混乱,无法实现用户独立管理:
- name: lookup ssh pubkeys from keyfiles and create ssh_pubkeys_list set_fact: ssh_keys: "{{ item.key }}" register: ssh_pubkeys_results_list with_items: - "{{ client }}" - name: iterate over ssh_pubkeys_list and join into a string set_fact: ssh_pubkeys_string: "{{ ssh_pubkeys_results_list.results | map(attribute='ansible_facts.ssh_keys') | join('\n')}}" - name: lookup ssh pubkeys from name and create ssh_pubkeys_list set_fact: ssh_keys: "{{ item.name }}" register: ssh_pubkeys_results with_items: - "{{ client }}" - name: Set authorized key for user become: yes authorized_key: user: "{{ item.name }}" state: present key: "{{ ssh_pubkeys_string }}" exclusive: True with_items: - "{{ client }}"
解决方案
核心思路是先按用户分组公钥,然后为每个用户单独处理其所有密钥,确保authorized_keys只保留该用户在YAML中的密钥,自动移除不在列表中的密钥:
- name: Group public keys by username set_fact: user_keys: "{{ client | groupby('name') }}" - name: Configure authorized keys for each user become: yes authorized_key: user: "{{ item.0 }}" state: present key: "{{ item.1 | map(attribute='key') | join('\n') }}" exclusive: True loop: "{{ user_keys }}"
代码解释
- 分组公钥:使用
groupby('name')过滤器将原始client列表按用户名分组,得到类似[('user1', [key_obj1, key_obj2]), ('user2', [key_obj3, key_obj4])]的结构。 - 循环处理每个用户:遍历分组后的结果,对每个用户:
item.0是用户名item.1是该用户的所有密钥对象,通过map(attribute='key')提取所有密钥内容,再用join('\n')拼接成多行字符串- 设置
exclusive=True,确保服务器上该用户的authorized_keys仅保留YAML中配置的这些密钥,自动删除不在列表中的密钥
这样就能实现:当YAML中移除某个用户的某条公钥时,服务器上该用户的authorized_keys会自动删除对应的密钥;新增密钥时也会自动添加,且每个用户的密钥独立管理。
内容的提问来源于stack exchange,提问作者WhizzY
相关产品推荐
相关产品推荐

