Added support for certificates in DER format for `x509_certificate_info` module (#622)

* Added support for DER format

* Updated description

* Adjusted description

The content of the certificate cannot be in DER format due to an input encoding problem in the Ansible module, but it works fine when reading the certificate from a file

* Update support.py

* Added der_support_enabled flag for DER-format support

* Added changelog fragment for #603

* Fixed typo

* Fixed missing import

* Resolved issues found by static code analysis

* Update plugins/module_utils/crypto/support.py

Committed suggested change

Co-authored-by: Felix Fontein <felix@fontein.de>

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
pull/623/head
Marcin Słowikowski 2023-06-15 12:51:14 +02:00 committed by GitHub
parent a7e9bb7618
commit 9c07a8354e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 25 additions and 9 deletions

View File

@ -0,0 +1,2 @@
minor_changes:
- "x509_certificate_info - added support for certificates in DER format when using ``path`` parameter (https://github.com/ansible-collections/community.crypto/issues/603)."

View File

@ -143,9 +143,9 @@ class CertificateInfoRetrieval(object):
def _get_issuer_uri(self): def _get_issuer_uri(self):
pass pass
def get_info(self, prefer_one_fingerprint=False): def get_info(self, prefer_one_fingerprint=False, der_support_enabled=False):
result = dict() result = dict()
self.cert = load_certificate(None, content=self.content, backend=self.backend) self.cert = load_certificate(None, content=self.content, backend=self.backend, der_support_enabled=der_support_enabled)
result['signature_algorithm'] = self._get_signature_algorithm() result['signature_algorithm'] = self._get_signature_algorithm()
subject = self._get_subject_ordered() subject = self._get_subject_ordered()

View File

@ -18,6 +18,10 @@ import re
from ansible.module_utils import six from ansible.module_utils import six
from ansible.module_utils.common.text.converters import to_native, to_bytes from ansible.module_utils.common.text.converters import to_native, to_bytes
from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import (
identify_pem_format,
)
try: try:
from OpenSSL import crypto from OpenSSL import crypto
HAS_PYOPENSSL = True HAS_PYOPENSSL = True
@ -189,7 +193,7 @@ def load_publickey(path=None, content=None, backend=None):
raise OpenSSLObjectError('Error while deserializing key: {0}'.format(e)) raise OpenSSLObjectError('Error while deserializing key: {0}'.format(e))
def load_certificate(path, content=None, backend='cryptography'): def load_certificate(path, content=None, backend='cryptography', der_support_enabled=False):
"""Load the specified certificate.""" """Load the specified certificate."""
try: try:
@ -201,12 +205,21 @@ def load_certificate(path, content=None, backend='cryptography'):
except (IOError, OSError) as exc: except (IOError, OSError) as exc:
raise OpenSSLObjectError(exc) raise OpenSSLObjectError(exc)
if backend == 'pyopenssl': if backend == 'pyopenssl':
if der_support_enabled is False or identify_pem_format(cert_content):
return crypto.load_certificate(crypto.FILETYPE_PEM, cert_content) return crypto.load_certificate(crypto.FILETYPE_PEM, cert_content)
elif der_support_enabled:
raise OpenSSLObjectError('Certificate in DER format is not supported by the pyopenssl backend.')
elif backend == 'cryptography': elif backend == 'cryptography':
if der_support_enabled is False or identify_pem_format(cert_content):
try: try:
return x509.load_pem_x509_certificate(cert_content, cryptography_backend()) return x509.load_pem_x509_certificate(cert_content, cryptography_backend())
except ValueError as exc: except ValueError as exc:
raise OpenSSLObjectError(exc) raise OpenSSLObjectError(exc)
elif der_support_enabled:
try:
return x509.load_der_x509_certificate(cert_content, cryptography_backend())
except ValueError as exc:
raise OpenSSLObjectError('Cannot parse DER certificate: {0}'.format(exc))
def load_certificate_request(path, content=None, backend='cryptography'): def load_certificate_request(path, content=None, backend='cryptography'):

View File

@ -40,6 +40,7 @@ options:
description: description:
- Remote absolute path where the certificate file is loaded from. - Remote absolute path where the certificate file is loaded from.
- Either I(path) or I(content) must be specified, but not both. - Either I(path) or I(content) must be specified, but not both.
- PEM and DER formats are supported.
type: path type: path
content: content:
description: description:
@ -447,7 +448,7 @@ def main():
valid_at[k] = get_relative_time_option(v, 'valid_at.{0}'.format(k)) valid_at[k] = get_relative_time_option(v, 'valid_at.{0}'.format(k))
try: try:
result = module_backend.get_info() result = module_backend.get_info(der_support_enabled=module.params['content'] is None)
not_before = module_backend.get_not_before() not_before = module_backend.get_not_before()
not_after = module_backend.get_not_after() not_after = module_backend.get_not_after()