When managing target nodes, some operations require the use of passwords to allow access, but Ansible is an automated configuration management tool, and the act of requiring interactive password entry during the automation phase should be frustrating.
In general, non-interactive scenarios are:
- (1). Write sensitive data to a file (such as writing a variable file) and then read it, which is not safe;
- (2). Define the environment variables corresponding to sensitive data, the disadvantage is that some client tools do not necessarily support this way, and this scheme is not convenient enough;
- (3). Use the command line option, but the disadvantage is that it is not safe, and Ansible does not support this function;
- (4).expect类工具,缺点是不方便。
Ansible itself provides a more convenient and secure solution: Vault encryption, which uses the AES256 encryption algorithm to protect Ansible.
Prior to Ansible 2.4, the Vault encryption feature was not user-friendly, and the features were restrictive, such as all tasks involved in encryption had to share the same password, for example, earlier versions could not encrypt some strings. The current Ansible version of Vault encryption is more user-friendly, and this article will introduce the friendly version of Vault encryption in detail.
1. An example of getting started: create an encrypted file
Ansible uses the ansible-valut command to complete vault encryption and decryption related operations, and it has many subcommands, such as the create subcommand to create encrypted files, the view subcommand to view encrypted files, and so on, and the options of these subcommands are mostly similar.
$ ansible-vault --help
positional arguments:
{create,decrypt,edit,view,encrypt,encrypt_string,rekey}
create 创建新的文件并加密
decrypt 解密已加密的文件
edit 编辑已加密文件的内容
view 查看已加密文件的内容
encrypt 加密已存在的未加密文件
encrypt_string 加密一段字符串
rekey 修改已加密文件的Vault ID和凭据密码
For example, use the create subcommand to create an encrypted file passwd_prompt.yml and write a password variable to this file.
$ ansible-vault create --vault-id @prompt passwd_prompt.yml
New vault password (default): # 提示用户输入的
Confirm new vault password (default): # 提示用户输入的
--- # 自动打开编辑器,比如打开vim
mypasswd: 123456 # 输入一个变量
# 保存并退出
The --vault-id @prompt is used as an argument to ansible-vault, which interactively prompts the user for a password that is required to encrypt the encrypted file passwd_prompt.yml when ansible-vault create is executed. To put it simply, this file holds the encrypted password data, but the password is also required to access the file. For the sake of distinction, this password will be referred to later in this article as the "credential password".
In the example above, I set a variable mypasswd with a value of 123456. When you exit the editor, the file is automatically encrypted. For example:
# 为排版需求,我截断了一部分字符
$ cat passwd_prompt.yml
$ANSIBLE_VAULT;1.1;AES256
316336393534333831363334363633653232303268
373962616633356439393830353430373230613239
323530393466363035633164306133663030303839
6137616561353337660a3430313931376266643034
373234623839383838386537643635666232303563
If you want to view the ciphertext, you can use the view subcommand of ansible-vault, which also requires the credential password.
$ ansible-vault view --vault-id @prompt passwd_prompt.yml
Vault password (default): # 输入凭据密码后将展示如下内容
---
mypasswd: 123456
Also, remember the first line of $ANSIBLE_VAULT in the encrypted file for the time being; 1.1; AES256, which explains the meaning of each field in this row later.
2. How to provide Vault ID and credential password
In the example above, the option --vault-id @prompt is used, and its behavior is to interactively prompt the user for a credential password.
Actually,-- full usage of the valut-id option looks like this:
--vault-id label@prompt
--vault-id label@path_to_normal_txt_file
--vault-id label@path_to_script_file
Before we explain these usages, a little bit about the history of Ansible Vault: in previous versions of Ansible, only one credential password was available for each ansbile or ansible-playbook command, which made it possible to use only one password for all the encryption involved in this task.
--vault-id dev_mysql@xxx
--vault-id test_mysql@xxx
--vault-id prod_mysql@xxx
You can also omit the vault ID and use the default vault ID uniformly.
--vault-id What is xxx in the label@xxx? There are three sources of credential passwords:
- (1).prompt: prompt is a fixed value that prompts the user to provide the credential password in an interactive manner
- (2). The file name of a common file: for example, "a.txt", which means that the password is read from the file
- (3). Script file name: indicates that the password is obtained from the script execution result
For example, there are common file a.txt:
echo '123456' >a.txt
There are script files a.sh which are as follows (py scripts, perl scripts, or even programs, etc., as long as the password is output to standard output and has executable permissions):
#!/bin/bash
echo 123456
So let's create three encrypted files with three different credential cipher sources:
$ ansible-vault create --vault-id id1@prompt first_encrypted.yml
$ ansible-vault create --vault-id [email protected] second_encrypted.yml
$ ansible-vault create --vault-id [email protected] third_encrypted.yml
If the Vault ID is omitted, then:
$ ansible-vault create --vault-id @prompt first_encrypted1.yml
$ ansible-vault create --vault-id a.txt second_encrypted1.yml
$ ansible-vault create --vault-id @a.txt second_encrypted1.yml
$ ansible-vault create --vault-id a.sh third_encrypted1.yml
$ ansible-vault create --vault-id @a.sh third_encrypted1.yml
When you want to access encrypted data, such as the ansible command, ansible-playbook command, and ansible-vault command, you need to specify the same vault ID as the encrypted data, and you can specify multiple vaults.
For example:
# 以文件的方式获取凭据密码
ansible-vault view --vault-id [email protected] second_encrypted.yml
# 以交互式方式提供凭据密码
ansible-vault view --vault-id id2@prompt second_encrypted.yml
# 指定多个凭据密码,通常用在ansible-playbook命令中,
# 比如变量文件中多个敏感数据使用了不同的vault id加密
ansible-playbook --vault-id [email protected] --vault-id [email protected] main.yml
3. Encrypt existing files
If you want to encrypt an already existing file, use ansible-vault encrypt, which is almost the same as the create subcommand.
For example, plain.yml file is currently a plaintext variable file:
$ cat plain.yml
---
plain_passwd: 123456
port: 2312
of Encryption:
$ ansible-vault encrypt --vault-id [email protected] plain.yml
Encryption successful
$ cat plain.yml
$ANSIBLE_VAULT;1.2;AES256;id1
336130623037643739633938313061336431
363838333864616665623034336439316234
643337663235366365316332643063653863
3534303533633334340a6438326433616236
383566346533653135313633633139613133
353935653734363833616464326662336132
Multiple copies of data can be loaded at once, but they use the same Vault ID and password.
$ ansible-vault encrypt --vault-id [email protected] foo.yml bar.yml baz.yml
4. The meaning of the encryption protocol header
In each encrypted file, a line of header data is included. You can use the cat command to view this, for example:
$ cat plain.yml
$ANSIBLE_VAULT;1.2;AES256;id1 #<==加密协议头
336130623037643739633938313061336431
363838333864616665623034336439316234
643337663235366365316332643063653863
3534303533633334340a6438326433616236
383566346533653135313633633139613133
353935653734363833616464326662336132
There are two types of protocol headers:
$ANSIBLE_VAULT;1.1;AES256
$ANSIBLE_VAULT;1.2;AES256;id1
The first of these fields can only be $ANSIBLE_VAULT at the moment.
The second field 1.1, 1.2 represents the version number of the vault format, which is 1.2 if the vault ID is given, or 1.1 if the default vault ID is used. The old version still has version 1.0, but now it will not be set to this version number, and the encrypted data of version 1.0 can only be read.
The third field currently only supports AES256 encryption.
The fourth field, if the vault ID is specified during encryption, the fourth field is saved as the vault ID, otherwise the fourth field is not set.
If you forget the vault ID of an encrypted file, you can directly view the encrypted file with the cat command to obtain the ID, or you can extract it directly.
$ awk -F';' 'NR==1{print $4}' encrypted.yml
id2
If Ansible needs to access multiple vault-encrypted files, it will automatically look for the user-provided credentials and passwords based on the vault ID.
For example, for the following command, two vault IDs and two passwords are naturally required if two encrypted variable files are referenced in the main.yml. When the first file needs to be decrypted during the execution of a task, Ansible will automatically obtain its vault ID and look for the corresponding vault ID and the source of its credential password from the command line.
$ ansible-playbook --vault-id [email protected] --vault-id [email protected] main.yml
5. Decrypt encrypted files
For a vault-encrypted file, the file can be decrypted using ansible-vault decrypt.
For example, to decrypt the encrypted plain.yml in the example above:
$ ansible-vault decrypt --vault-id [email protected] plain.yml
Decryption successful
$ cat plain.yml
---
plain_passwd: 123456
port: 2312
Decrypt multiple files:
$ ansible-vault decrypt --vault-id [email protected] foo.yml bar.yml baz.yml
6. Change the vault ID and password
For a vault-encrypted file, you can use the ansible-vault rekey to modify its vault ID or its credential password.
For example, first_passwd.yml is an encrypted file:
$ cat first_encrypted.yml
$ANSIBLE_VAULT;1.2;AES256;id1
6361623434363834363065643838346361383830
3038366239353535663330653463376666346636
6439663030643839623965613563343632343234
3739313638363262390a62666466343864626466
3235633862306366383161663765663962306132
To modify its Vault ID and credential password:
$ ansible-vault rekey --vault-id [email protected] \
--new-vault-id [email protected] \
first_encrypted.yml
Rekey successful
Looking at the encrypted content, both the vault ID and the ciphertext have changed:
$ cat first_encrypted.yml
$ANSIBLE_VAULT;1.2;AES256;id2
366666343166313633396135346464653537373936
343936653437616235316630333538343139336361
656330646535656335376662623062343863306561
3033383533306266620a3866396139663235303931
313230666235303833633330653863323738623339
Of course, you can also modify only the Vault ID or just the credential password, just leave one of the label@xxx unchanged. For example:
# Vault ID不变,只修改凭据密码
$ ansible-vault rekey --vault-id [email protected] \
--new-vault-id [email protected] \
first_encrypted.yml
# 凭据密码,只修改Vault ID
$ ansible-vault rekey --vault-id [email protected] \
--new-vault-id [email protected] \
first_encrypted.yml
7. Edit the contents of the encrypted file
If you want to edit the contents of a vault-encrypted file, use the ansible-vault edit command.
$ ansible-vault edit --vault-id [email protected] first_encrypted.yml
It will automatically open the default editor (like vim) for the user to edit. The internal process is to create a temporary file with the original plaintext data (when opening vim, the temporary file name is seen in the status bar at the bottom of vim), and the operations modified by the user are carried out in this temporary file, and when saved, the original file will be automatically encrypted and overwritten.
It can also be decrypted, modified, and re-encrypted, and it can be done in a non-interactive way.
ansible-vault decrypt xxx
sed -i 'xx' xxx
ansible-vault encrypt xxx
8. Use Vault to encrypt files in the ansible-playbook task
The original goal of encrypting data is to hide sensitive data in playbook, task, or variable files. What about files that use encryption?
For example, a playbook file named test.yml would look like this:
---
- hosts: localhost
gather_facts: no
vars_files:
- first_passwd.yml
- second_passwd.yml
tasks:
- name: debug var in first_passwd
debug:
var: passwd1
- name: debug var in second_passwd
debug:
var: passwd2
In this playbook, two variable files first_passwd.yml and second_passwd.yml are introduced, and then two tasks are used to access the two variables defined in the two variable files, passwd1 and passwd2.
The contents of these two variable files are as follows:
# first_passwd.yml内容:
---
passwd1: "passwd in first_passwd"
# second_passwd.yml内容:
---
passwd2: "passwd in second_passwd"
Encrypt these two files with a different Vault ID and credential password:
$ echo 'abcdef' >a.txt
$ echo 'ABCDEF' >b.txt
$ ansible-vault encrypt --vault-id [email protected] first_passwd.yml
$ ansible-vault encrypt --vault-id [email protected] second_passwd.yml
Then execute the playbook, because there are multiple encrypted files to be accessed, and the vault ID is different, and the credential password is also different, so you need to specify multiple --vault-id options. As follows:
$ ansible-playbook --vault-id [email protected] --vault-id [email protected] test.yml
......
TASK [debug var in first_passwd] *********************
ok: [localhost] => {
"passwd1": "passwd in first_passwd"
}
TASK [debug var in second_passwd] ********************
ok: [localhost] => {
"passwd2": "passwd in second_passwd"
}
......
9. Encrypt the string and embed the YAML file
With ansible-vault encrypt_string you can encrypt a string.
For example:
$ ansible-vault encrypt_string --vault-id [email protected] 'hello' --name 'mysql_pass'
mysql_pass: !vault |
$ANSIBLE_VAULT;1.2;AES256;id1
39623437656130313338613033383464376437
66303938343635623430353664303334623138
33353435366262653437663839316261623664
6362633233653237360a343439376437633733
6262
Encryption successful
where hello is the plaintext data that needs to be encrypted,-- name mysql_pass is the key in YAML, for example, it can be used as the name of a variable. The --name option can also be omitted.
$ ansible-vault encrypt_string --vault-id [email protected] 'hello'
!vault |
$ANSIBLE_VAULT;1.2;AES256;id1
61336334663365656361316532356133623
62343863366463396338333933343635373
39656461643962643831653561313266366
6432316334653339340a336565333361346
3635
Encryption successful
After encrypting a string, you can copy the encrypted string to the YAML file. For example, here is a variable file for MySQL Role:
---
mysql_port: 3306
mysql_user: root
mysql_pass: !vault |
$ANSIBLE_VAULT;1.2;AES256;id1
39623437656130313338613033383464376437
66303938343635623430353664303334623138
33353435366262653437663839316261623664
6362633233653237360a343439376437633733
6262
mysql_host: 192.168.200.27
In addition, the ansible-vault encrypt_string can also get the plaintext data to be encrypted from the standard input:
$ ansible-vault encrypt_string --vault-id [email protected] --stdin-name 'mysql_pass' <<<"hello"
mysql_pass: !vault |
$ANSIBLE_VAULT;1.2;AES256;id1
35386538393939633862626361323735306
63383966356265333336303231313735376
38346566373262663866363631373539313
6531643131306537350a363232656661303
6333
Encryption successful
# 或者
$ echo -n 'hello' | ansible-vault encrypt_string --vault-id [email protected] --stdin-name 'mysql_pass'
Note that when getting data to be encrypted from standard input, the option used is --stdin-name, not --stdin --name.
10. Speed up the process of encryption and decryption
If you want to encrypt and decrypt a large number of files, according to the official documentation, you can install the cryptography package to solve the problem.
pip install cryptography
11. Vault encryption best practices
Ansible Vault can encrypt all files in yaml and json formats, but it is not recommended to directly encrypt a file that contains a lot of data, because it is inconvenient to view and modify task files after encryption, and it is recommended to encrypt files that only contain sensitive data.
For example, consider the following variable file:
---
mysql_port: 3306
mysql_user: root
mysql_pass: xxxxxxxx
mysql_host: 192.168.200.27
In fact, the file only mysql_pass sensitive data that you want to hide, and the recommended approach is to use jinja2 in this file to refer to the variable that starts with the vault_ again, and the vault_ starts so that you can see at a glance that this is the variable encrypted by Vault. For example:
---
mysql_port: 3306
mysql_user: root
mysql_pass: "{{vault_mysql_pass}}"
mysql_host: 192.168.200.27
The referenced variable is then defined in a separate file vault_mysql_pass and the variable file is encrypted. For example, define vault_mysql_pass variables in a mysql_pass.yml file:
---
vault_mysql_pass: "abcdef"
of Encryption:
$ ansible-vault encrypt --vault-id [email protected] mysql_pass.yml
Link: https://www.cnblogs.com/f-ck-need-u/p/17718508.html
(The copyright belongs to the original author, invaded and deleted)
Pay attention to the good of the industry: IT operation and maintenance base camp, and get the 60 G "Network Work + System Gift Package"