18

我在使用 Ansible 方面相当新,并且一直在阅读这里和谷歌,但还没有找到答案。

我的情况是我在服务器上有 1 个用户,但需要将 2-3 个不同的 pub 密钥放入它的 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标志,它会删除列出的所有键。

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

使用exclusive标志它只需要最后一个键并添加它。如果它会循环并重复添加所有键,那就太棒了。如果在 Ansible 中有办法做到这一点,我还没有找到。

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

4

5 回答 5

19

有什么方法可以遍历 pub 文件并同时使用独占选项?

不,文档中有关于循环和排他性的注释:

Exclusive:是否从 authorized_keys 文件中删除所有其他未指定的密钥。通过用换行符分隔多个键,可以在单个键字符串值中指定多个键。此选项不支持循环,因此如果您使用 with_ ,它将在循环的每次迭代中独占,如果您想要文件中的多个键,您需要将它们全部传递给单个批次中的键,如上所述。

因此,您需要加入所有密钥并立即发送所有密钥。
像这样的东西:

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

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

于 2016-08-10T17:19:52.660 回答
9

如果您想避免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
于 2018-02-20T09:40:14.577 回答
4

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

---

- 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...
于 2016-10-26T14:54:02.653 回答
0

正如我在另一个答案中所写的那样(Ansible - 为多个用户和角色管理多个 SSH 密钥),这是我为我的用例解决这个问题的方式。也许在这里有用?

我将变量中的文件名数组传递给我的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
于 2018-11-01T15:57:03.233 回答
0

与前面的答案相同的基本概念,但仅使用变量并从 github 或 gitlab 之类的 url 中提取键。

#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
于 2021-08-26T14:56:07.597 回答