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

AttributeError exception in module community.crypto.openssl_privatekey_info when check_consistency is true #701

Closed
PrieJos opened this issue Jan 26, 2024 · 5 comments · Fixed by #702
Labels
bug Something isn't working

Comments

@PrieJos
Copy link

PrieJos commented Jan 26, 2024

SUMMARY

A task step like this:

    - name: Get private key information
      community.crypto.openssl_privatekey_info:
        path: "{{ pk_path }}"
        passphrase: "{{ pk_passphrase }}"
        check_consistency: true

will end up with the following exception:

AttributeError: 'cryptography.hazmat.bindings._rust.openssl.rsa.RSA' object has no attribute '_backend'

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.crypto.openssl_privatekey_info

ANSIBLE VERSION
ansible [core 2.16.0]
  config file = /home/users/sxprietj/.ansible.cfg
  configured module search path = ['/home/users/sxprietj/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/sap/SAPE/team/sxprietj/workspace/ansible_collections/roche/mono/.venv/lib/python3.11/site-packages/ansible
  ansible collection location = /home/users/sxprietj/workspace:/home/users/sxprietj/.ansible/collections
  executable location = /usr/sap/SAPE/team/sxprietj/workspace/ansible_collections/roche/mono/.venv/bin/ansible
  python version = 3.11.7 (main, Dec 15 2023, 12:28:21) [GCC 11.2.1 20220127 (Red Hat 11.2.1-9)] (/usr/sap/SAPE/team/sxprietj/workspace/ansible_collections/roche/mono/.venv/bin/python)
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
$ ansible-galaxy collection list community.crypto

# /home/users/sxprietj/.ansible/collections/ansible_collections
Collection       Version
---------------- -------
community.crypto 2.17.0 
CONFIGURATION
$ ansible-config dump --only-changed
COLLECTIONS_PATHS(env: ANSIBLE_COLLECTIONS_PATH) = ['/home/users/sxprietj/workspace', '/home/users/sxprietj/.ansible/collections']
CONFIG_FILE() = /home/users/sxprietj/.ansible.cfg
DEFAULT_STDOUT_CALLBACK(env: ANSIBLE_STDOUT_CALLBACK) = debug
DEFAULT_VAULT_PASSWORD_FILE(env: ANSIBLE_VAULT_PASSWORD_FILE) = /home/users/sxprietj/.ansible-vault-pass
EDITOR(env: EDITOR) = /usr/bin/vim -e
OS / ENVIRONMENT

OS version:

$ lsb_release -a
LSB Version:	:core-4.1-amd64:core-4.1-noarch
Distributor ID:	RedHatEnterprise
Description:	Red Hat Enterprise Linux release 8.8 (Ootpa)
Release:	8.8
Codename:	Ootpa

Package versions in python virtual environment:

$ pip list
Package                   Version
------------------------- ---------------
aiodns                    3.1.1
aiohttp                   3.9.1
aiosignal                 1.3.1
annotated-types           0.6.0
ansible                   9.0.1
ansible-compat            4.1.11
ansible-core              2.16.0
ansible-lint              6.22.2
ansible-rulebook          1.0.4
ansible-runner            2.3.4
anyio                     4.1.0
arrow                     1.3.0
astroid                   3.0.2
asttokens                 2.4.1
asyncio                   3.4.3
attrs                     23.2.0
Authlib                   1.3.0
beautifulsoup4            4.12.3
black                     23.12.1
bracex                    2.4
cachetools                5.3.2
cattrs                    23.2.3
certifi                   2023.11.17
cffi                      1.16.0
cfgv                      3.4.0
charset-normalizer        3.3.2
chimp                     2.8.1
click                     8.1.7
click-help-colors         0.9.4
comm                      0.2.0
coverage                  7.3.2
cryptography              42.0.1
dateutils                 0.6.12
debugpy                   1.8.0
debugpy-run               1.8
decorator                 5.1.1
deer                      1.4.2
defusedxml                0.7.1
dill                      0.3.7
distlib                   0.3.8
distro                    1.9.0
dnspython                 2.5.0
docformatter              1.7.5
docker                    7.0.0
docutils                  0.20.1
dpath                     2.1.6
drools-jpy                0.3.8
enrich                    1.2.7
execnet                   2.0.2
executing                 2.0.1
filelock                  3.13.1
flake8                    7.0.0
Flake8-pyproject          1.2.3
fqdn                      1.5.1
frozenlist                1.4.1
google-api-core           2.15.0
google-api-python-client  2.111.0
google-auth               2.25.2
google-auth-httplib2      0.2.0
google-auth-oauthlib      1.2.0
googleapis-common-protos  1.62.0
greenlet                  3.0.2
h11                       0.14.0
hdbcli                    2.19.21
httpcore                  1.0.2
httplib2                  0.22.0
httpx                     0.26.0
hvac                      2.1.0
identify                  2.5.33
idna                      3.6
iniconfig                 2.0.0
ipykernel                 6.29.0
ipython                   8.18.1
isodate                   0.6.1
isoduration               20.11.0
isort                     5.13.2
janus                     1.0.0
jc                        1.24.0
jedi                      0.19.1
Jinja2                    3.1.2
jmespath                  1.0.1
jpy                       0.14.0
jsonpointer               2.4
jsonschema                4.20.0
jsonschema-path           0.3.2
jsonschema-spec           0.2.4
jsonschema-specifications 2023.7.1
junit-xml                 1.9
jupyter_client            8.6.0
jupyter_core              5.5.0
lazy-object-proxy         1.9.0
lockfile                  0.12.2
lxml                      5.1.0
markdown-it-py            3.0.0
MarkupSafe                2.1.3
matplotlib-inline         0.1.6
mccabe                    0.7.0
mdurl                     0.1.2
mock                      5.1.0
molecule                  6.0.3
molecule-plugins          23.5.0
multidict                 6.0.4
mypy                      1.7.1
mypy-extensions           1.0.0
nest-asyncio              1.5.8
netaddr                   0.10.1
netapp-lib                2021.6.25
nocasedict                2.0.1
nocaselist                2.0.0
nodeenv                   1.8.0
oauthlib                  3.2.2
olderr                    2.2.2
openapi-schema-validator  0.6.2
openapi-spec-validator    0.7.1
outcome                   1.3.0.post0
packaging                 23.2
parso                     0.8.3
pathable                  0.4.3
pathspec                  0.12.1
pbr                       6.0.0
pexpect                   4.9.0
pickleDB                  0.9.2
pip                       23.3.2
platformdirs              4.1.0
pluggy                    1.3.0
ply                       3.11
pre-commit                3.6.0
prompt-toolkit            3.0.43
protobuf                  4.25.1
psutil                    5.9.6
ptyprocess                0.7.0
pure-eval                 0.2.2
pyasn1                    0.5.1
pyasn1-modules            0.3.0
pycares                   4.4.0
pycodestyle               2.11.1
pycparser                 2.21
pydantic                  2.5.3
pydantic_core             2.14.6
pyflakes                  3.2.0
Pygments                  2.17.2
pylint                    3.0.3
PyMySQL                   1.1.0
pyOpenSSL                 24.0.0
pyparsing                 3.1.1
pyroola                   1.2.1
PySocks                   1.7.1
pytest                    7.4.4
pytest-aiohttp            1.0.5
pytest-ansible            24.1.2
pytest-asyncio            0.23.3
pytest-html               4.1.1
pytest-json               0.4.0
pytest-lazy-fixture       0.6.3
pytest-metadata           3.0.0
pytest-mock               3.12.0
pytest-test-groups        1.0.3
pytest-xdist              3.5.0
python-daemon             3.0.1
python-dateutil           2.8.2
python-ldap               3.4.4
pytz                      2023.3.post1
pyvmomi                   8.0.2.0.1
pywbem                    1.6.2
PyYAML                    6.0.1
pyzmq                     25.1.2
redis                     5.0.1
referencing               0.30.2
requests                  2.31.0
requests-file             1.5.1
requests-oauthlib         1.3.1
requests-toolbelt         1.0.0
requirements-parser       0.5.0
resolvelib                1.0.1
rfc3339-validator         0.1.4
rfc3986                   2.0.0
rfc3987                   1.3.8
rich                      13.7.0
rochepki                  2.0.0
rpds-py                   0.13.2
rsa                       4.9
ruamel.yaml               0.18.5
ruamel.yaml.clib          0.2.8
ruff                      0.1.14
selenium                  4.16.0
setuptools                69.0.2
six                       1.16.0
smartkitty                2.2.1
sniffio                   1.3.0
sortedcontainers          2.4.0
soupsieve                 2.5
SQLAlchemy                2.0.25
sqlalchemy-hana           1.1.1
stack-data                0.6.3
subprocess-tee            0.4.1
tabulate                  0.9.0
testresources             2.0.1
tomlkit                   0.12.3
tornado                   6.4
traitlets                 5.14.0
trio                      0.23.2
trio-websocket            0.11.1
types-hdbcli              2.19.0.20240106
types-python-dateutil     2.8.19.14
types-requests            2.31.0.6
types-setuptools          69.0.0.0
types-urllib3             1.26.25.14
typing_extensions         4.9.0
untokenize                0.1.1
uri-template              1.3.0
uritemplate               4.1.1
urllib3                   1.26.18
virtualenv                20.25.0
voluptuous                0.14.1
watchdog                  3.0.0
wcmatch                   8.5
wcwidth                   0.2.12
webcolors                 1.13
websockets                12.0
wsproto                   1.2.0
xmltodict                 0.13.0
yamllint                  1.33.0
yamlloader                1.3.2
yarl                      1.9.4
zeep                      4.2.1
STEPS TO REPRODUCE

Assuming you have ansible and community.crypto installed, you execute a playbook like this:

---
- name: Private key check
  hosts: localhost
  gather_facts: false
  vars:
    pk_name: private.key
    pk_passphrase: password
  tasks:
    - name: Create temporary directory for output
      ansible.builtin.tempfile:
        state: directory
        prefix: test
      register: tmp_path
      
    - name: Set facts
      ansible.builtin.set_fact:
        pk_path: "{{ tmp_path.path }}/{{ pk_name }}"
        
    - name: Get private key information
      community.crypto.openssl_privatekey_info:
        path: "{{ pk_path }}"
        passphrase: "{{ pk_passphrase }}"
        check_consistency: true
      register: pk_content
EXPECTED RESULTS

The playbook above should finish with no errors.

ACTUAL RESULTS
PLAY [Private key check] ****************************************

TASK [Create temporary directory for output] ***********************************
changed: [localhost]

TASK [Set facts] ***************************************************************
ok: [localhost]

TASK [Get private key information] *********************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'cryptography.hazmat.bindings._rust.openssl.rsa.RSA' object has no attribute '_backend'
fatal: [localhost]: FAILED! => {
    "changed": false,
    "rc": 1
}

MSG:

MODULE FAILURE
See stdout/stderr for the exact error


MODULE_STDERR:

Traceback (most recent call last):
  File "/home/users/sxprietj/.ansible/tmp/ansible-tmp-1706257576.8649735-3966395-27432709708104/AnsiballZ_openssl_privatekey_info.py", line 107, in <module>
    _ansiballz_main()
  File "/home/users/sxprietj/.ansible/tmp/ansible-tmp-1706257576.8649735-3966395-27432709708104/AnsiballZ_openssl_privatekey_info.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/home/users/sxprietj/.ansible/tmp/ansible-tmp-1706257576.8649735-3966395-27432709708104/AnsiballZ_openssl_privatekey_info.py", line 47, in invoke_module
    runpy.run_module(mod_name='ansible_collections.community.crypto.plugins.modules.openssl_privatekey_info', init_globals=dict(_module_fqn='ansible_collections.community.crypto.plugins.modules.openssl_privatekey_info', _modlib_path=modlib_path),
  File "<frozen runpy>", line 226, in run_module
  File "<frozen runpy>", line 98, in _run_module_code
  File "<frozen runpy>", line 88, in _run_code
  File "/tmp/ansible_community.crypto.openssl_privatekey_info_payload_by34o3v2/ansible_community.crypto.openssl_privatekey_info_payload.zip/ansible_collections/community/crypto/plugins/modules/openssl_privatekey_info.py", line 277, in <module>
  File "/tmp/ansible_community.crypto.openssl_privatekey_info_payload_by34o3v2/ansible_community.crypto.openssl_privatekey_info_payload.zip/ansible_collections/community/crypto/plugins/modules/openssl_privatekey_info.py", line 264, in main
  File "/tmp/ansible_community.crypto.openssl_privatekey_info_payload_by34o3v2/ansible_community.crypto.openssl_privatekey_info_payload.zip/ansible_collections/community/crypto/plugins/module_utils/crypto/module_backends/privatekey_info.py", line 230, in get_info
  File "/tmp/ansible_community.crypto.openssl_privatekey_info_payload_by34o3v2/ansible_community.crypto.openssl_privatekey_info_payload.zip/ansible_collections/community/crypto/plugins/module_utils/crypto/module_backends/privatekey_info.py", line 256, in _is_key_consistent
  File "/tmp/ansible_community.crypto.openssl_privatekey_info_payload_by34o3v2/ansible_community.crypto.openssl_privatekey_info_payload.zip/ansible_collections/community/crypto/plugins/module_utils/crypto/module_backends/privatekey_info.py", line 110, in _is_cryptography_key_consistent
AttributeError: 'cryptography.hazmat.bindings._rust.openssl.rsa.RSA' object has no attribute '_backend'


PLAY RECAP *********************************************************************
localhost                  : ok=2   changed=2    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
@felixfontein felixfontein added the bug Something isn't working label Jan 26, 2024
@felixfontein
Copy link
Contributor

As a workaround you can either stick to cryptography < 42.0.0, or disable that check. There will be a new version of the collection ~this weekend fixing this bug.

@PrieJos
Copy link
Author

PrieJos commented Jan 26, 2024

Hi

As a workaround you can either stick to cryptography < 42.0.0, or disable that check. There will be a new version of the collection ~this weekend fixing this bug.

Yes. That was what we in fact did (disable the check).

Thanks! Looking forward for that fix.

Cheers
Jose M. Prieto

@felixfontein
Copy link
Contributor

Please note that it won't be a real fix for the functionality, since that is no longer reachable with cryptography 42.0.0+. It will simply disable the consistency check for RSA private keys, and the test will return none (instead of true/false) for RSA keys.

#702 contains the fix.

Out of curiosity, what is your use-case for check_consistency=true? Are you using it as a sanity check for self-generated keys, or are you using it to check keys provided by users / other services you don't trust? In the latter case you might want to use openssl rsa -in /path/to/key -check -noout instead. (We could also create a new module for wrapping the openssl CLI for this, if there's interest in it.)

@PrieJos
Copy link
Author

PrieJos commented Jan 30, 2024

Hi @felixfontein

Please note that it won't be a real fix for the functionality, since that is no longer reachable with cryptography 42.0.0+. It will simply disable the consistency check for RSA private keys, and the test will return none (instead of true/false) for RSA keys.

#702 contains the fix.

Thanks for this. We are completely fine with that approach.

Out of curiosity, what is your use-case for check_consistency=true? Are you using it as a sanity check for self-generated keys, or are you using it to check keys provided by users / other services you don't trust? In the latter case you might want to use openssl rsa -in /path/to/key -check -noout instead. (We could also create a new module for wrapping the openssl CLI for this, if there's interest in it.)

Well we were using the consistency check simply in a test playbook which was part of a molecule test scenario. That was the context. So we are not using this functionality in production.

Thanks again for your support.

Cheers
Jose M. Prieto

@yyarmoshyk
Copy link

the following did the trick in my case

pip3 install cryptography==41.0.5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
3 participants