Throw AnsibleError instead of OSError, py3.9 crypt (#70246)

Change:
- On Python 3.9, `crypt.crypt` will throw instead of returning `None`
  when the algorithm isn't supported. So we catch that and handle it
  the same way we handled the algorithm not being supported on 3.8: by
  throwing AnsibleError.

Test Plan:
- CI for <=3.8.
- Local for 3.9b3:
  ansible -m debug -a "msg=\"{{ 'changeme' | password_hash('bcrypt') }}\"" localhost

  Before:
  localhost | FAILED! => {
      "msg": "Unexpected failure during module execution.",
      "stdout": ""
  }

  After:
  localhost | FAILED! => {
      "msg": "crypt.crypt does not support 'bcrypt' algorithm"
  }

Tickets:
- Fixes #69930

Signed-off-by: Rick Elrod <rick@elrod.me>
This commit is contained in:
Rick Elrod 2020-06-24 13:50:28 -05:00 committed by GitHub
parent ebd20ddca6
commit 2531d54880
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 3 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- ansible.utils.encrypt now returns `AnsibleError` instead of crypt.crypt's `OSError` on Python 3.9

View file

@ -106,13 +106,23 @@ class CryptHash(BaseHash):
saltstring = "$%s$%s" % (self.algo_data.crypt_id, salt)
else:
saltstring = "$%s$rounds=%d$%s" % (self.algo_data.crypt_id, rounds, salt)
result = crypt.crypt(secret, saltstring)
# crypt.crypt returns None if it cannot parse saltstring
# crypt.crypt on Python < 3.9 returns None if it cannot parse saltstring
# On Python >= 3.9, it throws OSError.
try:
result = crypt.crypt(secret, saltstring)
orig_exc = None
except OSError as e:
result = None
orig_exc = e
# None as result would be interpreted by the some modules (user module)
# as no password at all.
if not result:
raise AnsibleError("crypt.crypt does not support '%s' algorithm" % self.algorithm)
raise AnsibleError(
"crypt.crypt does not support '%s' algorithm" % self.algorithm,
orig_exc=orig_exc,
)
return result