是否可以将 Ansible authorized_key 与多个密钥一起使用?

Is it possible to use Ansible authorized_key exclusive with multiple keys?

我刚开始使用 Ansible,一直在阅读 here 和 google,但还没有找到答案。

我的情况是我在服务器上有 1 个用户,但需要将 2-3 个不同的公钥放入 authorized_keys 文件。

我可以成功删除所有密钥,或使用此脚本添加所有密钥:

---
  - hosts: all

 tasks:
  - name: update SSH keys
    authorized_key:
     user: <user>
     key: "{{ lookup('file', item) }}"
     state: present
     #exclusive: yes
    with_fileglob:
      - ../files/pub_keys/*.pub

它使用 present 标志读取并添加所有键。使用 absent 标志,它会删除列出的所有键。

问题是我有一个仅在服务器上的旧密钥,我想 remove/overwrite 它并为将来的部署覆盖可能在服务器上但不在我的剧本中的任何未经授权的密钥。

使用 exclusive 标志,它只获取最后一个键并添加它。如果它能循环并递归地添加所有键,那就太棒了。如果有办法在 Ansible 中执行此操作,我还没有找到它。

有什么方法可以循环遍历 pub 文件并同时使用 exclusive 选项吗?

有没有办法循环pub文件的同时使用独占选项?

没有。在 docs:

中有关于循环和独占的说明

exclusive: Whether to remove all other non-specified keys from the authorized_keys file. Multiple keys can be specified in a single key string value by separating them by newlines. This option is not loop aware, so if you use with_ , it will be exclusive per iteration of the loop, if you want multiple keys in the file you need to pass them all to key in a single batch as mentioned above.

因此您需要加入所有密钥并一次发送所有密钥。
像这样:

- name: update SSH keys
  authorized_key:
    user: <user>
    key: "{{ lookup('pipe','cat ../files/pub_keys/*.pub') }}"
    state: present
    exclusive: yes

在生产 运行 之前检查此代码!

如果您将用户保留在一个变量中,您可以使用这个:

---

- hosts: all
  vars_files:
    - roles/users/vars/main.yml
  tasks:
    - name: Allow other users to login to the account
      authorized_key:
        user: user_name
        exclusive: yes
        key: "{{ developers|map(attribute='publish_ssh_key')|join('\n') }}"

roles/users/vars/main.yml 看起来像这样:

---

developers:
  - name: user1
    publish_ssh_key: ssh-rsa AAAA...
  - name: user2
    publish_ssh_key: ssh-rsa AAAA...

如果您想避免 pipe 查找(例如,因为路径与角色无关),您还可以结合使用 filefileglob 查找:

- name: update SSH keys
  authorized_key:
    user: <user>
    key:  "{% for key in lookup('fileglob', 'pub_keys/*.pub').split(',') %}{{ lookup('file', key) ~ '\n'}}{% endfor %}"
    state: present
    exclusive: yes

正如我在另一个答案 (Ansible - managing multiple SSH keys for multiple users & roles) 中所写的那样,这是我为我的用例解决此问题的方式。也许它在这里有用?

我将变量中的文件名数组传递给我的 user-account 角色。然后角色获取每个文件的内容,将它们附加到一个以换行符分隔的字符串中,最后将此值设置为新用户的 ssh-key。

.

剧本文件:

- hosts: aws-node1
  roles:
    - { role: user-account, username: 'developer1', ssh_public_keyfiles: ['peter-sshkey.pub', 'paul-sshkey.pub'] }

.

user-account 的角色定义:

- name: add user
  user:
    name: "{{username}}"


- name: lookup ssh pubkeys from keyfiles and create ssh_pubkeys_list
  set_fact:
    ssh_pubkeys_list: "{{ lookup('file', item) }}"
  with_items:
    "{{ssh_public_keyfiles}}"
  register: ssh_pubkeys_results_list


- 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_pubkeys_list') | list | join('\n') }}"


- name: update SSH authorized_keys for user {{ username }} with contents of ssh_pubkeys_string
  authorized_key:
    user: "{{ username }}"
    key: "{{ ssh_pubkeys_string }}"
    state: present
    exclusive: yes

与前面的答案相同的基本概念,但只使用变量并从 url 中提取密钥,例如 github 或 gitlab。

#Vars
ssh_users:
  - user1
  - user2
ssh_key_urls: "{{ ssh_users | map('regex_replace', '^(.*)$', 'https://key_server/\1.keys') | list }}"
authorized_keys: "{% for u in ssh_key_urls %}{{ lookup('url', u, split_lines=False) }}\n{% endfor %}"

#task
- name: setup authorized_keys
  authorized_key:
    key: "{{ authorized_keys }}"
    state: present
    exclusive: true