06 managing secrets, facts and cycles

Manage secrets, facts and cycles

1. Manage confidentiality

1.1 ansible vault

Ansible may need to access sensitive data such as passwords or apl keys so that managed hosts can be configured. Generally, this information may be stored in manifest variables or other ansible files in plain text. However, any user who has access to ansible files can access it, which poses a security risk

Ansible vault provided by ansible can decrypt and encrypt any structured data file used by ansible. To use ansible vault, you can create, edit, encrypt, decrypt, and view files through ansible vault's command-line tools

1.1.1 creating encrypted files

Use ansible vault create filename to create a new encrypted file. Enter the password. The default editor is vi to open the file

[root@my ansible]# ansible-vault create group_vars/apache
New Vault password: 
Confirm New Vault password: 

1.1.2 viewing encrypted files

Use ansbile vault view filename to view the encrypted file without having to open it for editing

[root@my ansible]# cat group_vars/apache 
$ANSIBLE_VAULT;1.1;AES256
33396234613132373566303135306537363139366334343463383065363061336362633333663436
3762353739663035323539613466643239326661633566620a353464626663623133366562636239
63623636346131383162326236666563373933363033613461383032646330303834303434613664
3863386262383932350a343130623164633132376632393563396461613739366630626633376637
36396633666166376537316237613862643666343861363132626566303233353430643862303961
3265636561646264343838626133353239376665613632356364
[root@my ansible]# ansible-vault view group_vars/apache 
Vault password: 
ansible_user=root
ansible_password=1

1.1.3 decrypt encrypted files

Use the ansbile vault decrypt filename command to permanently decrypt

[root@my ansible]# ansible-vault decrypt group_vars/apache 
Vault password: 
Decryption successful
[root@my ansible]# cat group_vars/apache 
ansible_user=root
ansible_password=1

1.1.4 the file already exists. Now encrypt it

Use ansible vault encrypt filename

[root@my ansible]# ansible-vault encrypt group_vars/apache 
New Vault password: 
Confirm New Vault password: 
Encryption successful

1.1.5 edit encrypted files

Use ansible vaule edit filename

[root@my ansible]# ansible-vault edit group_vars/apache 
Vault password:  //Enter the password here
//Enter the password and enter the vi editor automatically
ansible_user=root
ansible_password=1

1.1.6 re encrypt encrypted files

Using the ansible vault rekey filename, you need to enter the old password to modify the new password

[root@my ansible]# ansible-vault rekey group_vars/apache 
Vault password: 
New Vault password: 
Confirm New Vault password: 
Rekey successful

1.2 playbook and ansible vault

To run a playbook that can access files encrypted by ansible vault, you need to provide the encrypted file to the ansible playbook command. If you do not provide a password, playbook will return an error

[root@my ansible]# ansible-playbook group_vars/apache / / no password provided
ERROR! Attempting to decrypt but no vault secrets found

To provide a vault password for the playbook, use the – vault ID option, as shown in

//This is the password you entered manually
[root@my ansible]# ansible-playbook --vault-id @prompt playbook/test.yml 
Vault password (default): 
ERROR! variable files must contain either a dictionary of variables, or a list of dictionaries. Got: user:yi (<class 'ansible.parsing.yaml.objects.AnsibleUnicode'>)

Alternatively, you can use – vault password file = file name

[root@my ansible]# ls -a
.  ..  ansible.cfg  group_vars  hosts  host_vars  inventory  playbook  roles
[root@my ansible]# vim .mima / / set a hidden file name for storing passwords
[root@my ansible]# cat .mima 
1
[root@my ansible]# ansible-vault view --vault-password-file=.mima group_vars/apache 
ansible_user=root
ansible_password=1
[root@my ~]# openssl rand -base64 20 / / this is a randomly generated password
2mSBfy2utJiEIhIGVJMLrVSg008=

//decrypt
[root@my ansible]# ansible-vault decrypt --vault-password-file=.mima group_vars/apache 
Decryption successful
[root@my ansible]# cat group_vars/apache 
ansible_user=root
ansible_password=1
//Encrypt an existing file
[root@my ansible]# ansible-vault encrypt --vault-password-file=.mima group_vars/apache 
Encryption successful
//Reset the password without entering a new password
[root@my ansible]# vim .xinmima
[root@my ansible]# cat .xinmima 
1
[root@my ansible]# ansible-vault rekey --vault-password-file=.mima --new-vault-password-file=.xinmima group_vars/apache 
Rekey successful

1.2.1 recommended practices for variable file management

The general meaning is to put the variables that need to be encrypted under one file and the variables that do not need to be encrypted under another file, which means open

//Create a user module, encrypt variables, and execute after encryption
[root@my ansible]# cat playbook/test.yml 
---
- hosts: "*"
  vars_files:
    - vars/users.yml
  tasks:
    - name: create user {{ user }}
      user:
        user: "{{ user }}"
        state: present
[root@my ansible]# cat .mima 
1
[root@my ansible]# ansible-vault create --vault-password-file=.mima playbook/vars/users.yml 
[root@my ansible]# ansible-playbook --vault-password-file=.mima playbook/test.yml 

PLAY [*] ****************************************************************************************************

TASK [Gathering Facts] **************************************************************************************
ok: [192.168.47.147]

TASK [create user yi] ***************************************************************************************
changed: [192.168.47.147]

PLAY RECAP **************************************************************************************************
192.168.47.147             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[root@apache ~]# id yi
uid=2002(yi) gid=2002(yi) group=2002(yi)

2. Management facts

2.1 describe ansible facts

Ansible is actually a variable that ansible automatically detects on the managed host. The fact contains host related information

Collecting ide facts for managed hosts may include:

  • Host name
  • Kernel version
  • network interface
  • IP address
  • Operating system version
  • Various environmental variables
  • Number of CPU s
  • Memory provided or available
  • disk space available

With the help of facts, it is convenient to detect the state of the managed host and determine the operations to be performed according to the state, such as:

  • You can restart the server by running the conditional task based on the fact that it contains the current kernel version of the managed host
  • MySQL configuration files can be customized based on available memory through fact reporting
  • You can set the IPv4 address used in the configuration file based on the value of the fact

Usually, each play will automatically run the setup module before the first task

//On the command line
[root@my ansible]# ansible all -m setup | less
192.168.47.147 | SUCCESS => {
    "ansible_facts": {  //This is all information
        "ansible_all_ipv4_addresses": [
            "192.168.47.147"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::5421:1580:4f7f:fa15"
        ],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "07/29/2019",
        "ansible_bios_version": "6.00",
//In playbook
[root@my playbook]# cat test.yml   
---
- hosts: "*"
  tasks:
    - name: my
      debug:
        var: ansible_facts   //Meaning of var variable
[root@my playbook]# ansible-playbook test.yml / / this is to get all
TASK [my] ***************************************************************************************************
ok: [192.168.47.147] => {
    "ansible_facts": {
        "all_ipv4_addresses": [
            "192.168.47.147"
        ],
        "all_ipv6_addresses": [

//Get the facts you want in playbook
[root@my playbook]# vim test.yml 
[root@my playbook]# cat test.yml 
---
- hosts: "*"
  tasks:
    - name: my
      debug:
        var: ansible_facts['all_ipv4_addresses']
[root@my playbook]# ansible-playbook test.yml 

PLAY [*] ****************************************************************************************************

TASK [Gathering Facts] **************************************************************************************
ok: [192.168.47.147]

TASK [my] ***************************************************************************************************
ok: [192.168.47.147] => {
    "ansible_facts['all_ipv4_addresses']": [
        "192.168.47.147"  //Here is the result
    ]
}

//Get a little more accurate
[root@my playbook]# cat test.yml 
---
- hosts: "*"
  tasks:
    - name: my
      debug:
        var: ansible_facts['default_ipv4']['address'] //The difference is here
[root@my playbook]# ansible-playbook test.yml 

PLAY [*] ****************************************************************************************************

TASK [Gathering Facts] **************************************************************************************
ok: [192.168.47.147]

TASK [my] ***************************************************************************************************
ok: [192.168.47.147] => {
    "ansible_facts['default_ipv4']['address']": "192.168.47.147"  //The result is here
}

//Another method, python, is not recommended
[root@my playbook]# cat test.yml 
---
- hosts: "*"
  tasks:
    - name: my
      debug:
        var: ansible_facts.default_ipv4.address  //Here it is

The following table is the facts collected by the controlled node and can be used in the playbook:

factvariable
Short host nameansible_facts['hostname']
Fully qualified domain nameansible_facts['fqdn']
IPv4 addressansible_facts['default_ipv4']['address']
Name list of all network interfacesansible_facts['interfaces']
/Size of dev/vda1 disk partitionansible_facts['devices']['vda']['partitions']['vda1']['size']
DNS server listansible_facts['dns']['nameservers']
Currently running kernel versionansible_facts['kernel']

When using facts in playbook, ansible dynamically replaces the variable name of facts with the corresponding value:
msg: meaning of information

[root@my playbook]# cat test.yml 
---
- hosts: "*"
  tasks:
    - name: my
      debug:
        msg: >  
          The host named {{ ansible_facts['fqdn'] }}of
          ip is {{ ansible_facts['default_ipv4']['address'] }}
[root@my playbook]# ansible-playbook test.yml 

PLAY [*] ****************************************************************************************************

TASK [Gathering Facts] **************************************************************************************
ok: [192.168.47.147]

TASK [my] ***************************************************************************************************
ok: [192.168.47.147] => {
    "msg": "The host named apache of ip is 192.168.47.147\n" //My other host is called apache, and the address is 47.147
}

2.2 inject ansible facts as variables

Comparison of selected ansible fact names

ansible_facts formForm of old fact variable
ansible_facts['hostname']ansible_hostname
ansible_facts['fqdn']ansible_fqdn
ansible_facts['default_ipv4']['address']ansible_default_ipv4['address']
ansible_facts['interfaces']ansible_interfaces
ansible_facts['devices']['vda']['partitions']['vda1']['size']ansible_devices['vda']['partitions']['vda1']['size']
ansible_facts['dns']['nameservers']ansible_dns['nameservers']
ansible_facts['kernel']ansible_kernel

Insert in the [default] section of the Ansible configuration file_ facts_ as_ Set the vars parameter to False to turn off the old naming system. After closing, you can only use the new ansible_facts.* The naming system refers to Ansible fact. The default setting is currently True.

[root@my ansible]# vim ansible.cfg 
# will be changed to a default of 'False' in a future release.
# ansible_facts.
 inject_facts_as_vars = false

2.3 close fact collection

Reasons for closing facts:

  • Not prepared to use any facts
  • Hope to speed up play
  • You want to reduce the load caused by play on the managed host
  • The managed host cannot run the setup module for some reason
  • You need to install some prerequisite software before collecting facts

To disable fact collection for play, set gather_ Set the facts keyword to no:

---
- hosts: "*"
  gather_facts: no  //Here it is

Even if gather is set for play_ Facts: No, you can also manually collect facts at any time by running the task using the setup module:

---
- hosts: "*"
  gather_facts: no
  tasks:
    - name: my
      setup:
    - name: debug
        var: ansible_facts   //Turning it off and on belongs to cerebral palsy. It won't be used basically

2.4 custom creation facts

By default, the setup module is from / etc / ansible / facts.com of each managed host Load custom facts in the files and scripts in the D directory. The name of each file or script must be in The end of fact can only be used.
Available INI and JSON formats

[root@apache ~]# mkdir -p /etc/ansible/facts.d
[root@apache ~]# cd /etc/ansible/facts.d/
[root@apache facts.d]# vim my.fact
[root@apache facts.d]# cat my.fact 
[packages]
web_package = httpd
db_package = mariadb-server

[users]
user1 = joe
user2 = jane
[root@my playbook]# ansible all -m setup|less
"ansible_local": {    //Search ansible_local
            "my": {
                "packages": {
                    "db_package": "mariadb-server",
                    "web_package": "httpd"
                },
                "users": {
                    "user1": "joe",
                    "user2": "jane"

Custom facts are stored in ansible by the setup module_ facts. ansible_ Local variable.

2.5 magic variables

Some variables are not facts or configured through the setup module, but are also automatically set by Ansible. These magic variables can also be used to obtain information related to a specific managed host.

There are four most commonly used:

Magic variableexplain
hostvarsA variable that contains a managed host and can be used to get the value of a variable of another managed host. If facts have not been collected for the managed host, it will not contain the facts for that host.
group_namesLists all groups to which the currently managed host belongs
groupsLists all groups and hosts in the list
inventory_hostnameContains the host name of the currently managed host configured in the manifest. For various reasons, it may be different from the host name reported in the fact

One way to gain insight into their values is to use the debug module to report the contents of the hostvars variable for a specific host:

ansible 192.168.47.147 -m debug -a 'var=hostvars["localhost"]'

3. Task cycle

3.1 write cycle and condition tasks

By using loops, the first mock exam does not need to write multiple tasks. Instead of writing five tasks to ensure that there are five users, they just need to write one task to iterate over a list of five users to ensure that they all exist.

Ansible supports iterative tasks on a set of projects using the loop keyword. Loops can be configured to repeat tasks using items in the list, the contents of files in the list, generated sequences of numbers, or more complex structures

3.1.1 simple cycle

A simple loop iterates over a set of projects. Add the loop keyword to the task and take the list of items that should be iterated by it as the value. The loop variable item holds the values used during each iteration.

[root@my playbook]# cat user.yml 
---
- name: task1
  hosts: "*"
  tasks:
    - name: Create user {{ item }}
      user:
        name: "{{ item }}"
        state: present
      loop:
        - user1
        - user2
        - user3
[root@my playbook]# ansible-playbook user.yml 

PLAY [task1] ************************************************************************************************

TASK [Gathering Facts] **************************************************************************************
ok: [192.168.47.147]

TASK [Create user {{ item }}] **************************************************************************************
changed: [192.168.47.147] => (item=user1)
changed: [192.168.47.147] => (item=user2)
changed: [192.168.47.147] => (item=user3)

PLAY RECAP **************************************************************************************************
192.168.47.147             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[root@apache facts.d]# id user1
uid=2003(user1) gid=2003(user1) group=2003(user1)
[root@apache facts.d]# id user2
uid=2004(user2) gid=2004(user2) group=2004(user2)
[root@apache facts.d]# id user3
uid=2005(user3) gid=2005(user3) group=2005(user3)

//Another way
[root@my ansible]# cat playbook/vars/users.yml 
user:
  - user1
  - user2
  - user3
[root@my ansible]# cat playbook/user.yml 
---
- name: task1
  hosts: "*"
  vars_file: 
    - vars/users.yml
  tasks:
    - name: Create user {{ item }}
      user:
        name: "{{ item }}"
        state: absent
      loop: "{{ user }}"
[root@my ansible]# ansible-playbook playbook/user.yml 

3.1.2 circular hash or dictionary list

//The first way
[root@my playbook]# vim user.yml 
---
- name: task
  hosts: "*"
  vars_file:
    - vars/users.yml
  tasks:
    - name: Create user {{ item.name }}
      user:
        name: "{{ item.name }}"
        uid: "{{ item.uid}}"
        state: present
      loop: 
        - name: user1
          uid: 2222
[root@my playbook]# ansible-playbook user.yml 

//The second way
[root@my playbook]# cat user.yml 
---
- name: task
  hosts: "*"
  vars_file: 
    - vars/users.yml
  tasks:
    - name: Create user {{ item.name }}
      user:
        name: "{{ item.name }}"
        uid: "{{ item.uid}}"
        state: present
      loop: "{{ user }}"
[root@my playbook]# cat vars/users.yml 
user:
  - name: user1
    uid: 2222
  - name: user2
    uid: 2223
[root@my playbook]# ansible-playbook user.yml 

3.1.3 cyclic keywords of earlier styles

Circular keyworddescribe
with_itemsThe behavior is the same as the loop keyword of a simple list, such as a string list or a hash / dictionary list. But different from loop, if it is with_items provides a list of lists, which will be flattened into a single-level list. The loop variable item holds the list items used during each iteration.
with_fileThis keyword requires a list of control node file names. The loop variable item saves the contents of the corresponding file in the file list during each iteration.
with_sequenceThis keyword does not require a list, but requires parameters to generate a list of values from a sequence of numbers. The loop variable item saves the value of a generated item in the generated sequence during each iteration.
vars:
  data:
    - user0
    - user1
    - user2
tasks:
  - name: "with_items"
    debug:
      msg: "{{ item }}"
    with_items: "{{ data }}"

3.1.4 use register variable with loop

[root@my playbook]# cat test.yml 
---
- hosts: "*"
  gather_facts: no
  tasks:
    - name: my
      command: "echo hello {{ item }},how are you"
      loop:
        - tom
        - awm
      register: result


    - debug:
        var: result

Added by bubblegum.anarchy on Sat, 15 Jan 2022 16:43:10 +0200