From 028facdfed234ff089425c916d38b5a1fbd12dd0 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 13 Mar 2019 10:15:57 +0100 Subject: [PATCH] acme_challenge_cert_helper: add support for IP identifiers (#53661) * Add IP address identifier support to acme_challenge_cert_helper. * Add changelog. * type -> identifier_type. --- ...e_challenge_cert_helper-ip-identifiers.yml | 2 ++ .../crypto/acme/acme_challenge_cert_helper.py | 35 +++++++++++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 changelogs/fragments/53661-acme_challenge_cert_helper-ip-identifiers.yml diff --git a/changelogs/fragments/53661-acme_challenge_cert_helper-ip-identifiers.yml b/changelogs/fragments/53661-acme_challenge_cert_helper-ip-identifiers.yml new file mode 100644 index 0000000000..7c2bc34950 --- /dev/null +++ b/changelogs/fragments/53661-acme_challenge_cert_helper-ip-identifiers.yml @@ -0,0 +1,2 @@ +minor_changes: +- "acme_challenge_cert_helper - add support for IP address identifiers." diff --git a/lib/ansible/modules/crypto/acme/acme_challenge_cert_helper.py b/lib/ansible/modules/crypto/acme/acme_challenge_cert_helper.py index ca10a01fb3..6c39e9ce2c 100644 --- a/lib/ansible/modules/crypto/acme/acme_challenge_cert_helper.py +++ b/lib/ansible/modules/crypto/acme/acme_challenge_cert_helper.py @@ -106,9 +106,24 @@ EXAMPLES = ''' RETURN = ''' domain: description: - - "The domain the challenge is for." + - "The domain the challenge is for. The certificate should be provided if + this is specified in the request's the C(Host) header." returned: always type: str +identifier_type: + description: + - "The identifier type for the actual resource identifier. Will be C(dns) + or C(ip)." + returned: always + type: str + version_added: "2.8" +identifier: + description: + - "The identifier for the actual resource. Will be a domain name if the + type is C(dns), or an IP address if the type is C(ip)." + returned: always + type: str + version_added: "2.8" challenge_certificate: description: - "The challenge certificate in PEM format." @@ -149,6 +164,7 @@ try: import cryptography.hazmat.primitives.asymmetric.utils import cryptography.x509 import cryptography.x509.oid + import ipaddress from distutils.version import LooseVersion HAS_CRYPTOGRAPHY = (LooseVersion(cryptography.__version__) >= LooseVersion('1.3')) _cryptography_backend = cryptography.hazmat.backends.default_backend() @@ -206,11 +222,16 @@ def main(): # Some common attributes domain = to_text(challenge_data['resource']) - subject = issuer = cryptography.x509.Name([ - cryptography.x509.NameAttribute(cryptography.x509.oid.NameOID.COMMON_NAME, domain), - ]) + identifier_type, identifier = to_text(challenge_data.get('resource_original', 'dns:' + challenge_data['resource'])).split(':', 1) + subject = issuer = cryptography.x509.Name([]) not_valid_before = datetime.datetime.utcnow() not_valid_after = datetime.datetime.utcnow() + datetime.timedelta(days=10) + if identifier_type == 'dns': + san = cryptography.x509.DNSName(identifier) + elif identifier_type == 'ip': + san = cryptography.x509.IPAddress(ipaddress.ip_address(identifier)) + else: + raise ModuleFailException('Unsupported identifier type "{0}"'.format(identifier_type)) # Generate regular self-signed certificate regular_certificate = cryptography.x509.CertificateBuilder().subject_name( @@ -226,7 +247,7 @@ def main(): ).not_valid_after( not_valid_after ).add_extension( - cryptography.x509.SubjectAlternativeName([cryptography.x509.DNSName(domain)]), + cryptography.x509.SubjectAlternativeName([san]), critical=False, ).sign( private_key, @@ -250,7 +271,7 @@ def main(): ).not_valid_after( not_valid_after ).add_extension( - cryptography.x509.SubjectAlternativeName([cryptography.x509.DNSName(domain)]), + cryptography.x509.SubjectAlternativeName([san]), critical=False, ).add_extension( cryptography.x509.UnrecognizedExtension( @@ -267,6 +288,8 @@ def main(): module.exit_json( changed=True, domain=domain, + identifier_type=identifier_type, + identifier=identifier, challenge_certificate=challenge_certificate.public_bytes(cryptography.hazmat.primitives.serialization.Encoding.PEM), regular_certificate=regular_certificate.public_bytes(cryptography.hazmat.primitives.serialization.Encoding.PEM) )