From: Christoph Egger Date: Sat, 6 Feb 2016 21:41:07 +0000 (+0100) Subject: Move new tls tools to subdirectory X-Git-Url: https://git.siccegge.de//index.cgi?p=tools.git;a=commitdiff_plain;h=76db1f37cc1815129a14e0205518f9cff133d7be Move new tls tools to subdirectory --- diff --git a/addrecord b/addrecord deleted file mode 100644 index fa4c840..0000000 --- a/addrecord +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/python3 -# -# ssh-based server to allow hosts to update their own TLS-related RRs -# intended to be used like -# command="/srv/tls/bin/addrecord hepworth.siccegge.de" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIlLx3R+Q5LgBZbJ6USuzam/uAEQITl6vzOn/ylk4fq christoph@mitoraj - -import os -import sys -import re -import datetime -import fcntl - -import yaml - -class Addrecord: - def __init__(self, host): - self._host = host - self._ports = {'www': [443], - 'smtp': [25, 587, 465], - 'imap': [993, 143], - 'pop': [110, 995], - 'xmpp': [5222, 5269], - } - self._tlsa_re = re.compile('TLSA 3 1 1 [0-9a-f]{64}') - self._acme_re = re.compile(r'[a-zA-Z0-9_-]{43}') - with open('inventory.yaml') as inv: - self._inventory = yaml.load(inv) - - - def tlsa(self): - host = input("Hostname: ") - service = input("Service: ") - value = input("Value: ") - if host not in self._inventory[self._host][service]: - sys.stderr.write("Not authorized to update entries for service '%s' on '%s'\n" - % (service, host)) - return 1 - - if re.fullmatch(self._tlsa_re, value) is None: - sys.stderr.write("Not a valid TLSA record: '%s'\n" % value) - return 2 - - records = [] - for port in self._ports[service]: - records.append("{0:<35s}\t{1}\n".format("_%d._tcp.%s" % (port, host), - value)) - self._update_records('tlsa', records) - print("OK") - return 0 - - - def acme(self): - host = input("Hostname: ") - value = input("Value: ") - allowed_hosts = set() - for value in self._inventory[self._host].values(): - allowed_hosts = allowed_hosts.union(value) - - if host not in allowed_hosts: - sys.stderr.write("Not authorized to update entries for host '%s'\n" % host) - return 1 - - if re.fullmatch(self._acme_re, value) is None: - sys.stderr.write("Not a valid ACME challenge record: '%s'\n" % value) - return 2 - - records = [ "{0:<35s}\t{1}\n".format("_acme-challenge.%s" % host, value) ] - self._update_records('acme', records) - print("OK") - return 0 - - - def _update_records(self, sort, records): - to_remove = [ i.split()[0] for i in records ] - - with open('%s/%s.m4' % (sort, self._host), 'r') as oldzone: - fcntl.flock(oldzone, fcntl.LOCK_EX) - lines = oldzone.readlines() - lines = [ line for line in lines if line == '\n' or line.split()[0] not in to_remove ] - - lines.append('\n') - lines.append("; Last updated %s by %s\n" % (datetime.datetime.utcnow().isoformat(), - self._host)) - lines = lines + records - - with open('%s/%s.m4.new' % (sort, self._host), 'w') as newzone: - newtext = ''.join(lines) - newtext = re.sub(r'\n[\n]+', '\n\n', newtext) - newtext = re.sub(r'\n;.*\n\n;', '\n;', newtext) - newzone.write(newtext) - - os.rename('%s/%s.m4.new' % (sort, self._host), - '%s/%s.m4' % (sort, self._host)) - fcntl.flock(oldzone, fcntl.LOCK_UN) - - -def main(): - command = os.environ['SSH_ORIGINAL_COMMAND'] - host = sys.argv[1] - addrecord = Addrecord(host) - - if command == 'acme': - return addrecord.acme() - elif command == 'tlsa': - return addrecord.tlsa() - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/inventory.yaml b/inventory.yaml deleted file mode 100644 index 73e9d73..0000000 --- a/inventory.yaml +++ /dev/null @@ -1,14 +0,0 @@ -example.com: - www: - - www.example.com - - nginx.example.net - smtp: - - mx1.example.com - -example.org: - smtp: - - mx2.example.com - xmpp: - - example.com - - conference.example.com - - example.org \ No newline at end of file diff --git a/tls/addrecord b/tls/addrecord new file mode 100644 index 0000000..fa4c840 --- /dev/null +++ b/tls/addrecord @@ -0,0 +1,109 @@ +#!/usr/bin/python3 +# +# ssh-based server to allow hosts to update their own TLS-related RRs +# intended to be used like +# command="/srv/tls/bin/addrecord hepworth.siccegge.de" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIlLx3R+Q5LgBZbJ6USuzam/uAEQITl6vzOn/ylk4fq christoph@mitoraj + +import os +import sys +import re +import datetime +import fcntl + +import yaml + +class Addrecord: + def __init__(self, host): + self._host = host + self._ports = {'www': [443], + 'smtp': [25, 587, 465], + 'imap': [993, 143], + 'pop': [110, 995], + 'xmpp': [5222, 5269], + } + self._tlsa_re = re.compile('TLSA 3 1 1 [0-9a-f]{64}') + self._acme_re = re.compile(r'[a-zA-Z0-9_-]{43}') + with open('inventory.yaml') as inv: + self._inventory = yaml.load(inv) + + + def tlsa(self): + host = input("Hostname: ") + service = input("Service: ") + value = input("Value: ") + if host not in self._inventory[self._host][service]: + sys.stderr.write("Not authorized to update entries for service '%s' on '%s'\n" + % (service, host)) + return 1 + + if re.fullmatch(self._tlsa_re, value) is None: + sys.stderr.write("Not a valid TLSA record: '%s'\n" % value) + return 2 + + records = [] + for port in self._ports[service]: + records.append("{0:<35s}\t{1}\n".format("_%d._tcp.%s" % (port, host), + value)) + self._update_records('tlsa', records) + print("OK") + return 0 + + + def acme(self): + host = input("Hostname: ") + value = input("Value: ") + allowed_hosts = set() + for value in self._inventory[self._host].values(): + allowed_hosts = allowed_hosts.union(value) + + if host not in allowed_hosts: + sys.stderr.write("Not authorized to update entries for host '%s'\n" % host) + return 1 + + if re.fullmatch(self._acme_re, value) is None: + sys.stderr.write("Not a valid ACME challenge record: '%s'\n" % value) + return 2 + + records = [ "{0:<35s}\t{1}\n".format("_acme-challenge.%s" % host, value) ] + self._update_records('acme', records) + print("OK") + return 0 + + + def _update_records(self, sort, records): + to_remove = [ i.split()[0] for i in records ] + + with open('%s/%s.m4' % (sort, self._host), 'r') as oldzone: + fcntl.flock(oldzone, fcntl.LOCK_EX) + lines = oldzone.readlines() + lines = [ line for line in lines if line == '\n' or line.split()[0] not in to_remove ] + + lines.append('\n') + lines.append("; Last updated %s by %s\n" % (datetime.datetime.utcnow().isoformat(), + self._host)) + lines = lines + records + + with open('%s/%s.m4.new' % (sort, self._host), 'w') as newzone: + newtext = ''.join(lines) + newtext = re.sub(r'\n[\n]+', '\n\n', newtext) + newtext = re.sub(r'\n;.*\n\n;', '\n;', newtext) + newzone.write(newtext) + + os.rename('%s/%s.m4.new' % (sort, self._host), + '%s/%s.m4' % (sort, self._host)) + fcntl.flock(oldzone, fcntl.LOCK_UN) + + +def main(): + command = os.environ['SSH_ORIGINAL_COMMAND'] + host = sys.argv[1] + addrecord = Addrecord(host) + + if command == 'acme': + return addrecord.acme() + elif command == 'tlsa': + return addrecord.tlsa() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tls/inventory.yaml b/tls/inventory.yaml new file mode 100644 index 0000000..73e9d73 --- /dev/null +++ b/tls/inventory.yaml @@ -0,0 +1,14 @@ +example.com: + www: + - www.example.com + - nginx.example.net + smtp: + - mx1.example.com + +example.org: + smtp: + - mx2.example.com + xmpp: + - example.com + - conference.example.com + - example.org \ No newline at end of file