ansible manage variables and encryption and decryption

ansible manage variables and encryption and decryption

Introduction to ansible variable

Ansible supports the use of variables to store values and reuse these values in all files of ansible projects. This simplifies the creation and maintenance of projects and reduces the number of errors.

For example, a variable might contain the following values:

  • User to create

  • Packages to install

  • Services to restart

  • Files to delete

  • Archive to retrieve from the Internet

Named variable rules

The name of a variable must start with a letter and can only contain letters, numbers, and underscores.

invalid argumentValid variables
qqq 123qqq_123
list 123 abclist_123_abc
QQQ.123QQQ_123
list @1list1 or list_ one

Define variables

Variables can be defined at multiple locations in an Ansible project. However, these variables can be roughly reduced to three range levels:

Global variables: variables set from the command line or Ansible configuration

Play range: variables set in play and related structures

Host scope: tasks collected or registered by lists, facts, and variables set on host groups and individual hosts

If a variable with the same name is defined in more than one xekl (level), the variable with the highest priority is used. Narrow scope takes precedence over broader scope: variables defined by the manifest will be overwritten by variables defined by playbook, which will be overwritten by variables defined on the command line.

Variables in playbook

Variables play an important role in Ansible Playbook because they can simplify the management of variable data in playbook.

Defining variables in playbook

When you write playbook, you can define your own variables and then call these values in your tasks.

The playbook variable can be defined in many ways. A common way is to put variables in the vars block at the beginning of Playbook:

---
- hosts: server1
  remote_user: tom
  vars:                              //Variable module
    IP: 192.168.56.199              //Define variables
    NAME: node4
  tasks:
    - name: test
      lineinfile:
        path: /etc/hosts
        line: "{{ IP  }} {{ NAME  }}"   //If {{IP}} is preceded by a letter, do not type ""
        state: present


//View results
[root@server1 etc]# cat  hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.56.130 server1
192.168.56.199 node4

You can also define variables outside the playbook

You can also define the playbook variable in an external file. Instead of using the vars block in the playbook, you can use vars instead_ Files directive, followed by a list of external variable file names relative to the playbook position:

//Write variable file

[root@control book]# ls
ansible.cfg  node1.yml  playbook  vars
[root@control book]#  cat  vars/time.yml 
IP: 192.168.56.179
NAME: node7

//The variable file must be at the same level as the manifest file, otherwise the variable file cannot be found

[root@control vars]# tree  /opt/book/vars/
/opt/book/vars/
├── ansible.cfg
├── host_vars
│   ├── 192.168.56.130
│   ├── node1.yml
│   └── time.yml
└── playbook

//Modify file

[root@control vars]# cat  node1.yml 
---
- hosts: server1
  remote_user: tom
  vars_files:           //External variable module
    - vars/time.yml     //Variable address
  tasks:
    - name: test
      lineinfile:
        path: /etc/hosts
        line: "{{ IP  }} {{ NAME  }}"   //Reference variable
        state: present

//implement
[root@control vars]# ansible-playbook node1.yml 

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

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

TASK [test] ********************************************************************
changed: [192.168.56.130]

PLAY RECAP *********************************************************************
192.168.56.130             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


//see
[root@server1 etc]# cat  hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.56.130 server1
192.168.56.199 node4
192.168.56.179 node7

Host and group variables

The list variables directly applied to the host are divided into two categories:

  • Host variable, applied to a specific host
  • Group management, which applies to a host group or all hosts in a group of hosts

Host variables take precedence over group variables, but variables defined in playbook take precedence over both

Variables in playbook > host variables > group variables

One way to define host and group variables is to define them directly in the manifest file.

This is an old practice and is not recommended, but you may encounter it in your future work.

Define host variables:

[root@control vars]# cat  playbook 
[server1]
192.168.56.130   ansible_user=root  ansible_password=1

Populate host and group variables with directories

The preferred way to define variables for hosts and host groups is to create groups in the same working directory as the manifest file or directory_ Vars and host_vars two directories. These two directories contain files for defining group variables and host variables, respectively.

The recommended practice is to use host_vars and groups_ The vars directory defines manifest variables instead of defining them directly in the manifest file.

Create Host Directory

[root@control vars]# tree  /opt/book/vars/
/opt/book/vars/
├── ansible.cfg
├── host_vars
│   ├── 192.168.56.131
│   ├── node1.yml
│   └── time.yml
└── playbook

//Write host directory file
[root@control vars]# cat  host_vars/192.168.56.131 
ansibel_user: root
ansible_password: 1

//View manifest file
[root@control vars]# cat  playbook 
[server1]
192.168.56.131 


//test
[root@control vars]# ansible all -m ping
192.168.56.131 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}


//Define host variables
[root@control vars]# cat  host_vars/192.168.56.131 
ansibel_user: root
ansible_password: 1
IP: 192.168.56.199
NAME: www


//implement
[root@control vars]# cat  host_vars/node1.yml 
---
- hosts: '192.168.56.131'
  tasks:
    - name: test
      lineinfile:
         path: /etc/hosts
         line: "{{ IP  }} {{ NAME }}"
         state: present

//View results
[root@localhost ~]# cat   /etc/hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.56.199 www

If the internal and external variables are the same, the internal variable shall prevail

[root@control vars]# cat  host_vars/192.168.56.131 
ansibel_user: root
ansible_password: 1
IP: 192.168.56.110        //Define external variables
NAME: QQQ

[root@control vars]# cat  host_vars/node1.yml 
---
- hosts: '192.168.56.131'
  gather_facts: no
  vars:          
    IP: 192.168.56.188      //Define local variables
    NAME: LLL
  tasks:
    - name: test
      lineinfile:
         path: /etc/hosts
         line: "{{ IP  }} {{ NAME }}"
         state: present
//implement
[root@control vars]# ansible-playbook host_vars/node1.yml 

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

TASK [test] ********************************************************************
changed: [192.168.56.131]

PLAY RECAP *********************************************************************
192.168.56.131             : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 


//View results
[root@localhost ~]# cat   /etc/hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.56.199 www
192.168.56.188 LLL       //Only local variables are added


Use array as variable

In addition to allocating the configuration data related to the same element (package list, service list, user list, etc.) to multiple variables, arrays can also be used. One advantage of this approach is that arrays are browsable

Create group:

[root@control vars]# cat   host_vars/192.168.56.131  
ansibel_user: root
ansible_password: 1

info:
  node2:
    ip: 5.5.5.5
    max: www.aliyun.com
  node3:
    ip: 6.6.6.6
    min: www.baidu.com


[root@control vars]# cat  host_vars/node1.yml 
---
- hosts: '192.168.56.131'
  gather_facts: no
  vars:
    IP: 192.168.56.188
    NAME: LLL
  tasks:
    - name: test
      lineinfile:
         path: /etc/hosts
         line: "{{ info.node2.ip }} {{ info.node3.min  }}"
         state: present


"{{info.node2.ip}} {{info.node3.min}}"


//View results
[root@localhost ~]# cat   /etc/hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
5.5.5.5 www.baidu.com

Capture command output using registered variables

You can use the register statement to capture command output. The output is stored in a temporary variable and can then be used in the playbook for debugging purposes or for other purposes, such as specific configurations based on command output.

Standard input: STDIN

Standard output: STDOUT

Standard error: STDERR

The following playbook demonstrates how to capture command output for debugging purposes:

[root@control vars]# cat  host_vars/node1.yml ---
- hosts: '192.168.56.131'
  gather_facts: no
  tasks:
    - name: test
      command: "echo hello time"   //Output results
      register: result      //Registered name

    - debug: var=result     //

[root@control vars]# ansible-playbook host_vars/node1.yml  

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

TASK [test] ********************************************************************
changed: [192.168.56.131]

TASK [debug] *******************************************************************
ok: [192.168.56.131] => {
    "result": {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/libexec/platform-python"
        },
        "changed": true,
        "cmd": [
            "echo",
            "hello",
            "time"
        ],
        "delta": "0:00:00.001394",
        "end": "2021-07-22 23:01:09.288632",
        "failed": false,
        "rc": 0,
        "start": "2021-07-22 23:01:09.287238",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "hello time",
        "stdout_lines": [
            "hello time"     //capture
        ]
    }
}

PLAY RECAP *********************************************************************
192.168.56.131             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

//Capture printout results

[root@control vars]# cat  host_vars/node1.yml ---
- hosts: '192.168.56.131'
  gather_facts: no
  tasks:
    - name: test
      command: "echo hello time"
      register: result

    - name: create 
      shell: "echo {{ result['stdout'] }} > /opt/abc"
//The file / opt/abc must exist on the controlled host

[root@control vars]# ansible-playbook host_vars/node1.yml  

//implement
PLAY [192.168.56.131] **********************************************************

TASK [test] ********************************************************************
changed: [192.168.56.131]

TASK [create] ******************************************************************
changed: [192.168.56.131]

PLAY RECAP *********************************************************************
192.168.56.131             : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


//View results
[root@localhost opt]# cat  abc 
hello time


Management Secrets

Ansible may need to access sensitive data such as passwords or API keys in order to be able to configure the managed host. Typically, this information may be stored in plain text in manifest variables or other ansible files. However, if so, any user who has access to ansible files or the version control system storing these ansible files can access this sensitive data. This indicates a security risk.

Ansible Vault provided by ansible can encrypt and decrypt any structured data file used by ansible. To use Ansible Vault, you can create, edit, encrypt, decrypt, and view files through a command-line tool called Ansible Vault. Ansible Vault can encrypt any structured data file used by ansible. This may include manifest variables, variable files contained in the playbook, variable files passed as parameters when the playbook is executed, or variables defined in the ansible role.

To create an encrypted file:

//Create encrypted file
[root@control vars]# ansible-vault create took.ymlNew Vault password: 
Confirm New Vault password: 
[root@control vars]# ls
ansible.cfg  host_vars  took.yml
group_vars   playbook

//see
[root@control group_vars]# ls
took.yml  //Encrypted file
[root@control group_vars]# cat  took.yml 
$ANSIBLE_VAULT;1.1;AES256
35313330376339343338366131383335623366396631663436383238646266383136353062356230
3437373338633230643133666563346463616265326566340a353336633934633939313835333338
36363034306364383236366434306537623635613565336562626235643566323735346166613537
3932623638393866620a396434663538663635373235353634386165623836386434323532653065
3339

View encrypted files

[root@control group_vars]# ansible-vault view took.yml 
Vault password:    //Enter password to view
123

[root@control group_vars]# ls  -a
.  ..  .passwd  took.yml

[root@control group_vars]# cat .passwd / / create a password file
123456


//Create an encrypted file with a password file
[root@control vars]# ansible-vault create  --vault-password-file=group_vars/.passwd group_vars/pook.yml
[root@control vars]# ansible-vault view group_vars/pook.yml 

//Enter password to view
[root@control vars]# ansible-vault view group_vars/pook.yml 
Vault password: 
port: 9090

//View encrypted files with password files
[root@control vars]# ansible-vault view --vault-password-file=group_vars/.passwd  group_vars/pook.yml 
port: 9090

Encrypt existing files

[root@control vars]# ls
ansible.cfg  group_vars  host_vars  playbook

[root@control vars]# ansible-vault encrypt --vault-password-file=group_vars/.passwd playbook 
Encryption successful
//Password encrypted playbook file

[root@control vars]# cat  playbook 
$ANSIBLE_VAULT;1.1;AES256
35336637323031346432353466306636366137303233356530653339353435663638313932313730
3032346163636538613633326661323836623638626530370a323163303266623265306631653838
35393034386139326234336661626638373166323461653063393435366435363837656231323630
3766386334663761640a353733633136343761383830356636323836663035333463653738343466
64316638623238663932356365346431623530343234313462373431303031366466

//View encrypted files with password
[root@control vars]# ansible-vault view --vault-password-file=group_vars/.passwd playbook 
[server1]
192.168.56.131  


Decrypt existing files

[root@control vars]# ansible-vault decrypt --vault-password-file=group_vars/.passwd playbook //playbook encrypted file 
Decryption successful
[root@control vars]# cat  playbook 
[server1]
192.168.56.131  

Change password for encrypted file

[root@control group_vars]# ls
pook.yml  took.yml

//Change Password
[root@control group_vars]# ansible-vault rekey pook.yml 
Vault password: 
New Vault password: 
Confirm New Vault password: 
//You must know the password to change the new password

//View file with new password
[root@control group_vars]# ansible-vault view --vault-password-file=pk pook.yml 
port: 9090

Keywords: Linux ansible

Added by StoneJunkie on Wed, 19 Jan 2022 18:51:38 +0200