Commit Graph

66 Commits (e2d874c744698d97b603262a2f8a4d4d44c76782)

Author SHA1 Message Date
Toshio Kuratomi e238ae999b Cyptography pr 20566 rebase (#25560)
Make pyca/cryptography the preferred backend for cryptographic needs (mainly vault) falling back to pycrypto

pyca/cryptography is already implicitly a dependency in many cases
through paramiko (2.0+) as well as the new openssl_publickey module,
which requires pyOpenSSL 16.0+. Additionally, pyca/cryptography is
an optional dep for better performance with vault already.

This commit leverages cryptography's padding, constant time comparisons,
and CBC/CTR modes to reduce the amount of code ansible needs to
maintain.

* Handle wrong password given for VaultAES format

* Do not display deprecation warning for cryptography on python-2.6

* Namespace all of the pycrypto imports and always import them

  Makes unittests better and the code less likely to get stupid mistakes
  (like using HMAC from cryptogrpahy when the one from pycrypto is needed)

* Add back in atfork since we need pycrypto to reinitialize its RNG just in case we're being used with old paramiko

* contrib/inventory/gce: Remove spurious require on pycrypto

(cherry picked from commit 9e16b9db275263b3ea8d1b124966fdebfc9ab271)

* Add cryptography to ec2_win_password module requirements
  * Fix python3 bug which would pass text strings to a function which
    requires byte strings.

* Attempt to add pycrypto version to setup deps

* Change hacking README for dual pycrypto/cryptography

* update dependencies for various CI scripts

* additional CI dockerfile/script updates

* add paramiko to the windows and sanity requirement set

  This is needed because ansible lists it as a requirement. Previously
  the missing dep wasn't enforced, but cryptography imports pkg_resources
  so you can't ignore a requirement any more

* Add integration test cases for old vault and for wrong passwords

* helper script for manual testing of pycrypto/cryptography

* Skip the pycrypto tests so that users without it installed can still run the unittests

* Run unittests for vault with both cryptography and pycrypto backend
2017-06-27 06:00:15 -07:00
Dag Wieers 6f6bdf7914 ansible/parsing: PEP8 compliancy (#24701)
- Make PEP8 compliant
2017-05-18 18:41:00 +01:00
Adrian Likins e0a7105c2d Use sys.stdout.buffer to write vault bytes to stdout on py3 (#23760)
* Use sys.stdout.buffer to write vault bytes to stdout on py3

We need sys.stdout.buffer on py3 so we can write bytes to it since the plaintext
of the vaulted object could be anything/binary/etc

Before, attempting to write bytes to stdout on py3 would cause:

  TypeError: write() argument must be str, not bytes
2017-04-24 10:09:03 -04:00
Adrian Likins ae3d7fb29e Fix vault reading from stdin (avoid realpath() on non-links) (#23583)
* Fix vault reading from stdin (avoid realpath() on non-links)

os.path.realpath() is used to find the target of file paths that
are symlinks so vault operations happen directly on the target.

However, in addition to resolving symlinks, realpath() also returns
a full path. when reading from stdin, vault cli uses '-' as a special
file path so VaultEditor() will replace with stdin.
realpath() was expanding '-' with the CWD to something like
'/home/user/playbooks/-' causing errors like:

        ERROR! [Errno 2] No such file or directory: u'/home/user/ansible/-'

Fix is to specialcase '-' to not use realpath()

Fixes #23567

* to_text decrypt output when writing to stdout
2017-04-18 13:09:02 -04:00
Hugo Chargois 1bc5527c69 Vault: Remove tmp decrypted file when experiencing error while writing (#14835)
* Vault edit: Erase tmp file if error while writing to it

* Close the FDs returned by mkstemp()
2017-03-27 16:52:18 -04:00
Toshio Kuratomi 2fff690caa Update module_utils.six to latest (#22855)
* Update module_utils.six to latest

We've been held back on the version of six we could use on the module
side to 1.4.x because of python-2.4 compatibility.  Now that our minimum
is Python-2.6, we can update to the latest version of six in
module_utils and get rid of the second copy in lib/ansible/compat.
2017-03-23 13:35:05 -07:00
Nicolas Braud-Santoni f689cca0b8 vault: Uniformize construction of cipher objects 2017-03-08 15:14:20 -05:00
Nicolas Braud-Santoni 680d61c609 vault: call is_encrypted directly in is_encrypted_file
Doing the conversion and checking for exceptions there is pointless
since is_encrypted already does it.
2017-03-08 15:14:20 -05:00
Adrian Likins edcbef27ec Retain vault password as bytes in 2.2 (#22378)
* Retain vault password as bytes in 2.2

Prior to 2.2.1, the vault password was read in as byes and then remained
bytes all the way through the code.  A bug existed where bytes and text
were mixed, leading to a traceback with non-ascii passwords.  In devel,
this was fixed by changing the read in password to text type to match
with our overall strategy of converting at the borders.  This was
backported to stable-2.2 for the 2.2.1 release.

On reflection, this should not have been backported as it causes
passwords which were originally non-utf-8 to become utf-8.  People will
then have their working 2.2.x vault files become in-accessible.

this commit pipes bytes all the way through the system for vault
password.  That way if a password is read in as a non-utf-8 character
sequence, it will continue to work in 2.2.2+.  This change is only for
the 2.2 branch, not for 2.3 and beyond.

Why not everywhere?  The reason is that non-utf-8 passwords will cause
problems when vault files are shared between systems or users.  If the
password is read from the prompt and one user/machine has a latin1
encoded locale while a second one has utf-8, the non-ascii password
typed in won't match between machines.  Deal with this by making sure
that when we encrypt the data, we always use valid utf-8.

Fixes #20398

(cherry picked from commit 5dcce0666a81917c68b76286685642fd72d84327)
2017-03-07 15:30:09 -05:00
Adrian Likins 6c6b647182 Fix 'ansible-vault edit /some/symlink' (#20417)
Since vault edit attempts to unlink
edited files before creating a new file
with the same name and writing to it, if
the file was a symlink, the symlink would
be replaced with a regular file.

VaultEditor file ops now check if files
it is changing are symlinks and instead
works directly on the target, so that
os.rename() and shutils do the right thing.

Add unit tests cases for this case and
assorted VaultEditor test cases.

Fixes #20264
2017-02-24 12:35:39 -05:00
Adrian Likins 7b6c992c46 Vault encrypt string cli (#21024)
* Add a vault 'encrypt_string' command.

The command will encrypt the string on the command
line and print out the yaml block that can be included
in a playbook.

To be prompted for a string to encrypt:
   
   ansible-vault encrypt_string --prompt

To specify a string on the command line:

   ansible-vault encrypt_string "some string to encrypt"

To read a string from stdin to encrypt:

   echo  "the plaintext to encrypt" | ansible-vault encrypt_string

If a --name or --stdin-name is provided, the output will include that name in yaml key value format: 

   $ ansible-vault encrypt_string "42" --name "the_answer"
    the_answer: !vault-encrypted |
          $ANSIBLE_VAULT;1.1;AES256
          <vault cipher text here>

plaintext provided via prompt, cli, and/or stdin can be mixed:

      $ ansible-vault encrypt_string "42" --name "the_answer" --prompt
      Vault password: 
      Variable name (enter for no name): some_variable
      String to encrypt: microfiber
      # The encrypted version of variable ("some_variable", the string #1 from the interactive prompt).
     some_variable: !vault-encrypted |
              $ANSIBLE_VAULT;1.1;AES256
              < vault cipher text here>
      # The encrypted version of variable ("the_answer", the string #2 from the command line args).
      the_answer: !vault-encrypted |
             $ANSIBLE_VAULT;1.1;AES256
             < vault cipher text here>

Encryption successful
* add stdin and prompting to vault 'encrypt_string'
* add a --name to encrypt_string to optional specify a var name
* prompt for a var name to use with --prompt
* add a --stdin-name for the var name for value read from stdin
2017-02-17 10:12:14 -05:00
Carlos E. Garcia 0b8011436d minor spelling changes 2016-12-13 13:51:13 -05:00
Adrian Likins c09060e8ff Fix 'ansible-vault edit' crash on changed nonascii
ansible-vault edit was attempting to decode the file contents
and failing.

Fixes #18428
2016-11-16 15:14:07 -05:00
Adrian Likins 309f54b709 Fix 'vault rekey' with vault secret env var
if ANSIBLE_VAULT_PASSWORD_FILE is set, 'ansible-vault rekey myvault.yml'
will fail to prompt for the new vault password file, and will use
None.

Fix is to split out 'ask_vault_passwords' into 'ask_vault_passwords'
and 'ask_new_vault_passwords' to make the logic simpler. And then
make sure new_vault_pass is always set for 'rekey', and if not, then
call ask_new_vault_passwords() to set it.

ask_vault_passwords() would return values for vault_pass and new
vault_pass, and vault cli previously would not prompt for new_vault_pass
if there was a vault_pass set via a vault password file.

Fixes #18247
2016-11-01 13:07:48 -04:00
Toshio Kuratomi bf3d546d9a Only dispkay failure to use cryptography at a higher verbosity
Fixes #17982
2016-10-12 10:48:36 -07:00
Toshio Kuratomi e70066a6f7 Many Cleanups to vault
* Make is_encrypted_file handle both files opened in text and binary mode
  On python3, by default files are opened in text mode.  Since we know
  the encoding of vault files (and especially the header which is the
  first set of bytes) we can decide whether the file is an encrypted
  vault file in either case.
* Fix is_encrypted_file not resetting the file position
* Update is_encrypted_file to check that all the data in the file is ascii
* For is_encrypted_file(), add start_pos and count parameters
  This allows callers to specify reading vaulttext from the middle of
  a file if necessary.
* Combine VaultLib.encrypt() and VaultLib.encrypt_bytestring()
* Change vault's is_encrypted() to take either text or byte strings and to return False if any part of the data is non-ascii.
* Remove unnecessary use of six.b
* Vault Cipher: mark a few methods as private.
* VaultAES256._is_equal throws a TypeError if given non byte strings
* Make VaultAES256 methods that don't need self staticmethods and classmethods
* Mark VaultAES and is_encrypted as deprecated
* Get rid of VaultFile (unused and feature implemented in a different way)
* Normalize variable and parameter names on plaintext, ciphertext, vaulttext
* Normalize variable and parameter names on "b_" prefix when dealing with bytes
* Test changes:
  * Remove redundant tests( both checking the same byte string)
  * Fix use of format string without format operator
  * Enable vault editor tests on python3
  * Initialize the vault_cipher for VaultAES256 testing in setUp()
  * Make assertTrue and assertFalse take the actual method calls for
    better error messages.
  * Test that non-ascii byte strings compare correctly.
  * Test that unicode strings and ints raise TypeError

* Test-specific:
  * Removed test_methods_exist().  We only have one VaultLib so the
    implementation is the assurance that the methods exist. (Can use an abc for
    this if it changes).
  * Add tests for both byte string and text string input where the API takes either.
  * Convert "assert" to unittest assert functions or add a custom message where
    that will make failures easier to debug.
  * Move instantiating the VaultLib into setUp().
2016-09-15 15:22:06 -07:00
Toshio Kuratomi 4ed88512e4 Move uses of to_bytes, to_text, to_native to use the module_utils version (#17423)
We couldn't copy to_unicode, to_bytes, to_str into module_utils because
of licensing.  So once created it we had two sets of functions that did
the same things but had different implementations.  To remedy that, this
change removes the ansible.utils.unicode versions of those functions.
2016-09-06 22:54:17 -07:00
Adrian Likins e396d5d508 Implement vault encrypted yaml variables. (#16274)
Make !vault-encrypted create a AnsibleVaultUnicode
yaml object that can be used as a regular string object.

This allows a playbook to include a encrypted vault
blob for the value of a yaml variable. A 'secret_password'
variable can have it's value encrypted instead of having
to vault encrypt an entire vars file.

Add __ENCRYPTED__ to the vault yaml types so
template.Template can treat it similar
to __UNSAFE__ flags.

vault.VaultLib api changes:
    - Split VaultLib.encrypt to encrypt and encrypt_bytestring

    - VaultLib.encrypt() previously accepted the plaintext data
      as either a byte string or a unicode string.
      Doing the right thing based on the input type would fail
      on py3 if given a arg of type 'bytes'. To simplify the
      API, vaultlib.encrypt() now assumes input plaintext is a
      py2 unicode or py3 str. It will encode to utf-8 then call
      the new encrypt_bytestring(). The new methods are less
      ambiguous.

    - moved VaultLib.is_encrypted logic to vault module scope
      and split to is_encrypted() and is_encrypted_file().

Add a test/unit/mock/yaml_helper.py
It has some helpers for testing parsing/yaml

Integration tests added as roles test_vault and test_vault_embedded
2016-08-23 20:03:11 -04:00
Toshio Kuratomi 384a01fcff Fix tmpfile misspelled as tmplfile (#17183) 2016-08-22 11:31:42 -07:00
nyasukun adea1f2b80 fixed memoryerror when coping huge file (#16392)
* fixed

* support both python 2 and 3
2016-07-22 09:06:06 -04:00
Toshio Kuratomi 84c1697271 Only show the traceback for importing cryptography when in Ansible Debug. (#16795) 2016-07-22 05:40:43 -07:00
Connor Osborn b06c61c49b Fix exceptions thrown from cryptography import (#16723)
A simple import of cryptography can throw several types of errors. For example,
if `setuptools` is less than cryptography's minimum requirement of 11.3, then
this import of cryptography will throw a VersionConflict here. An earlier case
threw a DistributionNotFound exception.

An optional dependency should not stop ansible. If the error is more than
an ImportError, log a warning, so that errors can be fixed in ansible or
elsewhere.
2016-07-20 03:32:23 -07:00
jctanner 1db02dfb71 If decryption of a vaulted file failed, include the filename in the error. (#16329)
Fixes #16327
2016-06-18 09:30:08 -04:00
Peter Oliver 95cfceda98 Catch DistributionNotFound when pycrypto is absent (#15731)
* Catch DistributionNotFound when pycrypto is absent

On Solaris 11, module `pkg_resources` throws `DistributionNotFound` on import if `cryptography` is installed but `pycrypto` is not.  This change causes that situation to be handled gracefully.

I'm not using Paramiko or Vault, so I my understanding is that I don't
need `pycrpto`.  I could install `pycrypto` to make the error go away, but:
- The latest released version of `pycrypto` doesn't build cleanly on Solaris (https://github.com/dlitz/pycrypto/issues/184).
- Solaris includes an old version of GMP that triggers warnings every time Ansible runs (https://github.com/ansible/ansible/issues/6941).  I notice that I can silence these warnings with `system_warnings` in `ansible.cfg`, but not installing `pycrypto` seems like a safer solution.

* Ignore only `pkg_resources.DistributionNotFound`, not other exceptions.
2016-05-19 11:39:34 -07:00
Brian Coca e0573d3099 make vi the default editor if no EDITOR
fixes #15577
2016-05-03 09:39:19 -04:00
Toshio Kuratomi 2ba4428424 Catch ValueError as well because of El Capitan provoking a bug in python2's subprocess
Fixes #14895
2016-03-18 05:52:53 -07:00
Brian Coca 0f73fb0d6f better error messages when failing to decrypt 2016-02-18 08:57:28 -08:00
Brian Coca f26adcc7da avoid shredding empty files, also x/0
also cleaned up unused import and exception var
2016-01-21 10:54:56 -05:00
Toshio Kuratomi 4958180333 use integer division instead of floating point division.
Fixes #13855
2016-01-13 12:35:28 -08:00
Eric Feliksik 11ce08b9dd cleaner implementation and random chunk length. 2016-01-05 18:04:38 +01:00
Eric Feliksik 151e09d129 use unix shred if possible, otherwise fast custom impl; do not shred encrypted file 2016-01-05 01:43:42 +01:00
Eric Feliksik 1e911375e8 add docs, remove unnecessary int() cast 2016-01-04 18:13:59 +01:00
Eric Feliksik 7193d27acc add os.fsync() so that the shredding data (hopefully) hits the drive 2016-01-04 17:22:18 +01:00
Eric Feliksik 946b82bef7 shred ansible-vault tmp_file. Also when editor is interruped. 2015-12-30 18:21:34 +01:00
Abhijit Menon-Sen 7caefa5cd9 Fix typo 2015-11-03 10:57:48 +05:30
Brian Coca 00bc74404a vault noe preserves permissions on edit and rekey and sets a restricitve default umask for all other cases 2015-10-31 14:13:03 -04:00
James Cammarata 86de1429e5 Cleaning up FIXMEs 2015-10-22 16:03:50 -04:00
Toshio Kuratomi b23a083776 Make vault use a mapping of cipher name to classes instead of formatting the name for safety. 2015-10-16 10:05:27 -07:00
Toshio Kuratomi baa309309d Bundle a new version of python-six for compatibility along with some code to make it easy for distributions to override the bunndled copy if they have a new enough version. 2015-10-16 08:21:28 -07:00
Marius Gedminas 98958ec990 Simplify join expression 2015-10-16 17:39:27 +03:00
Marius Gedminas 56184a3d8c Python 3: avoid %-formatting of byte strings
This is needed for Python 3.4 compatibility; Python 3.5 can use
`b'%s\n' bytestring` again.
2015-10-16 17:18:35 +03:00
Abhijit Menon-Sen 0bb34fd076 Make «ansible-vault view» not write plaintext to a tempfile
CLI already provides a pager() method that feeds $PAGER on stdin, so we
just feed that the plaintext from the vault file. We can also eliminate
the redundant and now-unused shell_pager_command method in VaultEditor.
2015-09-30 22:13:36 +05:30
Toshio Kuratomi 86b2982005 Merge pull request #12112 from amenonsen/vault-stdio
Implement cat-like filtering behaviour for encrypt/decrypt
2015-08-27 11:26:48 -07:00
Abhijit Menon-Sen 090cfc9e03 More helpful prompts from ansible-vault encrypt/decrypt
Now we issue a "Reading … from stdin" prompt if our input isatty(), as
gpg does. We also suppress the "x successful" confirmation message at
the end if we're part of a pipeline.

(The latter requires that we not close sys.stdout in VaultEditor, and
for symmetry we do the same for sys.stdin, though it doesn't matter in
that case.)
2015-08-27 22:04:18 +05:30
Abhijit Menon-Sen e7eebb6954 Implement cat-like filtering behaviour for encrypt/decrypt
This allows the following invocations:

    # Interactive use, like gpg
    ansible-vault encrypt --output x

    # Non-interactive, for scripting
    echo plaintext|ansible-vault encrypt --output x

    # Separate input and output files
    ansible-vault encrypt input.yml --output output.yml

    # Existing usage (in-place encryption) unchanged
    ansible-vault encrypt inout.yml

…and the analogous cases for ansible-vault decrypt as well.

In all cases, the input and output files can be '-' to read from stdin
or write to stdout. This permits sensitive data to be encrypted and
decrypted without ever hitting disk.
2015-08-27 22:04:18 +05:30
Abhijit Menon-Sen 8fc8bf9439 Simplify VaultEditor methods
We don't need to keep creating VaultLibs everywhere, and we don't need
to keep checking for errors because VaultLib does it already.
2015-08-27 22:04:18 +05:30
Abhijit Menon-Sen e99395f0c0 Don't create a VaultLib in each method; do it in __init__ instead 2015-08-27 22:04:18 +05:30
Abhijit Menon-Sen 159887a6c9 Remove deprecated and unused VaultAES encryption code
Now that VaultLib always decides to use AES256 to encrypt, we don't need
this broken code any more. We need to be able to decrypt this format for
a while longer, but encryption support can be safely dropped.
2015-08-27 16:54:39 +05:30
Abhijit Menon-Sen b84053019a Make the filename the first argument to rekey_file 2015-08-26 19:54:59 +05:30
Abhijit Menon-Sen 20fd9224bb Pass the filename to the individual VaultEditor methods, not __init__
Now we don't have to recreate VaultEditor objects for each file, and so
on. It also paves the way towards specifying separate input and output
files later.
2015-08-26 19:17:37 +05:30