From 46372a0f2288190a08ddcc9c8d1574a3cadcef91 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 8 Jun 2024 16:35:44 +0200 Subject: [PATCH] dns+certs: add a new cert_alternate_names hook + improve custom_dns_rules hook --- src/certificate.py | 71 ++++++++++++++++++---------------------------- src/dns.py | 11 ++----- 2 files changed, 29 insertions(+), 53 deletions(-) diff --git a/src/certificate.py b/src/certificate.py index 155803674..ff6f44931 100644 --- a/src/certificate.py +++ b/src/certificate.py @@ -556,6 +556,7 @@ def _fetch_and_enable_new_certificate(domain, no_checks=False): def _prepare_certificate_signing_request(domain, key_file, output_folder): from OpenSSL import crypto # lazy loading this module for performance reasons + from yunohost.hook import hook_callback # Init a request csr = crypto.X509Req() @@ -563,52 +564,34 @@ def _prepare_certificate_signing_request(domain, key_file, output_folder): # Set the domain csr.get_subject().CN = domain - from yunohost.domain import domain_config_get + sanlist = [] + hook_results = hook_callback("cert_alternate_names", env={"domain": domain}) + for hook_name, results in hook_results.items(): + # + # There can be multiple results per hook name, so results look like + # {'/some/path/to/hook1': + # { 'state': 'succeed', + # 'stdreturn': ["foo", "bar"] + # }, + # '/some/path/to/hook2': + # { ... }, + # [...] + # + # Loop over the sub-results + for result in results.values(): + if results["stdreturn"]: + sanlist += results["stdreturn"] - # If XMPP is enabled for this domain, add xmpp-upload and muc subdomains - # in subject alternate names - if domain_config_get(domain, key="feature.xmpp.xmpp") == 1: - xmpp_records = ( - Diagnoser.get_cached_report( - "dnsrecords", item={"domain": domain, "category": "xmpp"} - ).get("data") - or {} - ) - sanlist = [] - - # Handle the boring case where the domain is not the root of the dns zone etc... - from yunohost.dns import ( - _get_relative_name_for_dns_zone, - _get_dns_zone_for_domain, - ) - - base_dns_zone = _get_dns_zone_for_domain(domain) - basename = _get_relative_name_for_dns_zone(domain, base_dns_zone) - suffix = f".{basename}" if basename != "@" else "" - - for sub in ("xmpp-upload", "muc"): - subdomain = sub + "." + domain - if xmpp_records.get("CNAME:" + sub + suffix) == "OK": - sanlist.append(("DNS:" + subdomain)) - else: - logger.warning( - m18n.n( - "certmanager_warning_subdomain_dns_record", - subdomain=subdomain, - domain=domain, - ) + if sanlist: + csr.add_extensions( + [ + crypto.X509Extension( + b"subjectAltName", + False, + (", ".join(["DNS:{sub}.{domain}" for sub in sanlist])).encode("utf-8"), ) - - if sanlist: - csr.add_extensions( - [ - crypto.X509Extension( - b"subjectAltName", - False, - (", ".join(sanlist)).encode("utf-8"), - ) - ] - ) + ] + ) # Set the key with open(key_file, "rt") as f: diff --git a/src/dns.py b/src/dns.py index 1bba97bdd..c5bd4c69d 100644 --- a/src/dns.py +++ b/src/dns.py @@ -235,15 +235,8 @@ def _build_dns_conf(base_domain, include_empty_AAAA_if_no_ipv6=False): # Custom records # ################## - # Defined by custom hooks ships in apps for example ... - - # FIXME : this ain't practical for apps that may want to add - # custom dns records for a subdomain ... there's no easy way for - # an app to compare the base domain is the parent of the subdomain ? - # (On the other hand, in sep 2021, it looks like no app is using - # this mechanism...) - - hook_results = hook_callback("custom_dns_rules", args=[base_domain]) + # Defined by custom hooks shipped in apps for example ... + hook_results = hook_callback("custom_dns_rules", env={"base_domain": base_domain, "suffix": suffix}) for hook_name, results in hook_results.items(): # # There can be multiple results per hook name, so results look like