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