我正在尝试将证书分发给其相应的主机(我仅给出私钥任务的示例):
- name: create certificate private key
community.crypto.openssl_privatekey:
path: "/root/client/{{ item }}.key"
type: Ed25519
backup: yes
return_content: yes
register: privatekey
loop: "{{ ansible_play_hosts_all }}"
when: "'prometheus1' in inventory_hostname"
我可以像这样为其他主机调用该变量:
{{ hostvars['prometheus1']['privatekey']['results'][0]['privatekey'] }}
索引指向某个键,因此 0 表示第一个主机(prometheus1
),1 表示第二个主机,依此类推。
我认为模板化是可行的方法,但我不知道如何编写模板。我认为ansible_play_hosts_all
解决方案的关键在于它的索引与私钥的索引相对应,例如:
ansible_play_hosts_all[2]
-->hostvars['prometheus1']['privatekey']['results'][2]['privatekey']
但逻辑是:
for i in index of ansible_play_hosts_all
add the hostvars['prometheus1']['privatekey']['results'][i]['privatekey']
if ansible_play_hosts_all[i] in inventory_hostname
我想是这样的:) 任何帮助都将不胜感激。
更新
也许更准确一点:
{% for i in ansible_play_hosts_all|length) %}
{{ hostvars['prometheus1']['privatekey']['results'][i]['privatekey'] }}
{% endfor %}
并添加条件:
{% if ansible_play_hosts_all[i] in inventory_hostname %}
答案1
使用起来会更简单代表团创建密钥,prometheus1
同时保留与正确主机关联的注册变量。然后,您就可以privatekey.privatekey
在模板中使用。
- name: create certificate private key
community.crypto.openssl_privatekey:
path: /root/client/{{ inventory_hostname }}.key
type: Ed25519
backup: yes
return_content: yes
register: privatekey
delegate_to: prometheus1
如果您确实想坚持当前的结构,则可以通过检查item
结果中的值来找到与当前主机相对应的列表元素,该值包含item
循环的该次迭代。
{{ (hostvars['prometheus1']['privatekey']['results'] | selectattr('item', '==', inventory_hostname) | list | first).privatekey }}
答案2
创建一个包含数据的字典,例如给定库存
shell> cat hosts
prometheus1 ansible_host=localhost
test_11 ansible_host=10.1.0.61 ansible_user=admin
test_12 ansible_host=10.1.0.62 ansible_user=admin
test_13 ansible_host=10.1.0.63 ansible_user=admin
剧本
- hosts: all
gather_facts: false
tasks:
- community.crypto.openssl_privatekey:
path: "{{ playbook_dir }}/client/{{ item }}.key"
type: Ed25519
backup: yes
return_content: yes
register: privatekey
loop: "{{ ansible_play_hosts_all|difference(['prometheus1']) }}"
delegate_to: prometheus1
run_once: true
- set_fact:
host_priv: "{{ privatekey.results|
json_query('[].{host: item,
priv: privatekey}')|
items2dict(key_name='host', value_name='priv') }}"
run_once: true
为每个主机生成私钥,但以下情况除外普罗米修斯1,将密钥存储在文件中,并根据注册的数据创建主机及其密钥的字典
shell> tree client/
client/
├── test_11.key
├── test_12.key
└── test_13.key
ok: [prometheus1] =>
host_priv:
test_11: |-
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIM7/BtpiM1EZxrrwtuE2VdSdr++3J/yxm/BnabnMqL3e
-----END PRIVATE KEY-----
test_12: |-
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIPr8VV2RDOggNxo6vpBiXjSTzclJHFHaTVSxlFFVKoU1
-----END PRIVATE KEY-----
test_13: |-
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIJjp2knmccffeEGvTNaP2f+ijXkeLmu89cGgkqFi771/
-----END PRIVATE KEY-----
然后,您可以继续游戏并将密钥复制给主机,例如
- name: copy private key
copy:
content: "{{ host_priv[inventory_hostname] }}"
dest: /tmp/private.key
when: inventory_hostname != 'prometheus1'
become: true
使路径适合您的需要并设置所有权和权限。
答案3
我最终想出了解决方案:
{% for i in range(ansible_play_hosts_all|length) %}
{% if ansible_play_hosts_all[i] in inventory_hostname -%}
{{ hostvars['prometheus1']['privatekey']['results'][i]['privatekey'] }}
{%- endif %}
{% endfor %}
这按预期工作。我循环遍历 ansible_play_hosts_all 的长度(以了解角色正在运行的主机数量),并在循环内部添加条件,即索引需要与清单中的主机名相对应。
if 条件中的and会删除输出中的空格。如果没有它们,-%
则%-
每个文件都会添加一个空行(在本例中这似乎不会影响 openssl,当然,没有它会更好)
模板任务本身如下:
- name: copy certificate through templating
template:
src: certs.j2
dest: "/root/{{ inventory_hostname }}.key"