diff --git a/main.py b/main.py index 06062e2..af58ecc 100755 --- a/main.py +++ b/main.py @@ -10,7 +10,7 @@ import sys import os -path =(os.path.dirname(os.path.abspath(__file__))) +path = os.path.dirname(os.path.abspath(__file__)) config = ConfigParser() config.read(path+'/config.ini') @@ -18,14 +18,17 @@ api_hostname = config.get('Re2o', 'hostname') api_password = config.get('Re2o', 'password') api_username = config.get('Re2o', 'username') -template_soa = ("$ORIGIN {zone}.\n" - "@ IN SOA {ns}. {mail} (\n" - " {serial} ; serial\n" - " {refresh} ; refresh\n" - " {retry} ; retry\n" - " {expire} ; expire\n" - " {ttl} ; ttl\n" - ")") +template_soa = ( + "$ORIGIN {zone}.\n" + "@ IN SOA {ns}. {mail} (\n" + " {serial} ; serial\n" + " {refresh} ; refresh\n" + " {retry} ; retry\n" + " {expire} ; expire\n" + " {ttl} ; ttl\n" + ")" +) + template_originv4 = "@ IN A {ipv4}" template_originv6 = "@ IN AAAA {ipv6}" template_ns = "@ IN NS {target}." @@ -38,56 +41,49 @@ template_cname = "{hostname} IN CNAME {alias}." template_ptr = "{target} IN PTR {hostname}." template_sshfp = "{hostname} SSHFP {algo} {type} {fp}" -template_zone = ("$TTL 2D\n" - "{soa}\n" - "\n" - "{originv4}\n" - "{originv6}\n" - "\n" - "{ns_records}\n" - "\n" - "{fp_records}\n" - "\n" - "{ns_records}\n" - "{mx_records}\n" - "\n" - "{txt_records}\n" - "\n" - "{srv_records}\n" - "\n" - "{a_records}\n" - "\n" - "{aaaa_records}\n" - "\n" - "{cname_records}") +template_zone = ( + "$TTL 2D\n" + "{soa}\n" + "\n" + "{originv4}\n" + "{originv6}\n" + "\n" + "{ns_records}\n" + "\n" + "{fp_records}\n" + "\n" + "{ns_records}\n" + "{mx_records}\n" + "\n" + "{txt_records}\n" + "\n" + "{srv_records}\n" + "\n" + "{a_records}\n" + "\n" + "{aaaa_records}\n" + "\n" + "{cname_records}" +) -template_reverse = ("$TTL 2D\n" - "{soa}\n" - "\n" - "{ns_records}\n" - "\n" - "{mx_records}\n" - "\n" - "{ptr_records}\n") +template_reverse = ( + "$TTL 2D\n" + "{soa}\n" + "\n" + "{ns_records}\n" + "\n" + "{mx_records}\n" + "\n" + "{ptr_records}\n" +) - - -def write_dns_files(api_client): - dns_zones = api_client.list("dns/zones") - zone_names = {zone['name'][1:] for zone in dns_zones} - records_to_add = {name: {'a': [], 'aaaa': [], 'cname': []} for name in zone_names} - - def add_record(zone, record, type): - nonlocal records_to_add - records_to_add[zone][type].append(record) - return False - - for zone in sorted(dns_zones, key=lambda zone:zone['name'].count('.')): +def write_dns_files(api_client, processes): + for zone in api_client.list("dns/zones"): zone_name = zone['name'][1:] now = datetime.datetime.now(datetime.timezone.utc) serial = now.strftime("%Y%m%d") + str(int(100*(now.hour*3600 + now.minute*60 + now.second)/86400)) - + soa_mail_fields = zone['soa']['mail'].split('@') soa_mail = "{}.{}.".format(soa_mail_fields[0].replace('.', '\\.'), soa_mail_fields[1]) @@ -95,105 +91,129 @@ def write_dns_files(api_client): ns = zone['ns_records'][0]['target'] else: ns = "ns."+zone_name+"." - soa = template_soa.format(zone=zone_name, - mail=soa_mail, - serial=serial, - ns=ns, - refresh=zone['soa']['refresh'], - retry=zone['soa']['retry'], - expire=zone['soa']['expire'], - ttl=zone['soa']['ttl']) - + + soa = template_soa.format( + zone=zone_name, + mail=soa_mail, + serial=serial, + ns=ns, + refresh=zone['soa']['refresh'], + retry=zone['soa']['retry'], + expire=zone['soa']['expire'], + ttl=zone['soa']['ttl'] + ) + if zone['originv4'] is not None: originv4 = template_originv4.format(ipv4=zone['originv4']['ipv4']) else: - originv4 = "" + originv4 = "" if zone['originv6'] is not None: originv6 = template_originv6.format(ipv6=zone['originv6']) else: originv6 = "" - + ns_records = "\n".join( template_ns.format(target=x['target']) for x in zone['ns_records'] ) fp_records = "\n".join( - template_sshfp.format(hostname=host['hostname'], algo=fp['algo_id'], type="1", fp=fp['hash']['1'] ) + template_sshfp.format( + hostname=host['hostname'], + algo=fp['algo_id'], + type="1", + fp=fp['hash']['1'] + ) + "\n" + - template_sshfp.format(hostname=host['hostname'], algo=fp['algo_id'], type="2", fp=fp['hash']['2'] ) + template_sshfp.format( + hostname=host['hostname'], + algo=fp['algo_id'], + type="2", + fp=fp['hash']['2'] + ) for host in zone['sshfp_records'] for fp in host['sshfp'] ) - - + mx_records = "\n".join( - template_mx.format(priority=x['priority'], - target=x['target']) + template_mx.format( + priority=x['priority'], + target=x['target'] + ) for x in zone['mx_records'] ) - + txt_records = "\n".join( - template_txt.format(field1=x['field1'], - field2=x['field2']) + template_txt.format( + field1=x['field1'], + field2=x['field2'] + ) for x in zone['txt_records'] ) - + srv_records = "\n".join( - template_srv.format(service=x['service'], - protocol=x['protocol'], - zone=zone_name, - ttl=x['ttl'], - priority=x['priority'], - weight=x['weight'], - port=x['port'], - target=x['target']) + template_srv.format( + service=x['service'], + protocol=x['protocol'], + zone=zone_name, + ttl=x['ttl'], + priority=x['priority'], + weight=x['weight'], + port=x['port'], + target=x['target'] + ) for x in zone['srv_records'] ) a_records = "\n".join( - template_a.format(hostname=x['hostname'], - ipv4=x['ipv4']) + template_a.format( + hostname=x['hostname'], + ipv4=x['ipv4'] + ) for x in zone['a_records'] - if (True if x['hostname'] + '.' + zone_name not in zone_names else add_record(x['hostname'] + '.' + zone_name, template_a.format(hostname='@', ipv4=ip['ipv4']), 'a')) ) aaaa_records = "\n".join( - template_aaaa.format(hostname=x['hostname'], - ipv6=ip['ipv6']) - for x in zone['aaaa_records'] + template_aaaa.format( + hostname=x['hostname'], + ipv6=ip['ipv6'] + ) + for x in zone['aaaa_records'] for ip in x['ipv6'] if x['ipv6'] is not None - and (True if x['hostname'] + '.' + zone_name not in zone_names else add_record(x['hostname'] + '.' + zone_name, template_aaaa.format(hostname='@', ipv6=ip['ipv6']), 'aaaa')) ) - + + aaaa_records = "\n".join( + template_aaaa.format( + hostname=x['hostname'], + ipv6=ip['ipv6'] + ) + for x in zone['aaaa_records'] + for ip in x['ipv6'] + if x['ipv6'] is not None + ) + cname_records = "\n".join( - template_cname.format(hostname=x['hostname'], - alias=x['alias']) + template_cname.format( + hostname=x['hostname'], + alias=x['alias'] + ) for x in zone['cname_records'] - if (True if x['hostname'] + '.' + zone_name not in zone_names else add_record(x['hostname'] + '.' + zone_name, template_cname.format(hostname='@', alias=x['alias']), 'cname')) ) - if records_to_add[zone_name]['a']: - a_records += "\n" + "\n".join(records_to_add[zone_name]['a']) - - if records_to_add[zone_name]['aaaa']: - aaaa_records += "\n" + "\n".join(records_to_add[zone_name]['aaaa']) - - if records_to_add[zone_name]['cname']: - cname_records += "\n" + "\n".join(records_to_add[zone_name]['cname']) - - zone_file_content = template_zone.format(soa=soa, - originv4=originv4, - originv6=originv6, - ns_records=ns_records, - fp_records=fp_records, - mx_records=mx_records, - txt_records=txt_records, - srv_records=srv_records, - a_records=a_records, - aaaa_records=aaaa_records, - cname_records=cname_records) + zone_file_content = template_zone.format( + soa=soa, + originv4=originv4, + originv6=originv6, + ns_records=ns_records, + fp_records=fp_records, + mx_records=mx_records, + txt_records=txt_records, + srv_records=srv_records, + a_records=a_records, + aaaa_records=aaaa_records, + cname_records=cname_records + ) filename = path+'/generated/dns.{zone}.zone'.format(zone=zone_name) with open(filename, 'w+') as f: @@ -206,7 +226,6 @@ def get_ip_reverse(ip, prefix_length): return '.'.join(ip.reverse_dns.split('.')[:prefix_length]) - def write_dns_reverse_file(api_client): """ Generate the reverve file for each reverse zone (= IpType) For each IpType, we generate both an Ipv4 reverse and a v6. @@ -237,12 +256,13 @@ def write_dns_reverse_file(api_client): ) mx_records = "\n".join( - template_mx.format(priority=x['priority'], - target=x['target']) + template_mx.format( + priority=x['priority'], + target=x['target'] + ) for x in zone['mx_records'] ) - ### We start with the v4 # We setup the network from the cidrs of the IpType @@ -275,46 +295,54 @@ def write_dns_reverse_file(api_client): elif subnet.prefixlen == 24: zone_name,prefix_length = ('.'.join(rev_dns_a[1:]), 1) - soa = template_soa.format(zone=zone_name, - mail=soa_mail, - serial=serial, - ns=ns, - refresh=zone['soa']['refresh'], - retry=zone['soa']['retry'], - expire=zone['soa']['expire'], - ttl=zone['soa']['ttl']) + soa = template_soa.format( + zone=zone_name, + mail=soa_mail, + serial=serial, + ns=ns, + refresh=zone['soa']['refresh'], + retry=zone['soa']['retry'], + expire=zone['soa']['expire'], + ttl=zone['soa']['ttl'] + ) + ptr_records = "\n".join( - template_ptr.format(hostname=host['hostname']+extension, - target=get_ip_reverse(host['ipv4'],prefix_length)) - for host in zone['ptr_records'] if host['ipv4'] in subnet + template_ptr.format( + hostname=host['hostname']+extension, + target=get_ip_reverse(host['ipv4'],prefix_length) ) - zone_file_content = template_reverse.format(soa=soa, - ns_records=ns_records, - mx_records=mx_records, - ptr_records = ptr_records) + for host in zone['ptr_records'] if host['ipv4'] in subnet + ) + zone_file_content = template_reverse.format( + soa=soa, + ns_records=ns_records, + mx_records=mx_records, + ptr_records = ptr_records + ) filename = path+'/generated/dns.{zone}.zone'.format(zone=zone_name) with open(filename, 'w+') as f: f.write(zone_file_content) - ### Continue with the ipv6 reverse if zone['ptr_v6_records']: net = netaddr.IPNetwork(zone['prefix_v6']+"/"+str(zone['prefix_v6_length'])) net_class = max(((net.prefixlen - 1) // 4) + 1, 1) zone6_name = ".".join( - netaddr.IPAddress(net.first).reverse_dns.split('.')[32 - net_class:] - )[:-1] + netaddr.IPAddress(net.first).reverse_dns.split('.')[32 - net_class:] + )[:-1] - soa = template_soa.format(zone=zone6_name, - mail=soa_mail, - serial=serial, - ns=ns, - refresh=zone['soa']['refresh'], - retry=zone['soa']['retry'], - expire=zone['soa']['expire'], - ttl=zone['soa']['ttl']) + soa = template_soa.format( + zone=zone6_name, + mail=soa_mail, + serial=serial, + ns=ns, + refresh=zone['soa']['refresh'], + retry=zone['soa']['retry'], + expire=zone['soa']['expire'], + ttl=zone['soa']['ttl'] + ) prefix_length = int((128 - net.prefixlen)/4) ptr_records = "\n".join( @@ -324,22 +352,24 @@ def write_dns_reverse_file(api_client): ) if zone6_name in zone_v6: # we already created the file, we ignore the soa - zone_file_content = template_reverse.format(soa="", - ns_records=ns_records, - mx_records=mx_records, - ptr_records = ptr_records) - + zone_file_content = template_reverse.format( + soa="", + ns_records=ns_records, + mx_records=mx_records, + ptr_records = ptr_records + ) filename = path+'/generated/dns.{zone}.zone'.format(zone=zone6_name) with open(filename, 'a') as f: f.write(zone_file_content) else: # we create the file from scratch - zone_file_content = template_reverse.format(soa=soa, - ns_records=ns_records, - mx_records=mx_records, - ptr_records = ptr_records) - + zone_file_content = template_reverse.format( + soa=soa, + ns_records=ns_records, + mx_records=mx_records, + ptr_records = ptr_records + ) filename = path+'/generated/dns.{zone}.zone'.format(zone=zone6_name) with open(filename, 'w+') as f: