ansible 管理机密
Ansible Vault
Ansible可能需要访问密码或API密钥等敏感数据,以便能配置受管主机。通常,此信息可能以纯文本形式存储在清单变量或其他Ansible文件中。这存在在安全风险。
Ansible提供的Ansible Vault可以加密和解密任何由Ansible使用的结构化数据文件。若要使用Ansible Vault,可通过一个名为ansible-vault的命令行工具创建、编辑、加密、解密和查看文件。Ansible Vault可以加密任何由Ansible使用的结构化数据文件。这可能包括清单变量、playbook中含有的变量文件、在执行playbook时作为参数传递的变量文件,或者Ansible角色中定义的变量。
创建加密文件
[root@localhost project]# ansible-vault create passwd
New Vault password:
Confirm New Vault password:
cat查看不了
[root@localhost project]# cat passwd
$ANSIBLE_VAULT;1.1;AES256
32353537316262353837323935643539303361656164353139313430343635336237323262336362
3566303565636337653435626330616530353235366630620a613161666539336435666266383766
31633537656531336532343265323535363435306635376564376331356231386434393833623633
3537353865646263610a613636396638396564363061343464316430373762633534386634613535
3833
[root@localhost project]# ansible-vault view passwd
Vault password:
passwd: 123
view加密查看
[root@localhost project]# ansible-vault edit passwd
Vault password:
编辑已加密文件
[root@localhost project]# ansible-vault decrypt passwd
Vault password:
Decryption successful
[root@localhost project]# cat pa
packages/ passwd
[root@localhost project]# cat passwd
passwd: 123
解密文件
[root@localhost project]# ansible-vault encrypt playbook/apache.yml
New Vault password:
Confirm New Vault password:
Encryption successful
加密已存在yml文件
[root@localhost project]# ansible-vault rekey playbook/apache.yml
Vault password:
New Vault password:
Confirm New Vault password:
Rekey successful
重新加密/改密码
利用文件解密
[root@localhost project]# cat .key
123
创建隐藏密码文件
[root@localhost project]# ansible-vault view --vault-password-file=.key playbook/apache.yml
利用文件解密
playbook和ansible vault
要运行可访问通过Ansible Vault加密的文件的playbook,需要向ansible-playbook命令提供加密密码。
---
- name: 111
hosts: apache
vars_files:
- /etc/ansible/vars/usr.yml
指定加密变量地址
[root@localhost ansible]# ansible-playbook --vault-id @prompt playbook/useradd.yml
输入加密密码即可提取加密变量运行剧本
管理事实
Ansible事实是Ansible在受管主机上自动检测到的变量。事实中包含有与主机相关的信息,可以像play中的常规变量、条件、循环或依赖于从受管主机收集的值的任何其他语句那样使用。
为受管主机收集的一些事实可能包括:
主机名称 内核版本 网络接口 IP地址 操作系统版本 各种环境变量 CPU数量 提供的或可用的内存 可用磁盘空间
事实 | 变量 |
---|
短主机名 | ansible_facts[‘hostname’] | 完全限定域名 | ansible_facts[‘fqdn’] | IPv4地址 | ansible_facts[‘default_ipv4’][‘address’] | 所有网络接口的名称列表 | ansible_facts[‘interfaces’] | /dev/vda1磁盘分区的大小 | ansible_facts[‘devices’][‘vda’][‘partitions’][‘vda1’][‘size’] | DNS服务器列表 | ansible_facts[‘dns’][‘nameservers’] | 当前运行的内核版本 | ansible_facts[‘kernel’] |
[root@localhost ansible]# cat ss.yml
---
- name: kkkk
hosts: apache
tasks:
- name: 122
debug:
var: ansible_facts['hostname']
[root@localhost ansible]# ansible-playbook ss.yml
PLAY [kkkk] *********************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************
ok: [192.168.216.172]
TASK [debug] ********************************************************************************************************************
ok: [192.168.216.172] => {
"ansible_facts['hostname']": "localhost"
}
PLAY RECAP **********************************************************************************************************************
192.168.216.172 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
提取hostname
关闭事实收集
不准备使用任何事实
希望加快play速度
希望减小play在受管主机上造成的负载
受管主机因为某种原因无法运行setup模块
需要安装一些必备软件后再收集事实
以上种种原因导致我们可能想要永久或暂时关闭事实收集的功能,要为play禁用事实收集功能,可将gather_facts关键字设置为no:
---
- name: 111
hosts: all
gather_facts: no
即使play设置了gather_facts: no,也可以随时通过运行使用setup模块的任务来手动收集事实:
---
- name: gather_facts
hosts: all
gather_facts: no
tasks:
- name: get gather_facts
setup:
- name: debug
debug:
var: ansible_facts
创建自定义事实
除了使用系统捕获的事实外,我们还可以自定义事实,并将其本地存储在每个受管主机上。这些事实整合到setup模块在受管主机上运行时收集的标准事实列表中。它们让受管主机能够向Ansible提供任意变量,以用于调整play的行为。 有了自定义事实,我们可以为受管主机定义特定的值,供play用于填充配置文件或有条件地运行任务。动态自定义事实允许在play运行时以编程方式确定这些事实的值,甚至还可以确定提供哪些事实。
默认情况下,setup模块从各受管主机的/etc/ansible/facts.d目录下的文件和脚本中加载自定义事实。各个文件或脚本的名称必须以.fact结尾才能被使用。动态自定义事实脚本必须输出JSON格式的事实,而且必须是可执行文件。
[root@localhost ~]# mkdir -p /etc/ansible/facts.d
[root@localhost ~]# cd /etc/ansible/facts.d
[root@localhost facts.d]# vim 123.fact
[root@localhost facts.d]# cat 123.fact
[pack]
web=httpd
[users]
user1=123
user2=234
不需要下载ansible,只需要创建目录
[root@localhost ansible]# ansible apache -m setup|less
"ansible_local": {
"123": {
"pack": {
"web": "httpd"
},
"users": {
"user1": "123",
"user2": "234"
魔法变量
魔法变量 | 说明 |
---|
hostvars | 包含受管主机的变量,可以用于获取另一台受管主机的变量的值。如果还没有为受管主机收集事实,则它不会包含该主机的事实。 | group_names | 列出当前受管主机所属的所有组 | groups | 列出清单中的所有组和主机 | inventory_hostname | 包含清单中配置的当前受管主机的主机名称。因为各种原因有可能与事实报告的主机名称不同 |
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable。更多魔法变量
[root@localhost ansible]# ansible apache -m debug -a 'var=hostvars["localhost"]'
192.168.216.172 | SUCCESS => {
"hostvars[\"localhost\"]": {
"ansible_check_mode": false,
"ansible_connection": "local",
"ansible_diff_mode": false,
"ansible_facts": {},
"ansible_forks": 5,
"ansible_inventory_sources": [
"/etc/ansible/hosts"
简单循环
- name: Postfix is running
service:
name: postfix
state: started
- name: Devecot is running
service:
name: dovecot
state: started
可以合并为
- name: Postfix and Devecot are running
service:
name: "{{ item }}"
state: started
loop:
- postfix
- dovecot
循环散列或字典列表
loop列表不需要是简单值列表,当前item循环变量中每个键的值可以分别通过item.name和item.groups变量来检索。
- name: Users exist and are in the correct groups
user:
name: "{{ item.name }}"
state: present
uid: "{{ item.uid }}"
loop:
- name: jane
uid:1001
- name: joe
uid:1002
较早样式的循环关键字
循环关键字 | 描述 |
---|
with_items | 行为与简单列表的loop关键字相同,例如字符串列表或散列/字典列表。但与loop不同的是,如果为with_items提供了列表的列表,它们将被扁平化为单级列表。循环变量item保存每次迭代过程中使用的列表项。 | with_file | 此关键字需要控制节点文件名列表。循环变量item在每次迭代过程中保存文件列表中相应文件的内容。 | with_sequence | 此关键字不需要列表,而是需要参数来根据数字序列生成值列表。循环变量item在每次迭代过程中保存生成的序列中的一个生成项的值。 |
[root@localhost playbook]# cat vars/999.yml
user:
- lhj
- hjj
- jhk
写一个变量
[root@localhost playbook]# cat useradd.yml
---
- name: 111
hosts: apache
vars_files:
- /etc/ansible/playbook/vars/999.yml
tasks:
- name: "{{ item }}"
user:
name: "{{ item }}"
state: present
loop: "{{ user }}"
直接利用变量循环
[root@localhost playbook]# ansible-playbook useradd.yml
PLAY [111] **********************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************
ok: [192.168.216.172]
TASK [{{ item }}] ***************************************************************************************************************
changed: [192.168.216.172] => (item=lhj)
changed: [192.168.216.172] => (item=hjj)
changed: [192.168.216.172] => (item=jhk)
PLAY RECAP **********************************************************************************************************************
192.168.216.172 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
字典列表
[root@localhost playbook]# cat vars/999.yml
user:
- name: lhj01
uid: 2001
- name: jiii1
uid: 2011
- name: tom01
uid: 2000
[root@localhost playbook]# cat useradd.yml
---
- name: 111
hosts: apache
vars_files:
- /etc/ansible/playbook/vars/999.yml
tasks:
- name: "{{ item.name }}"
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
loop: "{{ user }}"
[root@localhost playbook]# ansible-playbook useradd.yml
PLAY [111] **********************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************
ok: [192.168.216.172]
TASK [{{ item.name }}] **********************************************************************************************************
changed: [192.168.216.172] => (item={u'name': u'lhj01', u'uid': 2001})
changed: [192.168.216.172] => (item={u'name': u'jiii1', u'uid': 2011})
changed: [192.168.216.172] => (item={u'name': u'tom01', u'uid': 2000})
PLAY RECAP **********************************************************************************************************************
192.168.216.172 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
将Register变量与Loop一起使用
[root@localhost playbook]# cat usr.yml
---
- name: task1
gather_facts: no
hosts: apache
tasks:
- name: 12131
shell: "echo hello {{ item }} "
loop:
- tom
- jerry
- emily
register: result
- name: 123
debug:
var: result
"stdout": "hello tom",
"stdout_lines": [
"hello tom"
]
},
{
"ansible_loop_var": "item",
"changed": true,
"cmd": "echo hello jerry ",
"delta": "0:00:00.002544",
"end": "2021-07-24 07:17:19.810147",
"failed": false,
"invocation": {
"module_args": {
"_raw_params": "echo hello jerry ",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "jerry",
"rc": 0,
"start": "2021-07-24 07:17:19.807603",
"stderr": "",
"stderr_lines": [],
"stdout": "hello jerry",
"stdout_lines": [
"hello jerry"
]
},
{
"ansible_loop_var": "item",
"changed": true,
"cmd": "echo hello emily ",
|