openssl_publickey: add cryptography backend (#60387)
* Add cryptography backend. * Add changelog. * Make sure requirements are satisfied. * Use more compatible elliptic curve. * Decrease required version numbers. * PyOpenSSL >= 16.0.0 is really needed. * Update lib/ansible/modules/crypto/openssl_publickey.py Co-Authored-By: MarkusTeufelberger <mteufelberger@mgit.at>
This commit is contained in:
parent
13996aaff6
commit
6a786d0d93
5 changed files with 333 additions and 200 deletions
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- "openssl_publickey - now works with both PyOpenSSL and cryptography Python libraries. Autodetection can be overridden with ``select_crypto_backend`` option."
|
|
@ -18,14 +18,18 @@ version_added: "2.3"
|
|||
short_description: Generate an OpenSSL public key from its private key.
|
||||
description:
|
||||
- This module allows one to (re)generate OpenSSL public keys from their private keys.
|
||||
- It uses the pyOpenSSL python library to interact with openssl.
|
||||
- Keys are generated in PEM format.
|
||||
- This module works only if the version of PyOpenSSL is recent enough (> 16.0.0).
|
||||
- Keys are generated in PEM or OpenSSH format.
|
||||
- The module can use the cryptography Python library, or the pyOpenSSL Python
|
||||
library. By default, it tries to detect which one is available. This can be
|
||||
overridden with the I(select_crypto_backend) option. When I(format) is C(OpenSSH),
|
||||
the C(cryptography) backend has to be used."
|
||||
requirements:
|
||||
- pyOpenSSL
|
||||
- cryptography (if I(format) is C(OpenSSH))
|
||||
- Either cryptography >= 1.2.3 (older versions might work as well)
|
||||
- Or pyOpenSSL >= 16.0.0
|
||||
- Needs cryptography >= 1.4 if I(format) is C(OpenSSH)
|
||||
author:
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Yanis Guenane (@Spredzy)
|
||||
- Felix Fontein (@felixfontein)
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
|
@ -67,6 +71,16 @@ options:
|
|||
type: bool
|
||||
default: no
|
||||
version_added: "2.8"
|
||||
select_crypto_backend:
|
||||
description:
|
||||
- Determines which crypto backend to use.
|
||||
- The default choice is C(auto), which tries to use C(cryptography) if available, and falls back to C(pyopenssl).
|
||||
- If set to C(pyopenssl), will try to use the L(pyOpenSSL,https://pypi.org/project/pyOpenSSL/) library.
|
||||
- If set to C(cryptography), will try to use the L(cryptography,https://cryptography.io/) library.
|
||||
type: str
|
||||
default: auto
|
||||
choices: [ auto, cryptography, pyopenssl ]
|
||||
version_added: "2.9"
|
||||
extends_documentation_fragment:
|
||||
- files
|
||||
seealso:
|
||||
|
@ -146,25 +160,34 @@ backup_file:
|
|||
|
||||
import os
|
||||
import traceback
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
MINIMAL_PYOPENSSL_VERSION = '16.0.0'
|
||||
MINIMAL_CRYPTOGRAPHY_VERSION = '1.2.3'
|
||||
MINIMAL_CRYPTOGRAPHY_VERSION_OPENSSH = '1.4'
|
||||
|
||||
PYOPENSSL_IMP_ERR = None
|
||||
try:
|
||||
import OpenSSL
|
||||
from OpenSSL import crypto
|
||||
PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__)
|
||||
except ImportError:
|
||||
PYOPENSSL_IMP_ERR = traceback.format_exc()
|
||||
pyopenssl_found = False
|
||||
PYOPENSSL_FOUND = False
|
||||
else:
|
||||
pyopenssl_found = True
|
||||
PYOPENSSL_FOUND = True
|
||||
|
||||
CRYPTOGRAPHY_IMP_ERR = None
|
||||
try:
|
||||
import cryptography
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import serialization as crypto_serialization
|
||||
CRYPTOGRAPHY_VERSION = LooseVersion(cryptography.__version__)
|
||||
except ImportError:
|
||||
CRYPTOGRAPHY_IMP_ERR = traceback.format_exc()
|
||||
cryptography_found = False
|
||||
CRYPTOGRAPHY_FOUND = False
|
||||
else:
|
||||
cryptography_found = True
|
||||
CRYPTOGRAPHY_FOUND = True
|
||||
|
||||
from ansible.module_utils import crypto as crypto_utils
|
||||
from ansible.module_utils._text import to_native, to_bytes
|
||||
|
@ -177,7 +200,7 @@ class PublicKeyError(crypto_utils.OpenSSLObjectError):
|
|||
|
||||
class PublicKey(crypto_utils.OpenSSLObject):
|
||||
|
||||
def __init__(self, module):
|
||||
def __init__(self, module, backend):
|
||||
super(PublicKey, self).__init__(
|
||||
module.params['path'],
|
||||
module.params['state'],
|
||||
|
@ -189,10 +212,34 @@ class PublicKey(crypto_utils.OpenSSLObject):
|
|||
self.privatekey_passphrase = module.params['privatekey_passphrase']
|
||||
self.privatekey = None
|
||||
self.fingerprint = {}
|
||||
self.backend = backend
|
||||
|
||||
self.backup = module.params['backup']
|
||||
self.backup_file = None
|
||||
|
||||
def _create_publickey(self, module):
|
||||
self.privatekey = crypto_utils.load_privatekey(
|
||||
self.privatekey_path,
|
||||
self.privatekey_passphrase,
|
||||
backend=self.backend
|
||||
)
|
||||
if self.backend == 'cryptography':
|
||||
if self.format == 'OpenSSH':
|
||||
return self.privatekey.public_key().public_bytes(
|
||||
crypto_serialization.Encoding.OpenSSH,
|
||||
crypto_serialization.PublicFormat.OpenSSH
|
||||
)
|
||||
else:
|
||||
return self.privatekey.public_key().public_bytes(
|
||||
crypto_serialization.Encoding.PEM,
|
||||
crypto_serialization.PublicFormat.SubjectPublicKeyInfo
|
||||
)
|
||||
else:
|
||||
try:
|
||||
return crypto.dump_publickey(crypto.FILETYPE_PEM, self.privatekey)
|
||||
except AttributeError as exc:
|
||||
raise PublicKeyError('You need to have PyOpenSSL>=16.0.0 to generate public keys')
|
||||
|
||||
def generate(self, module):
|
||||
"""Generate the public key."""
|
||||
|
||||
|
@ -203,23 +250,7 @@ class PublicKey(crypto_utils.OpenSSLObject):
|
|||
|
||||
if not self.check(module, perms_required=False) or self.force:
|
||||
try:
|
||||
if self.format == 'OpenSSH':
|
||||
with open(self.privatekey_path, 'rb') as private_key_fh:
|
||||
privatekey_content = private_key_fh.read()
|
||||
key = crypto_serialization.load_pem_private_key(
|
||||
privatekey_content,
|
||||
password=None if self.privatekey_passphrase is None else to_bytes(self.privatekey_passphrase),
|
||||
backend=default_backend()
|
||||
)
|
||||
publickey_content = key.public_key().public_bytes(
|
||||
crypto_serialization.Encoding.OpenSSH,
|
||||
crypto_serialization.PublicFormat.OpenSSH
|
||||
)
|
||||
else:
|
||||
self.privatekey = crypto_utils.load_privatekey(
|
||||
self.privatekey_path, self.privatekey_passphrase
|
||||
)
|
||||
publickey_content = crypto.dump_publickey(crypto.FILETYPE_PEM, self.privatekey)
|
||||
publickey_content = self._create_publickey(module)
|
||||
|
||||
if self.backup:
|
||||
self.backup_file = module.backup_local(self.path)
|
||||
|
@ -230,8 +261,6 @@ class PublicKey(crypto_utils.OpenSSLObject):
|
|||
raise PublicKeyError(exc)
|
||||
except (IOError, OSError) as exc:
|
||||
raise PublicKeyError(exc)
|
||||
except AttributeError as exc:
|
||||
raise PublicKeyError('You need to have PyOpenSSL>=16.0.0 to generate public keys')
|
||||
|
||||
self.fingerprint = crypto_utils.get_fingerprint(
|
||||
self.privatekey_path,
|
||||
|
@ -253,26 +282,34 @@ class PublicKey(crypto_utils.OpenSSLObject):
|
|||
try:
|
||||
with open(self.path, 'rb') as public_key_fh:
|
||||
publickey_content = public_key_fh.read()
|
||||
if self.format == 'OpenSSH':
|
||||
current_publickey = crypto_serialization.load_ssh_public_key(publickey_content, backend=default_backend())
|
||||
publickey_content = current_publickey.public_bytes(crypto_serialization.Encoding.PEM,
|
||||
crypto_serialization.PublicFormat.SubjectPublicKeyInfo)
|
||||
current_publickey = crypto.dump_publickey(
|
||||
crypto.FILETYPE_ASN1,
|
||||
crypto.load_publickey(crypto.FILETYPE_PEM, publickey_content)
|
||||
)
|
||||
if self.backend == 'cryptography':
|
||||
if self.format == 'OpenSSH':
|
||||
# Read and dump public key. Makes sure that the comment is stripped off.
|
||||
current_publickey = crypto_serialization.load_ssh_public_key(publickey_content, backend=default_backend())
|
||||
publickey_content = current_publickey.public_bytes(
|
||||
crypto_serialization.Encoding.OpenSSH,
|
||||
crypto_serialization.PublicFormat.OpenSSH
|
||||
)
|
||||
else:
|
||||
current_publickey = crypto_serialization.load_pem_public_key(publickey_content, backend=default_backend())
|
||||
publickey_content = current_publickey.public_bytes(
|
||||
crypto_serialization.Encoding.PEM,
|
||||
crypto_serialization.PublicFormat.SubjectPublicKeyInfo
|
||||
)
|
||||
else:
|
||||
publickey_content = crypto.dump_publickey(
|
||||
crypto.FILETYPE_PEM,
|
||||
crypto.load_publickey(crypto.FILETYPE_PEM, publickey_content)
|
||||
)
|
||||
except Exception as dummy:
|
||||
return False
|
||||
|
||||
try:
|
||||
desired_publickey = crypto.dump_publickey(
|
||||
crypto.FILETYPE_ASN1,
|
||||
crypto_utils.load_privatekey(self.privatekey_path, self.privatekey_passphrase)
|
||||
)
|
||||
desired_publickey = self._create_publickey(module)
|
||||
except crypto_utils.OpenSSLBadPassphraseError as exc:
|
||||
raise PublicKeyError(exc)
|
||||
|
||||
return current_publickey == desired_publickey
|
||||
return publickey_content == desired_publickey
|
||||
|
||||
if not state_and_perms:
|
||||
return state_and_perms
|
||||
|
@ -311,16 +348,52 @@ def main():
|
|||
format=dict(type='str', default='PEM', choices=['OpenSSH', 'PEM']),
|
||||
privatekey_passphrase=dict(type='str', no_log=True),
|
||||
backup=dict(type='bool', default=False),
|
||||
select_crypto_backend=dict(type='str', choices=['auto', 'pyopenssl', 'cryptography'], default='auto'),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
add_file_common_args=True,
|
||||
required_if=[('state', 'present', ['privatekey_path'])],
|
||||
)
|
||||
|
||||
if not pyopenssl_found:
|
||||
module.fail_json(msg=missing_required_lib('pyOpenSSL'), exception=PYOPENSSL_IMP_ERR)
|
||||
if module.params['format'] == 'OpenSSH' and not cryptography_found:
|
||||
module.fail_json(msg=missing_required_lib('cryptography'), exception=CRYPTOGRAPHY_IMP_ERR)
|
||||
minimal_cryptography_version = MINIMAL_CRYPTOGRAPHY_VERSION
|
||||
if module.params['format'] == 'OpenSSH':
|
||||
minimal_cryptography_version = MINIMAL_CRYPTOGRAPHY_VERSION_OPENSSH
|
||||
|
||||
backend = module.params['select_crypto_backend']
|
||||
if backend == 'auto':
|
||||
# Detection what is possible
|
||||
can_use_cryptography = CRYPTOGRAPHY_FOUND and CRYPTOGRAPHY_VERSION >= LooseVersion(minimal_cryptography_version)
|
||||
can_use_pyopenssl = PYOPENSSL_FOUND and PYOPENSSL_VERSION >= LooseVersion(MINIMAL_PYOPENSSL_VERSION)
|
||||
|
||||
# Decision
|
||||
if can_use_cryptography:
|
||||
backend = 'cryptography'
|
||||
elif can_use_pyopenssl:
|
||||
if module.params['format'] == 'OpenSSH':
|
||||
module.fail_json(
|
||||
msg=missing_required_lib('cryptography >= {0}'.format(MINIMAL_CRYPTOGRAPHY_VERSION_OPENSSH)),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR
|
||||
)
|
||||
backend = 'pyopenssl'
|
||||
|
||||
# Success?
|
||||
if backend == 'auto':
|
||||
module.fail_json(msg=("Can't detect any of the required Python libraries "
|
||||
"cryptography (>= {0}) or PyOpenSSL (>= {1})").format(
|
||||
minimal_cryptography_version,
|
||||
MINIMAL_PYOPENSSL_VERSION))
|
||||
|
||||
if module.params['format'] == 'OpenSSH' and backend != 'cryptography':
|
||||
module.fail_json(msg="Format OpenSSH requires the cryptography backend.")
|
||||
|
||||
if backend == 'pyopenssl':
|
||||
if not PYOPENSSL_FOUND:
|
||||
module.fail_json(msg=missing_required_lib('pyOpenSSL >= {0}'.format(MINIMAL_PYOPENSSL_VERSION)),
|
||||
exception=PYOPENSSL_IMP_ERR)
|
||||
elif backend == 'cryptography':
|
||||
if not CRYPTOGRAPHY_FOUND:
|
||||
module.fail_json(msg=missing_required_lib('cryptography >= {0}'.format(minimal_cryptography_version)),
|
||||
exception=CRYPTOGRAPHY_IMP_ERR)
|
||||
|
||||
base_dir = os.path.dirname(module.params['path']) or '.'
|
||||
if not os.path.isdir(base_dir):
|
||||
|
@ -330,7 +403,7 @@ def main():
|
|||
)
|
||||
|
||||
try:
|
||||
public_key = PublicKey(module)
|
||||
public_key = PublicKey(module, backend)
|
||||
|
||||
if public_key.state == 'present':
|
||||
if module.check_mode:
|
||||
|
|
166
test/integration/targets/openssl_publickey/tasks/impl.yml
Normal file
166
test/integration/targets/openssl_publickey/tasks/impl.yml
Normal file
|
@ -0,0 +1,166 @@
|
|||
---
|
||||
- name: Generate privatekey
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey.pem'
|
||||
|
||||
- name: Generate publickey - PEM format
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Generate publickey - OpenSSH format
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey-ssh.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
format: OpenSSH
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
|
||||
|
||||
- name: Generate publickey - OpenSSH format - test idempotence (issue 33256)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey-ssh.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
format: OpenSSH
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
|
||||
register: publickey_ssh_idempotence
|
||||
|
||||
- name: Generate publickey2 - standard
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey2.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Delete publickey2 - standard
|
||||
openssl_publickey:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/publickey2.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Generate privatekey3 - with passphrase
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey3.pem'
|
||||
passphrase: ansible
|
||||
cipher: aes256
|
||||
|
||||
- name: Generate publickey3 - with passphrase protected privatekey
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey3.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey3.pem'
|
||||
privatekey_passphrase: ansible
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Generate publickey3 - with passphrase protected privatekey - idempotence
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey3.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey3.pem'
|
||||
privatekey_passphrase: ansible
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: publickey3_idempotence
|
||||
|
||||
- name: Generate empty file that will hold a public key (issue 33072)
|
||||
file:
|
||||
path: '{{ output_dir }}/publickey4.pub'
|
||||
state: touch
|
||||
|
||||
- name: Generate publickey in empty existing file (issue 33072)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey4.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Generate privatekey 5 (ECC)
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey5.pem'
|
||||
type: ECC
|
||||
curve: secp256r1
|
||||
|
||||
- name: Generate publickey 5 - PEM format
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey5.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
backup: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: privatekey5_1
|
||||
- name: Generate publickey 5 - PEM format (idempotent)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey5.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
backup: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: privatekey5_2
|
||||
- name: Generate publickey 5 - PEM format (different private key)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey5.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey5.pem'
|
||||
backup: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: privatekey5_3
|
||||
|
||||
- name: Generate privatekey with password
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: auto
|
||||
select_crypto_backend: cryptography
|
||||
|
||||
- name: Generate publickey - PEM format (failed passphrase 1)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey_pw1.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
privatekey_passphrase: hunter2
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
ignore_errors: yes
|
||||
register: passphrase_error_1
|
||||
|
||||
- name: Generate publickey - PEM format (failed passphrase 2)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey_pw2.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
privatekey_passphrase: wrong_password
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
ignore_errors: yes
|
||||
register: passphrase_error_2
|
||||
|
||||
- name: Generate publickey - PEM format (failed passphrase 3)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey_pw3.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
ignore_errors: yes
|
||||
register: passphrase_error_3
|
||||
|
||||
- name: Create broken key
|
||||
copy:
|
||||
dest: "{{ output_dir }}/publickeybroken.pub"
|
||||
content: "broken"
|
||||
- name: Regenerate broken key
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickeybroken.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey5.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: output_broken
|
||||
|
||||
- name: Generate publickey - PEM format (for removal)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey_removal.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
- name: Generate publickey - PEM format (removal)
|
||||
openssl_publickey:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/publickey_removal.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
backup: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: remove_1
|
||||
- name: Generate publickey - PEM format (removal, idempotent)
|
||||
openssl_publickey:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/publickey_removal.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
backup: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: remove_2
|
|
@ -1,156 +1,48 @@
|
|||
---
|
||||
- block:
|
||||
- name: Generate privatekey
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey.pem'
|
||||
- name: Generate privatekey1 - standard
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey_autodetect.pem'
|
||||
|
||||
- name: Generate publickey - PEM format
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
- name: Run module with backend autodetection
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/privatekey_autodetect_public.pem'
|
||||
privatekey_path: '{{ output_dir }}/privatekey_autodetect.pem'
|
||||
|
||||
- name: Generate publickey - OpenSSH format
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey-ssh.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
format: OpenSSH
|
||||
# cryptography.hazmat.primitives import serialization.Encoding.OpenSSH and
|
||||
# cryptography.hazmat.primitives import serialization.PublicFormat.OpenSSH constants
|
||||
# appeared in version 1.4 of cryptography
|
||||
when: cryptography_version.stdout is version('1.4.0', '>=')
|
||||
when: |
|
||||
pyopenssl_version.stdout is version('16.0.0', '>=') or
|
||||
cryptography_version.stdout is version('1.2.3', '>=')
|
||||
|
||||
- name: Generate publickey - OpenSSH format - test idempotence (issue 33256)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey-ssh.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
format: OpenSSH
|
||||
when: cryptography_version.stdout is version('1.4.0', '>=')
|
||||
register: publickey_ssh_idempotence
|
||||
- block:
|
||||
- name: Running tests with pyOpenSSL backend
|
||||
include_tasks: impl.yml
|
||||
vars:
|
||||
select_crypto_backend: pyopenssl
|
||||
|
||||
- name: Generate publickey2 - standard
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey2.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
|
||||
- name: Delete publickey2 - standard
|
||||
openssl_publickey:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/publickey2.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
|
||||
- name: Generate privatekey3 - with passphrase
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey3.pem'
|
||||
passphrase: ansible
|
||||
cipher: aes256
|
||||
|
||||
- name: Generate publickey3 - with passphrase protected privatekey
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey3.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey3.pem'
|
||||
privatekey_passphrase: ansible
|
||||
|
||||
- name: Generate publickey3 - with passphrase protected privatekey - idempotence
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey3.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey3.pem'
|
||||
privatekey_passphrase: ansible
|
||||
register: publickey3_idempotence
|
||||
|
||||
- name: Generate empty file that will hold a public key (issue 33072)
|
||||
file:
|
||||
path: '{{ output_dir }}/publickey4.pub'
|
||||
state: touch
|
||||
|
||||
- name: Generate publickey in empty existing file (issue 33072)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey4.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
|
||||
- name: Generate privatekey 5 (ECC)
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey5.pem'
|
||||
type: ECC
|
||||
curve: secp256k1
|
||||
|
||||
- name: Generate publickey 5 - PEM format
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey5.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
backup: yes
|
||||
register: privatekey5_1
|
||||
- name: Generate publickey 5 - PEM format (idempotent)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey5.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
backup: yes
|
||||
register: privatekey5_2
|
||||
- name: Generate publickey 5 - PEM format (different private key)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey5.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey5.pem'
|
||||
backup: yes
|
||||
register: privatekey5_3
|
||||
|
||||
- name: Generate privatekey with password
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekeypw.pem'
|
||||
passphrase: hunter2
|
||||
cipher: auto
|
||||
select_crypto_backend: cryptography
|
||||
|
||||
- name: Generate publickey - PEM format (failed passphrase 1)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey_pw1.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
privatekey_passphrase: hunter2
|
||||
ignore_errors: yes
|
||||
register: passphrase_error_1
|
||||
|
||||
- name: Generate publickey - PEM format (failed passphrase 2)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey_pw2.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
privatekey_passphrase: wrong_password
|
||||
ignore_errors: yes
|
||||
register: passphrase_error_2
|
||||
|
||||
- name: Generate publickey - PEM format (failed passphrase 3)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey_pw3.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekeypw.pem'
|
||||
ignore_errors: yes
|
||||
register: passphrase_error_3
|
||||
|
||||
- name: Create broken key
|
||||
copy:
|
||||
dest: "{{ output_dir }}/publickeybroken.pub"
|
||||
content: "broken"
|
||||
- name: Regenerate broken key
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickeybroken.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey5.pem'
|
||||
register: output_broken
|
||||
|
||||
- name: Generate publickey - PEM format (for removal)
|
||||
openssl_publickey:
|
||||
path: '{{ output_dir }}/publickey_removal.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
- name: Generate publickey - PEM format (removal)
|
||||
openssl_publickey:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/publickey_removal.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
backup: yes
|
||||
register: remove_1
|
||||
- name: Generate publickey - PEM format (removal, idempotent)
|
||||
openssl_publickey:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/publickey_removal.pub'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
backup: yes
|
||||
register: remove_2
|
||||
|
||||
- import_tasks: ../tests/validate.yml
|
||||
- import_tasks: ../tests/validate.yml
|
||||
vars:
|
||||
select_crypto_backend: pyopenssl
|
||||
|
||||
when: pyopenssl_version.stdout is version('16.0.0', '>=')
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
- name: Running tests with cryptography backend
|
||||
include_tasks: impl.yml
|
||||
vars:
|
||||
select_crypto_backend: cryptography
|
||||
|
||||
- import_tasks: ../tests/validate.yml
|
||||
vars:
|
||||
select_crypto_backend: cryptography
|
||||
|
||||
when: cryptography_version.stdout is version('1.2.3', '>=')
|
||||
|
|
|
@ -15,25 +15,25 @@
|
|||
- name: Validate public key - OpenSSH format (test - privatekey's publickey)
|
||||
shell: 'ssh-keygen -y -f {{ output_dir }}/privatekey.pem'
|
||||
register: privatekey_publickey
|
||||
when: cryptography_version.stdout is version('1.4.0', '>=')
|
||||
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
|
||||
|
||||
- name: Validate public key - OpenSSH format (test - publickey)
|
||||
slurp:
|
||||
src: '{{ output_dir }}/publickey-ssh.pub'
|
||||
register: publickey
|
||||
when: cryptography_version.stdout is version('1.4.0', '>=')
|
||||
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
|
||||
|
||||
- name: Validate public key - OpenSSH format (assert)
|
||||
assert:
|
||||
that:
|
||||
- privatekey_publickey.stdout == '{{ publickey.content|b64decode }}'
|
||||
when: cryptography_version.stdout is version('1.4.0', '>=')
|
||||
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
|
||||
|
||||
- name: Validate public key - OpenSSH format - test idempotence (issue 33256)
|
||||
assert:
|
||||
that:
|
||||
- publickey_ssh_idempotence is not changed
|
||||
when: cryptography_version.stdout is version('1.4.0', '>=')
|
||||
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
|
||||
|
||||
- name: Validate publickey2 (test - Ensure key has been removed)
|
||||
stat:
|
||||
|
|
Loading…
Reference in a new issue