1.. _vault:
2
3Ansible Vault
4=============
5
6.. contents:: Topics
7
8Ansible Vault is a feature of ansible that allows you to keep sensitive data such as passwords or keys in encrypted files, rather than as plaintext in playbooks or roles. These vault files can then be distributed or placed in source control.
9
10To enable this feature, a command line tool - :ref:`ansible-vault` - is used to edit files, and a command line flag (:option:`--ask-vault-pass <ansible-playbook --ask-vault-pass>`, :option:`--vault-password-file <ansible-playbook --vault-password-file>` or  :option:`--vault-id <ansible-playbook --vault-id>`) is used. Alternately, you may specify the location of a password file or command Ansible to always prompt for the password in your ansible.cfg file. These options require no command line flag usage.
11
12For best practices advice, refer to :ref:`best_practices_for_variables_and_vaults`.
13
14.. _what_can_be_encrypted_with_vault:
15
16What Can Be Encrypted With Vault
17````````````````````````````````
18
19File-level encryption
20^^^^^^^^^^^^^^^^^^^^^
21
22Ansible Vault can encrypt any structured data file used by Ansible.
23
24This can include "group_vars/" or "host_vars/" inventory variables, variables loaded by "include_vars" or "vars_files", or variable files passed on the ansible-playbook command line with ``-e @file.yml`` or ``-e @file.json``.  Role variables and defaults are also included.
25
26Ansible tasks, handlers, and so on are also data so these can be encrypted with vault as well. To hide the names of variables that you're using, you can encrypt the task files in their entirety.
27
28Ansible Vault can also encrypt arbitrary files, even binary files.  If a vault-encrypted file is
29given as the ``src`` argument to the :ref:`copy <copy_module>`, :ref:`template <template_module>`,
30:ref:`unarchive <unarchive_module>`, :ref:`script <script_module>` or :ref:`assemble
31<assemble_module>` modules, the file will be placed at the destination on the target host decrypted
32(assuming a valid vault password is supplied when running the play).
33
34.. note::
35    The advantages of file-level encryption are that it is easy to use and that password rotation is straightforward with :ref:`rekeying <rekeying_files>`.
36    The drawback is that the contents of files are no longer easy to access and read. This may be problematic if it is a list of tasks (when encrypting a variables file, :ref:`best practice <best_practices_for_variables_and_vaults>` is to keep references to these variables in a non-encrypted file).
37
38
39Variable-level encryption
40^^^^^^^^^^^^^^^^^^^^^^^^^
41
42Ansible also supports encrypting single values inside a YAML file, using the `!vault` tag to let YAML and Ansible know it uses special processing. This feature is covered in more detail :ref:`below <encrypt_string_for_use_in_yaml>`.
43
44.. note::
45    The advantage of variable-level encryption is that files are still easily legible even if they mix plaintext and encrypted variables.
46    The drawback is that password rotation is not as simple as with file-level encryption: the :ref:`rekey <ansible_vault_rekey>` command does not work with this method.
47
48
49.. _vault_ids:
50
51Vault IDs and Multiple Vault Passwords
52``````````````````````````````````````
53
54
55A vault ID is an identifier for one or more vault secrets;
56Ansible supports multiple vault passwords.
57
58Vault IDs provide labels to distinguish between individual vault passwords.
59
60To use vault IDs, you must provide an ID *label* of your choosing and a *source* to obtain its password (either ``prompt`` or a file path):
61
62.. code-block:: bash
63
64   --vault-id label@source
65
66This switch is available for all Ansible commands that can interact with vaults: :ref:`ansible-vault`, :ref:`ansible-playbook`, etc.
67
68Vault-encrypted content can specify which vault ID it was encrypted with.
69
70For example, a playbook can now include a vars file encrypted with a 'dev' vault
71ID and a 'prod' vault ID.
72
73.. note:
74    Older versions of Ansible, before 2.4, only supported using one single vault password at a time.
75
76
77.. _creating_files:
78
79Creating Encrypted Files
80````````````````````````
81
82To create a new encrypted data file, run the following command:
83
84.. code-block:: bash
85
86   ansible-vault create foo.yml
87
88First you will be prompted for a password. After providing a password, the tool will launch whatever editor you have defined with $EDITOR, and defaults to vi.  Once you are done with the editor session, the file will be saved as encrypted data.
89
90The default cipher is AES (which is shared-secret based).
91
92To create a new encrypted data file with the Vault ID 'password1' assigned to it and be prompted for the password, run:
93
94.. code-block:: bash
95
96   ansible-vault create --vault-id password1@prompt foo.yml
97
98
99.. _editing_encrypted_files:
100
101Editing Encrypted Files
102```````````````````````
103
104To edit an encrypted file in place, use the :ref:`ansible-vault edit <ansible_vault_edit>` command.
105This command will decrypt the file to a temporary file and allow you to edit
106the file, saving it back when done and removing the temporary file:
107
108.. code-block:: bash
109
110   ansible-vault edit foo.yml
111
112To edit a file encrypted with the 'vault2' password file and assigned the 'pass2' vault ID:
113
114.. code-block:: bash
115
116   ansible-vault edit --vault-id pass2@vault2 foo.yml
117
118
119.. _rekeying_files:
120
121Rekeying Encrypted Files
122````````````````````````
123
124Should you wish to change your password on a vault-encrypted file or files, you can do so with the rekey command:
125
126.. code-block:: bash
127
128    ansible-vault rekey foo.yml bar.yml baz.yml
129
130This command can rekey multiple data files at once and will ask for the original
131password and also the new password.
132
133To rekey files encrypted with the 'preprod2' vault ID and the 'ppold' file and be prompted for the new password:
134
135.. code-block:: bash
136
137    ansible-vault rekey --vault-id preprod2@ppold --new-vault-id preprod2@prompt foo.yml bar.yml baz.yml
138
139A different ID could have been set for the rekeyed files by passing it to ``--new-vault-id``.
140
141.. _encrypting_files:
142
143Encrypting Unencrypted Files
144````````````````````````````
145
146If you have existing files that you wish to encrypt, use
147the :ref:`ansible-vault encrypt <ansible_vault_encrypt>` command.  This command can operate on multiple files at once:
148
149.. code-block:: bash
150
151   ansible-vault encrypt foo.yml bar.yml baz.yml
152
153To encrypt existing files with the 'project' ID and be prompted for the password:
154
155.. code-block:: bash
156
157   ansible-vault encrypt --vault-id project@prompt foo.yml bar.yml baz.yml
158
159.. note::
160
161   It is technically possible to separately encrypt files or strings with the *same* vault ID but *different* passwords, if different password files or prompted passwords are provided each time.
162   This could be desirable if you use vault IDs as references to classes of passwords (rather than a single password) and you always know which specific password or file to use in context. However this may be an unnecessarily complex use-case.
163   If two files are encrypted with the same vault ID but different passwords by accident, you can use the :ref:`rekey <rekeying_files>` command to fix the issue.
164
165
166.. _decrypting_files:
167
168Decrypting Encrypted Files
169``````````````````````````
170
171If you have existing files that you no longer want to keep encrypted, you can permanently decrypt
172them by running the :ref:`ansible-vault decrypt <ansible_vault_decrypt>` command.  This command will save them unencrypted
173to the disk, so be sure you do not want :ref:`ansible-vault edit <ansible_vault_edit>` instead:
174
175.. code-block:: bash
176
177    ansible-vault decrypt foo.yml bar.yml baz.yml
178
179
180.. _viewing_files:
181
182Viewing Encrypted Files
183```````````````````````
184
185If you want to view the contents of an encrypted file without editing it, you can use the :ref:`ansible-vault view <ansible_vault_view>` command:
186
187.. code-block:: bash
188
189    ansible-vault view foo.yml bar.yml baz.yml
190
191
192.. _encrypt_string_for_use_in_yaml:
193
194Use encrypt_string to create encrypted variables to embed in yaml
195`````````````````````````````````````````````````````````````````
196
197The :ref:`ansible-vault encrypt_string <ansible_vault_encrypt_string>` command will encrypt and format a provided string into a format
198that can be included in :ref:`ansible-playbook` YAML files.
199
200To encrypt a string provided as a cli arg:
201
202.. code-block:: bash
203
204    ansible-vault encrypt_string --vault-password-file a_password_file 'foobar' --name 'the_secret'
205
206Result::
207
208    the_secret: !vault |
209          $ANSIBLE_VAULT;1.1;AES256
210          62313365396662343061393464336163383764373764613633653634306231386433626436623361
211          6134333665353966363534333632666535333761666131620a663537646436643839616531643561
212          63396265333966386166373632626539326166353965363262633030333630313338646335303630
213          3438626666666137650a353638643435666633633964366338633066623234616432373231333331
214          6564
215
216To use a vault-id label for 'dev' vault-id:
217
218.. code-block:: bash
219
220    ansible-vault encrypt_string --vault-id dev@a_password_file 'foooodev' --name 'the_dev_secret'
221
222Result::
223
224    the_dev_secret: !vault |
225              $ANSIBLE_VAULT;1.2;AES256;dev
226              30613233633461343837653833666333643061636561303338373661313838333565653635353162
227              3263363434623733343538653462613064333634333464660a663633623939393439316636633863
228              61636237636537333938306331383339353265363239643939666639386530626330633337633833
229              6664656334373166630a363736393262666465663432613932613036303963343263623137386239
230              6330
231
232To encrypt a string read from stdin and name it 'db_password':
233
234.. code-block:: bash
235
236    echo -n 'letmein' | ansible-vault encrypt_string --vault-id dev@a_password_file --stdin-name 'db_password'
237
238.. warning::
239
240   This method leaves the string in your shell history. Do not use it outside of testing.
241
242Result::
243
244    Reading plaintext input from stdin. (ctrl-d to end input)
245    db_password: !vault |
246              $ANSIBLE_VAULT;1.2;AES256;dev
247              61323931353866666336306139373937316366366138656131323863373866376666353364373761
248              3539633234313836346435323766306164626134376564330a373530313635343535343133316133
249              36643666306434616266376434363239346433643238336464643566386135356334303736353136
250              6565633133366366360a326566323363363936613664616364623437336130623133343530333739
251              3039
252
253To be prompted for a string to encrypt, encrypt it, and give it the name 'new_user_password':
254
255
256.. code-block:: bash
257
258    ansible-vault encrypt_string --vault-id dev@a_password_file --stdin-name 'new_user_password'
259
260Output::
261
262    Reading plaintext input from stdin. (ctrl-d to end input)
263
264User enters 'hunter2' and hits ctrl-d.
265
266.. warning::
267
268   Do not press Enter after supplying the string. That will add a newline to the encrypted value.
269
270Result::
271
272    new_user_password: !vault |
273              $ANSIBLE_VAULT;1.2;AES256;dev
274              37636561366636643464376336303466613062633537323632306566653533383833366462366662
275              6565353063303065303831323539656138653863353230620a653638643639333133306331336365
276              62373737623337616130386137373461306535383538373162316263386165376131623631323434
277              3866363862363335620a376466656164383032633338306162326639643635663936623939666238
278              3161
279
280See also :ref:`single_encrypted_variable`
281
282After you added the encrypted value to a var file (vars.yml), you can see the original value using the debug module.
283
284.. code-block:: console
285
286   ansible localhost -m debug -a var="new_user_password" -e "@vars.yml" --ask-vault-pass
287   Vault password:
288
289   localhost | SUCCESS => {
290       "new_user_password": "hunter2"
291   }
292
293
294.. _providing_vault_passwords:
295
296Providing Vault Passwords
297`````````````````````````
298
299When all data is encrypted using a single password the :option:`--ask-vault-pass <ansible-playbook --ask-vault-pass>`
300or :option:`--vault-password-file <ansible-playbook --vault-password-file>` cli options should be used.
301
302For example, to use a password store in the text file :file:`/path/to/my/vault-password-file`:
303
304.. code-block:: bash
305
306    ansible-playbook --vault-password-file /path/to/my/vault-password-file site.yml
307
308To prompt for a password:
309
310.. code-block:: bash
311
312    ansible-playbook --ask-vault-pass site.yml
313
314To get the password from a vault password executable script :file:`my-vault-password.py`:
315
316.. code-block:: bash
317
318    ansible-playbook --vault-password-file my-vault-password.py
319
320The config option :ref:`DEFAULT_VAULT_PASSWORD_FILE` can be used to specify a vault password file so that the
321:option:`--vault-password-file <ansible-playbook --vault-password-file>` cli option does not have to be
322specified every time.
323
324
325.. _specifying_vault_ids:
326
327Labelling Vaults
328^^^^^^^^^^^^^^^^
329
330Since Ansible 2.4 the :option:`--vault-id <ansible-playbook --vault-id>` can be used to indicate which vault ID
331('dev', 'prod', 'cloud', etc) a password is for as well as how to source the password (prompt, a file path, etc).
332
333By default the vault-id label is only a hint, any values encrypted with the password will be decrypted.
334The config option :ref:`DEFAULT_VAULT_ID_MATCH` can be set to require the vault id to match the vault ID
335used when the value was encrypted.
336This can reduce errors when different values are encrypted with different passwords.
337
338For example, to use a password file :file:`dev-password` for the vault-id 'dev':
339
340.. code-block:: bash
341
342    ansible-playbook --vault-id dev@dev-password site.yml
343
344To prompt for the password for the 'dev' vault ID:
345
346.. code-block:: bash
347
348    ansible-playbook --vault-id dev@prompt site.yml
349
350To get the 'dev' vault ID password from an executable script :file:`my-vault-password.py`:
351
352.. code-block:: bash
353
354    ansible-playbook --vault-id dev@my-vault-password.py
355
356
357The config option :ref:`DEFAULT_VAULT_IDENTITY_LIST` can be used to specify a default vault ID and password source
358so that the :option:`--vault-id <ansible-playbook --vault-id>` cli option does not have to be specified every time.
359
360
361The :option:`--vault-id <ansible-playbook --vault-id>` option can also be used without specifying a vault-id.
362This behaviour is equivalent to :option:`--ask-vault-pass <ansible-playbook --ask-vault-pass>` or
363:option:`--vault-password-file <ansible-playbook --vault-password-file>` so is rarely used.
364
365For example, to use a password file :file:`dev-password`:
366
367.. code-block:: bash
368
369    ansible-playbook --vault-id dev-password site.yml
370
371To prompt for the password:
372
373.. code-block:: bash
374
375    ansible-playbook --vault-id @prompt site.yml
376
377To get the password from an executable script :file:`my-vault-password.py`:
378
379.. code-block:: bash
380
381    ansible-playbook --vault-id my-vault-password.py
382
383.. note::
384    Prior to Ansible 2.4, the :option:`--vault-id <ansible-playbook --vault-id>` option is not supported
385    so :option:`--ask-vault-pass <ansible-playbook --ask-vault-pass>` or
386    :option:`--vault-password-file <ansible-playbook --vault-password-file>` must be used.
387
388
389Multiple Vault Passwords
390^^^^^^^^^^^^^^^^^^^^^^^^
391
392Ansible 2.4 and later support using multiple vault passwords, :option:`--vault-id <ansible-playbook --vault-id>` can
393be provided multiple times.
394
395For example, to use a 'dev' password read from a file and to be prompted for the 'prod' password:
396
397.. code-block:: bash
398
399    ansible-playbook --vault-id dev@dev-password --vault-id prod@prompt site.yml
400
401By default the vault ID labels (dev, prod etc.) are only hints, Ansible will attempt to decrypt vault content
402with each password. The password with the same label as the encrypted data will be tried first, after that
403each vault secret will be tried in the order they were provided on the command line.
404
405Where the encrypted data doesn't have a label, or the label doesn't match any of the provided labels, the
406passwords will be tried in the order they are specified.
407
408In the above case, the 'dev' password will be tried first, then the 'prod' password for cases
409where Ansible doesn't know which vault ID is used to encrypt something.
410
411To add a vault ID label to the encrypted data use the :option:`--vault-id <ansible-vault-create --vault-id>` option
412with a label when encrypting the data.
413
414The :ref:`DEFAULT_VAULT_ID_MATCH` config option can be set so that Ansible will only use the password with
415the same label as the encrypted data. This is more efficient and may be more predictable when multiple
416passwords are used.
417
418The config option :ref:`DEFAULT_VAULT_IDENTITY_LIST` can have multiple values which is equivalent to multiple :option:`--vault-id <ansible-playbook --vault-id>` cli options.
419
420The :option:`--vault-id <ansible-playbook --vault-id>` can be used in lieu of the :option:`--vault-password-file <ansible-playbook --vault-password-file>` or :option:`--ask-vault-pass <ansible-playbook --ask-vault-pass>` options,
421or it can be used in combination with them.
422
423When using :ref:`ansible-vault` commands that encrypt content (:ref:`ansible-vault encrypt <ansible_vault_encrypt>`, :ref:`ansible-vault encrypt_string <ansible_vault_encrypt_string>`, etc)
424only one vault-id can be used.
425
426
427.. _vault_password_client_scripts:
428
429Vault Password Client Scripts
430`````````````````````````````
431
432When implementing a script to obtain a vault password it may be convenient to know which vault ID label was
433requested. For example a script loading passwords from a secret manager may want to use the vault ID label to pick
434either the 'dev' or 'prod' password.
435
436Since Ansible 2.5 this is supported through the use of Client Scripts. A Client Script is an executable script
437with a name ending in ``-client``. Client Scripts are used to obtain vault passwords in the same way as any other
438executable script. For example:
439
440.. code-block:: bash
441
442    ansible-playbook --vault-id dev@contrib/vault/vault-keyring-client.py
443
444The difference is in the implementation of the script. Client Scripts are executed with a ``--vault-id`` option
445so they know which vault ID label was requested. So the above Ansible execution results in the below execution
446of the Client Script:
447
448.. code-block:: bash
449
450    contrib/vault/vault-keyring-client.py --vault-id dev
451
452:file:`contrib/vault/vault-keyring-client.py` is an example of Client Script that loads passwords from the
453system keyring.
454
455
456.. _speeding_up_vault:
457
458Speeding Up Vault Operations
459````````````````````````````
460
461If you have many encrypted files, decrypting them at startup may cause a perceptible delay. To speed this up, install the cryptography package:
462
463.. code-block:: bash
464
465    pip install cryptography
466
467
468.. _vault_format:
469
470Vault Format
471````````````
472
473A vault encrypted file is a UTF-8 encoded txt file.
474
475The file format includes a newline terminated header.
476
477For example::
478
479    $ANSIBLE_VAULT;1.1;AES256
480
481or::
482
483    $ANSIBLE_VAULT;1.2;AES256;vault-id-label
484
485The header contains the vault format id, the vault format version, the vault cipher, and a vault-id label (with format version 1.2), separated by semi-colons ';'
486
487The first field ``$ANSIBLE_VAULT`` is the format id. Currently ``$ANSIBLE_VAULT`` is the only valid file format id. This is used to identify files that are vault encrypted (via vault.is_encrypted_file()).
488
489The second field (``1.X``) is the vault format version. All supported versions of ansible will currently default to '1.1' or '1.2' if a labeled vault-id is supplied.
490
491The '1.0' format is supported for reading only (and will be converted automatically to the '1.1' format on write). The format version is currently used as an exact string compare only (version numbers are not currently 'compared').
492
493The third field (``AES256``) identifies the cipher algorithm used to encrypt the data. Currently, the only supported cipher is 'AES256'. [vault format 1.0 used 'AES', but current code always uses 'AES256']
494
495The fourth field (``vault-id-label``) identifies the vault-id label used to encrypt the data. For example using a vault-id of ``dev@prompt`` results in a vault-id-label of 'dev' being used.
496
497Note: In the future, the header could change. Anything after the vault id and version can be considered to depend on the vault format version. This includes the cipher id, and any additional fields that could be after that.
498
499The rest of the content of the file is the 'vaulttext'. The vaulttext is a text armored version of the
500encrypted ciphertext. Each line will be 80 characters wide, except for the last line which may be shorter.
501
502Vault Payload Format 1.1 - 1.2
503``````````````````````````````
504
505The vaulttext is a concatenation of the ciphertext and a SHA256 digest with the result 'hexlifyied'.
506
507'hexlify' refers to the ``hexlify()`` method of the Python Standard Library's `binascii <https://docs.python.org/3/library/binascii.html>`_ module.
508
509hexlify()'ed result of:
510
511- hexlify()'ed string of the salt, followed by a newline (``0x0a``)
512- hexlify()'ed string of the crypted HMAC, followed by a newline. The HMAC is:
513
514  - a `RFC2104 <https://www.ietf.org/rfc/rfc2104.txt>`_ style HMAC
515
516    - inputs are:
517
518      - The AES256 encrypted ciphertext
519      - A PBKDF2 key. This key, the cipher key, and the cipher IV are generated from:
520
521        - the salt, in bytes
522        - 10000 iterations
523        - SHA256() algorithm
524        - the first 32 bytes are the cipher key
525        - the second 32 bytes are the HMAC key
526        - remaining 16 bytes are the cipher IV
527
528-  hexlify()'ed string of the ciphertext. The ciphertext is:
529
530  - AES256 encrypted data. The data is encrypted using:
531
532    - AES-CTR stream cipher
533    - cipher key
534    - IV
535    - a 128 bit counter block seeded from an integer IV
536    - the plaintext
537
538      - the original plaintext
539      - padding up to the AES256 blocksize. (The data used for padding is based on `RFC5652 <https://tools.ietf.org/html/rfc5652#section-6.3>`_)
540
541
542