Skip to content

Commit

Permalink
Add validation option.
Browse files Browse the repository at this point in the history
  • Loading branch information
felixfontein committed Dec 28, 2024
1 parent ddbcf49 commit 5f924cc
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
3 changes: 3 additions & 0 deletions changelogs/fragments/830-x509-convert-verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- "x509_certificate_convert - add new option ``verify_cert_parsable`` which allows to check whether the certificate can actually be parsed
(https://github.com/ansible-collections/community.crypto/issues/809, https://github.com/ansible-collections/community.crypto/pull/830)."
41 changes: 40 additions & 1 deletion plugins/modules/x509_certificate_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
description:
- If the input is a PEM file, ensure that it contains a single PEM object, that the header and footer match, and are
of type C(CERTIFICATE) or C(X509 CERTIFICATE).
- See also the O(verify_cert_parsable) option, which checks whether the certificate is parsable.
type: bool
default: false
dest_path:
Expand All @@ -72,12 +73,21 @@
with a new one by accident.
type: bool
default: false
verify_cert_parsable:
description:
- If set to V(true), ensures that the certificate can be parsed.
- To ensure that a PEM file does not contain multiple certificates, use the O(strict) option.
type: bool
default: false
version_added: 2.23.0
seealso:
- plugin: ansible.builtin.b64encode
plugin_type: filter
- module: community.crypto.x509_certificate
- module: community.crypto.x509_certificate_pipe
- module: community.crypto.x509_certificate_info
requirements:
- cryptography >= 1.6 if O(verify_cert_parsable=true)
"""

EXAMPLES = r"""
Expand All @@ -98,8 +108,9 @@

import base64
import os
import traceback

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.common.text.converters import to_native, to_bytes, to_text

from ansible_collections.community.crypto.plugins.module_utils.io import (
Expand All @@ -124,6 +135,19 @@
OpenSSLObject,
)

MINIMAL_CRYPTOGRAPHY_VERSION = '1.6'

CRYPTOGRAPHY_IMP_ERR = None
try:
import cryptography # noqa: F401, pylint: disable=unused-import
from cryptography.x509 import load_der_x509_certificate
from cryptography.hazmat.backends import default_backend
except ImportError:
CRYPTOGRAPHY_IMP_ERR = traceback.format_exc()
CRYPTOGRAPHY_FOUND = False
else:
CRYPTOGRAPHY_FOUND = True


def parse_certificate(input, strict=False):
input_format = 'pem' if identify_pem_format(input) else 'der'
Expand Down Expand Up @@ -175,6 +199,9 @@ def __init__(self, module):
except Exception as exc:
module.fail_json(msg='Error while parsing PEM: {exc}'.format(exc=exc))

if module.params['verify_cert_parsable']:
self.verify_cert_parsable(module)

self.backup = module.params['backup']
self.backup_file = None

Expand All @@ -190,6 +217,17 @@ def __init__(self, module):
except Exception:
pass

def verify_cert_parsable(self, module):
if not CRYPTOGRAPHY_FOUND:
module.fail_json(
msg=missing_required_lib('cryptography >= {0}'.format(MINIMAL_CRYPTOGRAPHY_VERSION)),
exception=CRYPTOGRAPHY_IMP_ERR,
)
try:
load_der_x509_certificate(self.input, default_backend())
except Exception as exc:
module.fail_json(msg='Error while parsing certificate: {exc}'.format(exc=exc))

def needs_conversion(self):
if self.dest_content is None or self.dest_content_format is None:
return True
Expand Down Expand Up @@ -247,6 +285,7 @@ def main():
strict=dict(type='bool', default=False),
dest_path=dict(type='path', required=True),
backup=dict(type='bool', default=False),
verify_cert_parsable=dict(type='bool', default=False),
)
module = AnsibleModule(
argument_spec,
Expand Down
30 changes: 30 additions & 0 deletions tests/integration/targets/x509_certificate_convert/tasks/impl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,33 @@
- result_8 is not changed
- result_9 is not changed
- result_10 is not changed

- name: Create empty file
ansible.builtin.copy:
dest: '{{ remote_tmp_dir }}/empty'
content: ''

- name: Convert empty file to PEM (w/o verify)
community.crypto.x509_certificate_convert:
src_path: '{{ remote_tmp_dir }}/empty'
dest_path: '{{ remote_tmp_dir }}/empty.pem'
format: pem
verify_cert_parsable: false
register: result_1

- name: Convert empty file to PEM (w/ verify)
community.crypto.x509_certificate_convert:
src_path: '{{ remote_tmp_dir }}/empty'
dest_path: '{{ remote_tmp_dir }}/empty.pem'
format: pem
verify_cert_parsable: true
register: result_2
ignore_errors: true

- name: Check conditions
assert:
that:
- result_1 is changed
- result_2 is failed
- >-
result_2.msg.startswith('Error while parsing certificate: ')

0 comments on commit 5f924cc

Please sign in to comment.