#!/usr/bin/env python3 # SPDX-FileCopyrightText: 2026 Matthew Fennell # # SPDX-License-Identifier: AGPL-3.0-or-later import urllib.parse # We ultimately want the variables to be specified in the double-brace format # recognised by ansible. However, we don't want those double braces or spaces # to be encoded, so search for the placeholders ENVSUFFIX and DANEHASH from the # original selects to replace them after encoding is complete. def template_url(selects): url = "&".join( map(lambda select: urllib.parse.urlencode({"select": select}), selects) ) url = "https://api.mythic-beasts.com/dns/v2/zones/{{ domain }}/records?" + url url = url.replace("ENVSUFFIX", "{{ env_suffix }}") url = url.replace("DANEHASH", "{{ dane_hash }}") return url # These select queries specify the records that will be replaced whenever we # PUT new records to the endpoint. # For most records, we only specify the host and type. For instance, # host=chat&type=A will select any A record on the chat subdomain for # replacement. # For TLSA records, we additionally specify the data (which for these records # is the hash of the cert). # This is crucial to rollover new certs properly: when requesting a new cert # with a different TLSA hash, we have to first add the new TLSA record, wait # for propagation, only then update the cert, and finally delete the old # record. While waiting for propagation, both the old and new TLSA records need # to be present. # Therefore, specifying the data prevents us from replacing the TLSA hash of # the existing cert if we run the playbook while waiting for propagation. It # simply ensures that a TLSA record with this hash exists, and leaves any # others alone for manual cleanup. common_selects = [ "host=chatENVSUFFIX&type=A", "host=chatENVSUFFIX&type=AAAA", "host=conferenceENVSUFFIX&type=CNAME", "host=uploadENVSUFFIX&type=CNAME", "host=_xmpp-client._tcpENVSUFFIX&type=SRV", "host=_xmpps-client._tcpENVSUFFIX&type=SRV", "host=_5222._tcp.chatENVSUFFIX&type=TLSA&data=DANEHASH", "host=_5223._tcp.chatENVSUFFIX&type=TLSA&data=DANEHASH", ] non_transport_selects = [ "host=_xmpp-server._tcpENVSUFFIX&type=SRV", "host=_xmpps-server._tcpENVSUFFIX&type=SRV", "host=_xmpps-server._tcp.conferenceENVSUFFIX&type=SRV", "host=_xmpps-server._tcp.uploadENVSUFFIX&type=SRV", "host=_5269._tcp.chatENVSUFFIX&type=TLSA&data=DANEHASH", "host=_5270._tcp.chatENVSUFFIX&type=TLSA&data=DANEHASH", ] common_url = template_url(common_selects) non_transport_url = template_url(non_transport_selects) print(common_url) print(non_transport_url)