From 05b0bdbe0ddf198e6dad4e15088875c10e13a00d Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 21 Jul 2020 15:33:05 +0200 Subject: [PATCH] Support arbitrary dotted notation for OIDs in cryptography backend (#91) * Support arbitrary dotted notation for OIDs in cryptography backend. * Add test. * Fix typos. * Fix order. --- changelogs/fragments/90-cryptography-oids.yml | 2 + .../crypto/cryptography_support.py | 12 +- .../targets/openssl_csr/tasks/impl.yml | 123 ++++++++++++------ .../targets/openssl_csr/tests/validate.yml | 43 ++++-- 4 files changed, 126 insertions(+), 54 deletions(-) create mode 100644 changelogs/fragments/90-cryptography-oids.yml diff --git a/changelogs/fragments/90-cryptography-oids.yml b/changelogs/fragments/90-cryptography-oids.yml new file mode 100644 index 00000000..c6301a9c --- /dev/null +++ b/changelogs/fragments/90-cryptography-oids.yml @@ -0,0 +1,2 @@ +minor_changes: +- "cryptography backends - support arbitrary dotted OIDs (https://github.com/ansible-collections/community.crypto/issues/39)." diff --git a/plugins/module_utils/crypto/cryptography_support.py b/plugins/module_utils/crypto/cryptography_support.py index 93fb67ce..a527d1c0 100644 --- a/plugins/module_utils/crypto/cryptography_support.py +++ b/plugins/module_utils/crypto/cryptography_support.py @@ -51,6 +51,9 @@ from ._objects import ( from ._obj2txt import obj2txt +DOTTED_OID = re.compile(r'^\d+(?:\.\d+)+$') + + def cryptography_get_extensions_from_cert(cert): # Since cryptography won't give us the DER value for an extension # (that is only stored for unrecognized extensions), we have to re-do @@ -112,6 +115,8 @@ def cryptography_get_extensions_from_csr(csr): def cryptography_name_to_oid(name): dotted = OID_LOOKUP.get(name) if dotted is None: + if DOTTED_OID.match(name): + return x509.oid.ObjectIdentifier(name) raise OpenSSLObjectError('Cannot find OID for "{0}"'.format(name)) return x509.oid.ObjectIdentifier(dotted) @@ -119,7 +124,12 @@ def cryptography_name_to_oid(name): def cryptography_oid_to_name(oid, short=False): dotted_string = oid.dotted_string names = OID_MAP.get(dotted_string) - name = names[0] if names else oid._name + if names: + name = names[0] + else: + name = oid._name + if name == 'Unknown OID': + name = dotted_string if short: return NORMALIZE_NAMES_SHORT.get(name, name) else: diff --git a/tests/integration/targets/openssl_csr/tasks/impl.yml b/tests/integration/targets/openssl_csr/tasks/impl.yml index aa6f9c0c..ccecfefb 100644 --- a/tests/integration/targets/openssl_csr/tasks/impl.yml +++ b/tests/integration/targets/openssl_csr/tasks/impl.yml @@ -550,19 +550,7 @@ - Encipher Only - decipherOnly key_usage_critical: yes - extended_key_usage: - - serverAuth # the same as "TLS Web Server Authentication" - - TLS Web Server Authentication - - TLS Web Client Authentication - - Code Signing - - E-mail Protection - - timeStamping - - OCSPSigning - - Any Extended Key Usage - - qcStatements - - DVCS - - IPSec User - - biometricInfo + extended_key_usage: '{{ value_for_extended_key_usage if select_crypto_backend != "pyopenssl" else value_for_extended_key_usage_pyopenssl }}' subject_alt_name: '{{ value_for_san if select_crypto_backend != "pyopenssl" else value_for_san_pyopenssl }}' basic_constraints: - "CA:TRUE" @@ -575,6 +563,33 @@ authority_cert_serial_number: '{{ 12345 if select_crypto_backend != "pyopenssl" else omit }}' select_crypto_backend: '{{ select_crypto_backend }}' vars: + value_for_extended_key_usage_pyopenssl: + - serverAuth # the same as "TLS Web Server Authentication" + - TLS Web Server Authentication + - TLS Web Client Authentication + - Code Signing + - E-mail Protection + - timeStamping + - OCSPSigning + - Any Extended Key Usage + - qcStatements + - DVCS + - IPSec User + - biometricInfo + value_for_extended_key_usage: + - serverAuth # the same as "TLS Web Server Authentication" + - TLS Web Server Authentication + - TLS Web Client Authentication + - Code Signing + - E-mail Protection + - timeStamping + - OCSPSigning + - Any Extended Key Usage + - qcStatements + - DVCS + - IPSec User + - biometricInfo + - 1.2.3.4.5.6 value_for_authority_cert_issuer: - "DNS:ca.example.org" - "IP:1.2.3.4" @@ -631,19 +646,7 @@ - Encipher Only - decipherOnly key_usage_critical: yes - extended_key_usage: - - serverAuth # the same as "TLS Web Server Authentication" - - TLS Web Server Authentication - - TLS Web Client Authentication - - Code Signing - - E-mail Protection - - timeStamping - - OCSPSigning - - Any Extended Key Usage - - qcStatements - - DVCS - - IPSec User - - biometricInfo + extended_key_usage: '{{ value_for_extended_key_usage if select_crypto_backend != "pyopenssl" else value_for_extended_key_usage_pyopenssl }}' subject_alt_name: '{{ value_for_san if select_crypto_backend != "pyopenssl" else value_for_san_pyopenssl }}' basic_constraints: - "CA:TRUE" @@ -656,6 +659,33 @@ authority_cert_serial_number: '{{ 12345 if select_crypto_backend != "pyopenssl" else omit }}' select_crypto_backend: '{{ select_crypto_backend }}' vars: + value_for_extended_key_usage_pyopenssl: + - serverAuth # the same as "TLS Web Server Authentication" + - TLS Web Server Authentication + - TLS Web Client Authentication + - Code Signing + - E-mail Protection + - timeStamping + - OCSPSigning + - Any Extended Key Usage + - qcStatements + - DVCS + - IPSec User + - biometricInfo + value_for_extended_key_usage: + - serverAuth # the same as "TLS Web Server Authentication" + - TLS Web Server Authentication + - TLS Web Client Authentication + - Code Signing + - E-mail Protection + - timeStamping + - OCSPSigning + - Any Extended Key Usage + - qcStatements + - DVCS + - IPSec User + - biometricInfo + - 1.2.3.4.5.6 value_for_authority_cert_issuer: - "DNS:ca.example.org" - "IP:1.2.3.4" @@ -713,19 +743,7 @@ - Encipher Only - decipherOnly key_usage_critical: yes - extended_key_usage: - - serverAuth # the same as "TLS Web Server Authentication" - - TLS Web Server Authentication - - TLS Web Client Authentication - - Code Signing - - E-mail Protection - - timeStamping - - OCSPSigning - - Any Extended Key Usage - - qcStatements - - DVCS - - IPSec User - - biometricInfo + extended_key_usage: '{{ value_for_extended_key_usage if select_crypto_backend != "pyopenssl" else value_for_extended_key_usage_pyopenssl }}' subject_alt_name: '{{ value_for_san if select_crypto_backend != "pyopenssl" else value_for_san_pyopenssl }}' basic_constraints: - "CA:TRUE" @@ -738,6 +756,33 @@ authority_cert_serial_number: '{{ 12345 if select_crypto_backend != "pyopenssl" else omit }}' select_crypto_backend: '{{ select_crypto_backend }}' vars: + value_for_extended_key_usage_pyopenssl: + - serverAuth # the same as "TLS Web Server Authentication" + - TLS Web Server Authentication + - TLS Web Client Authentication + - Code Signing + - E-mail Protection + - timeStamping + - OCSPSigning + - Any Extended Key Usage + - qcStatements + - DVCS + - IPSec User + - biometricInfo + value_for_extended_key_usage: + - serverAuth # the same as "TLS Web Server Authentication" + - TLS Web Server Authentication + - TLS Web Client Authentication + - Code Signing + - E-mail Protection + - timeStamping + - OCSPSigning + - Any Extended Key Usage + - qcStatements + - DVCS + - IPSec User + - biometricInfo + - 1.2.3.4.5.6 value_for_authority_cert_issuer: - "DNS:ca.example.org" - "IP:1.2.3.4" diff --git a/tests/integration/targets/openssl_csr/tests/validate.yml b/tests/integration/targets/openssl_csr/tests/validate.yml index dbbd07ae..b5de7f0f 100644 --- a/tests/integration/targets/openssl_csr/tests/validate.yml +++ b/tests/integration/targets/openssl_csr/tests/validate.yml @@ -189,20 +189,6 @@ "pathlen:23", ] - everything_info.basic_constraints_critical == true - - everything_info.extended_key_usage == [ - "Any Extended Key Usage", - "Biometric Info", - "Code Signing", - "E-mail Protection", - "IPSec User", - "OCSP Signing", - "TLS Web Client Authentication", - "TLS Web Server Authentication", - "TLS Web Server Authentication", - "Time Stamping", - "dvcs", - "qcStatements", - ] - everything_info.extended_key_usage_critical == false - everything_info.key_usage == [ "CRL Sign", @@ -249,6 +235,20 @@ "URI:https://example.org/test/index.html", "RID:1.2.3.4", ] + - everything_info.extended_key_usage == [ + "Any Extended Key Usage", + "Biometric Info", + "Code Signing", + "E-mail Protection", + "IPSec User", + "OCSP Signing", + "TLS Web Client Authentication", + "TLS Web Server Authentication", + "TLS Web Server Authentication", + "Time Stamping", + "dvcs", + "qcStatements", + ] when: select_crypto_backend == 'pyopenssl' - name: Check CSR with everything (non-pyOpenSSL specific) @@ -273,6 +273,21 @@ "dirName:/O=Example Com/CN=example.com" ] - everything_info.subject_key_identifier == "00:11:22:33" + - everything_info.extended_key_usage == [ + "1.2.3.4.5.6", + "Any Extended Key Usage", + "Biometric Info", + "Code Signing", + "E-mail Protection", + "IPSec User", + "OCSP Signing", + "TLS Web Client Authentication", + "TLS Web Server Authentication", + "TLS Web Server Authentication", + "Time Stamping", + "dvcs", + "qcStatements", + ] when: select_crypto_backend != 'pyopenssl' - name: Verify Ed25519 and Ed448 tests (for cryptography >= 2.6, < 2.8)