ansible-collections / community.crypto

The community.crypto collection for Ansible.
https://galaxy.ansible.com/ui/repo/published/community/crypto/
Other
97 stars 88 forks source link

The attribute passphrase and cipher should be independent #793

Closed felipenazario closed 1 month ago

felipenazario commented 1 month ago
SUMMARY

The openssl allow us to generate a private key using or not encrypted keys. But the following module is not allowing us the same support.

ISSUE TYPE
COMPONENT NAME

community.crypto.openssl_privatekey

ANSIBLE VERSION
ansible [core 2.16.10]
  config file = None
  configured module search path = ['/home/marcos/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/marcos/desenvolvimento/workspace_infra/InfraAsCode/.pyenv_for_3.12.5/lib/python3.12/site-packages/ansible
  ansible collection location = /home/marcos/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/marcos/desenvolvimento/workspace_infra/InfraAsCode/.pyenv_for_3.12.5/bin/ansible
  python version = 3.12.5 (main, Aug 12 2024, 11:29:32) [GCC 7.5.0] (/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/.pyenv_for_3.12.5/bin/python)
  jinja version = 3.1.4
COLLECTION VERSION
Collection       Version
---------------- -------
community.crypto 2.22.0
CONFIGURATION
CALLBACKS_ENABLED(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = ['ansible.posix.timer', 'ansible.posix.profile_roles', 'ansible.posix.profile>
COLLECTIONS_PATHS(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = ['/opt/ansible/collections', '/home/marcos/desenvolvimento/workspace_infra/In>
CONFIG_FILE() = /home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg
DEFAULT_FORKS(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = 10
DEFAULT_HOST_LIST(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = ['/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/inve>
DEFAULT_PRIVATE_ROLE_VARS(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = True
DEFAULT_ROLES_PATH(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = ['/opt/ansible/roles', '/home/marcos/desenvolvimento/workspace_infra/InfraAs>
DEFAULT_TIMEOUT(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = 15
DEPRECATION_WARNINGS(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = True
HOST_KEY_CHECKING(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = False
INTERPRETER_PYTHON(/home/marcos/desenvolvimento/workspace_infra/InfraAsCode/ansible/linux/ansible.cfg) = auto
PAGER(env: PAGER) = less
OS / ENVIRONMENT

NAME="openSUSE Leap" VERSION="15.3" ID="opensuse-leap" ID_LIKE="suse opensuse" VERSION_ID="15.3" PRETTY_NAME="openSUSE Leap 15.3" ANSI_COLOR="0;32" CPE_NAME="cpe:/o:opensuse:leap:15.3" BUG_REPORT_URL="https://bugs.opensuse.org" HOME_URL="https://www.opensuse.org/"

STEPS TO REPRODUCE

I always generated private key in bash.

export PASSWD_SERVER_KEY='123456'

echo 'Generate server private key.'
openssl \
genrsa \
-passout pass:$PASSWD_SERVER_KEY \
-out server.key 8192

However, I'm having difficulty converting this to task, as we apparently don't have the equivalent.

EXPECTED RESULTS

Notice that in the task I am informing passphrase field, but also omitting cipher field to be 100% equivalent to openssl. Unfortunately, there is a bond between these fields.

- name: 'Generate server private key.'
  community.crypto.openssl_privatekey:
    path: "/etc/my_certificates/server.key"
    passphrase: "123456"
    select_crypto_backend: cryptography
    cipher: "{{ omit }}"
    type: RSA
    state: 'present'
    size: 8192
    owner: root
    group: root
    mode: '440'
ACTUAL RESULTS

Notice that in the task I am must omit the passphrase field because it that works together with the cipher, even though this dependency does not exist in the equivalent openssl command.

- name: 'Generate server private key.'
  community.crypto.openssl_privatekey:
    path: "/etc/my_certificates/server.key"
    passphrase: "{{ omit }}"
    select_crypto_backend: cryptography
    cipher: "{{ omit }}"
    type: RSA
    state: 'present'
    size: 8192
    owner: root
    group: root
    mode: '440'

Am I doing something wrong in the task or the task is it just like that? Is it possible to revoke this dependency between the passphrase and cipher attributes?

felixfontein commented 1 month ago

This collection does not aim to be 100% compatible to OpenSSL (the name prefix openssl_ for the module name is mainly legacy), so this is definitely not a bug.

Also the cipher is only used when a passphrase is specified (it's the cipher used to encrypt the key with the given passphrase). So cipher and passphrase are very dependent on each other.

Since we dropped the PyOpenSSL backend the only valid value for cipher is auto, so I guess we can give cipher a default value so there's no more need to specify it. That would be an enhancement.

felixfontein commented 1 month ago

794 implements the default value.

felixfontein commented 1 month ago

(Actually with cryptography 38.0.0 it is possible to configure this a bit: https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/#cryptography.hazmat.primitives.serialization.PrivateFormat.encryption_builder - the only option of the returned builder that seems to affect regular private keys is kdf_rounds though. So it doesn't make sense yet to add more options to cipher, or create new options for that.)