Ansible is the configuration
management tool we use at work. It has built-in support for encrypted
so you can safely store secrets in version control.
I thought I should review the
It's a bit shoddy but probably OK, provided you have a really strong vault password.
The code starts off with a bad sign:
from cryptography.hazmat.primitives.hashes import SHA256 as c_SHA256 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.hazmat.backends import default_backend
I like the way the Python cryptography library calls this stuff HAZMAT but I don't like the fact that Ansible is getting its hands dirty with HAZMAT. It's likely to lead to embarrassing cockups, and in fact Ansible had an embarrassing cockup - there are two vault ciphers, "AES" (the cockup, now disabled except that for compatibility you can still decrypt) and "AES256" (fixed replacement).
As a consequence of basing
ansible-vault on relatively low-level
primitives, it has its own Python implementations of constant-time
comparison and PKCS#7 padding. Ugh.
Proper random numbers:
b_salt = os.urandom(32)
b_derivedkey = PBKDF2(b_password, b_salt, dkLen=(2 * keylength) + ivlength, count=10000, prf=pbkdf2_prf)
PBKDF2 HMAC SHA256 takes about 24ms for 10k iterations on my machine, which is not bad but also not great - e.g. 1Password uses 100k iterations of the same algorithm, and gpg tunes its non-PBKDF2 password hash to take (by default) at least 100ms.
The deeper problem here is that Ansible has hard-coded the PBKDF2 iteration count, so it can't be changed without breaking compatibility. In gpg an encrypted blob includes the variable iteration count as a parameter.
b_vaulttext = b'\n'.join([hexlify(b_salt), to_bytes(hmac.hexdigest()), hexlify(b_ciphertext)]) b_vaulttext = hexlify(b_vaulttext)
The ASCII-armoring of the ciphertext is as dumb as a brick, with hex-encoding inside hex-encoding.
I also (more briefly) looked through
code for managing vault files.
It is based on handing decrypted YAML files to
$EDITOR, so it's a
bit awkward if you don't want to wrap secrets in YAML or if you don't
want to manipulate them in your editor.
so the decrypted file can be placed on a ram disk, though you might
have to set
TMPDIR to make sure.
the file after finishing with it.