Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Share the implementation of hashing for both vars_prompt and password_hash #21215

Merged
merged 10 commits into from Aug 27, 2018

Conversation

mfuchs
Copy link
Contributor

@mfuchs mfuchs commented Feb 9, 2017

ISSUE TYPE
  • Feature Pull Request
  • Bugfix Pull Request
  • Docs Pull Request
COMPONENT NAME

vars_prompt
filter

ANSIBLE VERSION
2.2.1
SUMMARY

Shares the implementation of hashing secrets for both vars_prompt and password_hash.

Fixes #15326
Fixes #17266

# after
{{ 'secret' | password_hash('bcrypt', rounds=14) }}

@mattclay
Copy link
Member

CI failure due to unit test errors. Here's one of the errors:

2017-02-09 23:40:23 =================================== FAILURES ===================================
2017-02-09 23:40:23 _________________________ TestEncrypt.test_do_encrypt __________________________
2017-02-09 23:40:23 
2017-02-09 23:40:23 self = <units.utils.test_encrypt.TestEncrypt testMethod=test_do_encrypt>
2017-02-09 23:40:23 
2017-02-09 23:40:23     def test_do_encrypt(self):
2017-02-09 23:40:23         self.assertTrue(encrypt.PASSLIB_AVAILABLE)
2017-02-09 23:40:23     
2017-02-09 23:40:23 >       with self.assertRaises(AnsibleError):
2017-02-09 23:40:23 E       TypeError: failUnlessRaises() takes at least 3 arguments (2 given)
2017-02-09 23:40:23 
2017-02-09 23:40:23 test/units/utils/test_encrypt.py:76: TypeError

@mattclay mattclay added the ci_verified Changes made in this PR are causing tests to fail. label Feb 10, 2017
@ansibot
Copy link
Contributor

ansibot commented Feb 10, 2017

@ansibot ansibot added affects_2.3 This issue/PR affects Ansible v2.3 c:plugins/filter c:utils/encrypt docs_pull_request needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. labels Feb 10, 2017
@mfuchs mfuchs force-pushed the vars_prompt_password_hash_unification branch from 36751e8 to 036e006 Compare February 10, 2017 19:32
@ansibot ansibot removed the ci_verified Changes made in this PR are causing tests to fail. label Feb 10, 2017
@mfuchs mfuchs force-pushed the vars_prompt_password_hash_unification branch 2 times, most recently from 0f2e55c to 1ac23f6 Compare February 10, 2017 21:17
@mattclay mattclay added the ci_verified Changes made in this PR are causing tests to fail. label Feb 11, 2017
@mattclay
Copy link
Member

CI failure in unit tests due to:

2017-02-10 21:37:00 E           MissingBackendError: bcrypt: no backends available -- recommend you install one (e.g. 'pip install bcrypt')

The full error is quite long, so I'll just link to the logs here: https://app.shippable.com/runs/589e2dee031d631000bae9d4/2/console

@mfuchs mfuchs force-pushed the vars_prompt_password_hash_unification branch from 1ac23f6 to 719aa81 Compare February 11, 2017 11:03
@ansibot ansibot removed the ci_verified Changes made in this PR are causing tests to fail. label Feb 11, 2017
@mfuchs
Copy link
Contributor Author

mfuchs commented Feb 11, 2017

Thanks mattclay for your input! :)

ready_for_review

@ansibot ansibot removed the needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. label Feb 11, 2017
@abadger
Copy link
Contributor

abadger commented Mar 1, 2017

Catch and reraise is a better pattern than passing the exception in. Python 2 makes this a pain, though. Ned Batchelder has a good blog post about how to do that right: https://nedbatchelder.com/blog/200711/rethrowing_exceptions_in_python.html

passlib changes number of rounds while crypt has a static value. I'm not sure of al the ramifications for that. It would mean that pre and post change, lookup('password_hash'[...]) will return different strings. If rounds is calculated dynamically at runtime, it could mean that when I use a playbook that has lookup('password_hash'[...]) on my low end laptop, I generate a different string than when someone else runs it on their high end workstation. If that's true it leads to non-repeatability of playbook runs.

@mfuchs
Copy link
Contributor Author

mfuchs commented Mar 1, 2017

As discussed with abadger I will make sure that password_hash returns the same value for both 2.2 and when this commit is merged.
No matter if passlib is installed or not.
This will also be part of the unit test.

Furthermore I will look into allowing a rounds parameter for crypt, for example crypt.crypt('secret', '$6$rounds=656000$abc').

Maybe I will also update the vars_prompt documentation to mention that it makes sense to specify a rounds parameter to ensure replayability.

@ansibot ansibot added needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. labels Apr 11, 2017
@ansibot ansibot added the support:core This issue/PR relates to code supported by the Ansible Engineering Team. label Jun 29, 2017
Copy link
Contributor

@dharmabumstead dharmabumstead left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc updates are OK. Thanks @mfuchs!

@mfuchs mfuchs force-pushed the vars_prompt_password_hash_unification branch from 719aa81 to 00e8c2d Compare August 21, 2017 19:30
@ansibot ansibot removed the needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html label Aug 21, 2017
@mfuchs
Copy link
Contributor Author

mfuchs commented Aug 24, 2018

Some tests fail.
I checked and at least test/integration/targets/vars_prompt/vars_prompt-5.yml fails.
The reason is that it expects re.compile('"password": "\\$6\\$rounds=') in the password-output.
Yet since no rounds are provided the default of crypt is used leading to a output like

"password": "$6$jESIyad4F08hP3Ta$hrnwEbDk9uSg1IURdckNLBy9xoeO1y1peRDBHsdmwzlWv1u9Cs0qasiy7THQ88dnzC0f4PaFX4ySUCcyT5emn0"

This change was implemented to be more consistent overall, thus having consistency between vars_prompt and password_hash (no matter if passlib is installed or not) and not depending on the always changing defaults of passlib.

@abadger
Copy link
Contributor

abadger commented Aug 24, 2018

Makes sense to me. Go ahead and change the test.

…_hash.

* vars_prompt with encrypt does not require passlib for the algorithms
  supported by crypt.
* Additional checks ensure that there is always a result.
  This works around issues in the crypt.crypt python function that returns
  None for algorithms it does not know.
  Some modules (like user module) interprets None as no password at all,
  which is misleading.
* The password_hash filter supports all parameters of passlib.
  This allows users to provide a rounds parameter, fixing ansible#15326.
* password_hash is not restricted to the subset provided by crypt.crypt,
  fixing one half of ansible#17266.
* Updated documentation fixes other half of ansible#17266.
* password_hash does not hard-code the salt-length, which fixes bcrypt
  in connection with passlib.
  bcrypt requires a salt with length 22, which fixes ansible#25347
* Salts are only generated by ansible when using crypt.crypt.
  Otherwise passlib generates them.
* Avoids deprecated functionality of passlib with newer library versions.
* When no rounds are specified for sha256/sha256_crypt and sha512/sha512_crypt
  always uses the default values used by crypt, i.e. 5000 rounds.
  Before when installed passlibs' defaults were used.
  passlib changes its defaults with newer library versions, leading to non
  idempotent behavior.

  NOTE: This will lead to the recalculation of existing hashes generated
        with passlib and without a rounds parameter.
        Yet henceforth the hashes will remain the same.
        No matter the installed passlib version.
        Making these hashes idempotent.

Fixes ansible#15326
Fixes ansible#17266
Fixes ansible#25347 except bcrypt still uses 2a, instead of the suggested 2b.
* random_salt is solely handled by encrypt.py.
  There is no _random_salt function there anymore.
  Also the test moved to test_encrypt.py.
* Uses pytest.skip when passlib is not available, instead of a silent return.
* More checks are executed when passlib is not available.
…ibleError.

The password_hash filter then transforms the AnsibleError to an AnsibleFilterError.
When no rounds are provided the defaults of crypt are used.
In that case the rounds are not part of the resulting MCF output.
@mfuchs mfuchs force-pushed the vars_prompt_password_hash_unification branch from 913bbf6 to e2224ad Compare August 24, 2018 14:02
@mfuchs
Copy link
Contributor Author

mfuchs commented Aug 24, 2018

Since the test is rather new I rebased on current devel + adapted the integration test.

@ansibot ansibot added support:community This issue/PR relates to code supported by the Ansible community. and removed needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. labels Aug 24, 2018
@abadger abadger merged commit 7871027 into ansible:devel Aug 27, 2018
@abadger
Copy link
Contributor

abadger commented Aug 27, 2018

Merged to devel for the 2.7.0 release. Thanks @mfuchs

@BarbzYHOOL
Copy link

awesome

alikins added a commit that referenced this pull request Aug 27, 2018
* devel: (513 commits)
  Fix systemd service is already masked issue (#44730)
  fix issue with no_log in py3
  modules/terraform: Quote the variable values in the command line (#43493)
  YUM4/DNF compatibility via yum action plugin (#44322)
  BOTMETA.yml: remove superfluous labels (#44628)
  Share the implementation of hashing for both vars_prompt and password_hash (#21215)
  one_host environment variables, Fixes #44163 (#44568)
  ec2: add "IAM Role" to instance_profile_name
  ios_vrf speed fix (#43765)
  fix typo (#44712)
  junos cli_config idempotence fix (#44706)
  Switch to LiteralPath instead of Path. Closes #44508 (#44509)
  Module win_domain_computer fix delete computer with child (#44500)
  ACME: improve documentation (#44691)
  doc: fixed typo (#44685)
  IPA: Add option to specify timeout (#44572)
  Added nios_txt_record module (#39264)
  adds the bigip_cli_script module (#44674)
  Clean up BOTMETA.yml (#44574)
  Change validate-modules for removed modules
  ...
@ansible ansible locked and limited conversation to collaborators Jul 22, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.3 This issue/PR affects Ansible v2.3 c:plugins/filter c:utils/encrypt docs This issue/PR relates to or includes documentation. feature This issue/PR relates to a feature request. new_contributor This PR is the first contribution by a new community member. plugins/filter support:community This issue/PR relates to code supported by the Ansible community. support:core This issue/PR relates to code supported by the Ansible Engineering Team. test This PR relates to tests. utils/encrypt
Projects
None yet