def add_3597(zd): zd.set("finalizer_script", "ldns-3597") zd.add("finalizer_params", "-i") zd.add("finalizer_params", "signed/" + dnsutil.ufqdn(zd.get("name"))) zd.add("finalizer_params", "-o") zd.add("finalizer_params", "final/" + dnsutil.ufqdn(zd.get("name"))) for t in T3597.split(" "): zd.add("finalizer_params", t)
def generate_static_zone_entries(): zds = [] zd = zonedata.ZoneData() zd.set("name", "types." + env.DOMAIN) add_3597(zd) set_servers(zd) zds.append(zd) # this one is based on the previous one so it isn't done through # auto/ zd = zonedata.ZoneData() dname = "types-signed." + env.DOMAIN zd.set("name", dname) dnsutil.add_standard_sign_options(zd) add_3597(zd) set_servers(zd) zds.append(zd) # Apex cname works with powerdns only (we load it with zone2sql in an sqlite3 backend to make it work) # TODO: is this still the case? zd = zonedata.ZoneData() dname = "apexcname." + env.DOMAIN zd.set("name", dname) zd.add("primary_names", "powerdns") dnsutil.add_standard_sign_options(zd) zds.append(zd) zd = zonedata.ZoneData() dname = "wildcards-nsec3." + env.DOMAIN zd.set("name", dname) add_nsec3_sign_options(zd) set_servers(zd) zds.append(zd) zd = zonedata.ZoneData() dname = "nsec3-opt-out." + env.DOMAIN zd.set("name", dname) add_nsec3_opt_out_sign_options(zd) zd.set("finalizer_script", "../ext/concat.sh") zd.add("finalizer_params", "final/" + dnsutil.ufqdn(zd.get("name"))) zd.add("finalizer_params", "signed/" + dnsutil.ufqdn(zd.get("name"))) zd.add( "finalizer_params", "../input/static_zones/" + dnsutil.ufqdn(zd.get("name")) + ".opt-out") set_servers(zd) zds.append(zd) # Create an entry for each file in auto for af in list_files(): autofiles = list_files() zd = zonedata.ZoneData() zd.set("name", af[0]) dnsutil.add_standard_sign_options(zd) zds.append(zd) zonedata.write_zone_data(env.ZONE_DB_PATH + "/static_zones.db", zds)
def finalize_or_sign_zones(regen_all): all_zones = dnsutil.read_all_db_files() os.makedirs(OUTPUT_DIR, exist_ok=True) for z in all_zones: needed_files = [ INPUT_DIR + "/" + dnsutil.ufqdn(z.get("name")) ] output_file = OUTPUT_DIR + "/" + dnsutil.ufqdn(z.get("name")) if filestamps.file_updated(needed_files, output_file): print("[finalizer] Creating zone " + z.get("name")) finalize_or_sign_zone(z)
def copy_or_sign_zones(regen_all): all_zones = dnsutil.read_all_db_files() os.makedirs(OUTPUT_DIR, exist_ok=True) # needed info: zone file name, zone origin, signer commands #print([str(zd) for zd in all_zones]) for z in all_zones: needed_files = [INPUT_DIR + "/" + dnsutil.ufqdn(z.get("name"))] output_file = OUTPUT_DIR + "/" + dnsutil.ufqdn(z.get("name")) if len(z.get("signer_keys")) > 0: needed_files.extend( [KEYS_DIR + "/" + k for k in z.get("signer_keys")]) if filestamps.file_updated(needed_files, output_file): print("[signer] Creating zone " + z.get("name")) copy_or_sign_zone(z)
def get_zone_chunk(self, zd): zname = zd.get("name") zname_u = dnsutil.ufqdn(zname) lines = [ " - domain: %s" % zname, # TODO: tsig " acl: any", " acl: awb_md5", " acl: awb_sha1", " acl: awb_sha1_longkey", " acl: awb_sha256", ] if self.is_primary_for(zd): lines.append(" file: \"/var/dns-workbench/zones/%s\"" % zname_u) for secondary in zd.get("secondary_names"): raise Exception("NotImplYet " + self.get_name() + " " + zd.get("name")) elif self.is_secondary_for(zd): primary_addr = get_primary_addr(zd) lines.append(" master: m%s" % primary_addr) #lines.append(" notify-in m%s;" % primary_addr) lines.extend([""]) return lines
def get_zone_chunk(self, zd): # Note: the actual zones themselves are loaded with the update script # this merely sets them up for transfer-out xfrout_acl_base = "{ \"action\": \"ACCEPT\" }" xfrout_acl_base_key = "{ \"action\": \"ACCEPT\", \"key\": \"%s\" }" xfrout_acl = " [ " xfrout_acl += ", ".join( [xfrout_acl_base_key % (key.get_name()) for key in self.tsig_keys]) xfrout_acl += ", " + xfrout_acl_base + " ] " zname = zd.get("name") zname_u = dnsutil.ufqdn(zname) lines = [] if self.is_secondary_for(zd): lines.append("config add Xfrin/zones { " + "\"name\": \"%s\"," % zname + "\"class\": \"IN\"," + "\"master_addr\": \"%s\"," % get_primary_addr(zd) + "\"master_port\": 53" + " } ") lines.append("config add Xfrout/zone_config {" + "\"origin\": \"%s\", " % zd.get("name") + "\"class\": \"IN\", " + "\"transfer_acl\": %s" % xfrout_acl + " } ") return lines
def get_zone_chunk(self, zd): zname = zd.get("name") zname_u = dnsutil.ufqdn(zname) lines = [ "<zone>", " domain %s" % zname, ] if self.is_primary_for(zd): lines.append(" file masters/workbench/%s" % zname_u) lines.append(" type master") # TODO for some reasons this exception is triggered and causes problems - figure out why, fix them # For now, just skip it, because is seems to work if we do. #for secondary in zd.get("secondary_names"): # raise Exception("NotImplYet") lines.append(" maintain-dnssec false") lines.append(" dnssec-mode off") lines.append(" notify-auto false") elif self.is_secondary_for(zd): lines.append(" file slaves/workbench/%s" % zname_u) lines.append(" type slave") primary_addr = get_primary_addr(zd) lines.append(" master %s port 53" % primary_addr) lines.append("</zone>") lines.append("") return lines
def copy_or_sign_zone(zd): # only do this if there is a master if zd.get("nofile"): return signer = zd.get("signer_script") zname = dnsutil.ufqdn(zd.get("name")) infile = INPUT_DIR + "/" + zname outfile = OUTPUT_DIR + "/" + zname if signer == "": # just copy shutil.copy(infile, outfile) else: cmd = [signer] cmd.extend(zd.get("signer_params")) cmd.extend([KEYS_DIR + "/" + k for k in zd.get("signer_keys")]) print(" ".join(cmd)) with CWD(env.OUTPUT_BASE_PATH): try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except Exception: print("Error calling external program: " + " ".join(cmd)) raise out, err = p.communicate() if p.returncode != 0: sys.stdout.write(out.decode('utf-8')) sys.stderr.write(err.decode('utf-8')) raise Exception("Error calling subprocess: " + " ".join(cmd))
def finalize_or_sign_zone(zd): # only do this if there is a master if zd.get("nofile"): return finalizer = zd.get("finalizer_script") zname = dnsutil.ufqdn(zd.get("name")) infile = INPUT_DIR + "/" + zname outfile = OUTPUT_DIR + "/" + zname if finalizer == "": # just copy shutil.copy(infile, outfile) else: cmd = [ finalizer ] cmd.extend(zd.get("finalizer_params")) with CWD(env.OUTPUT_BASE_PATH): try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except Exception: print("Error calling external program: " + " ".join(cmd)) raise out, err = p.communicate() # TODO: check rcode if p.returncode != 0: sys.stderr.write("Error from subprocess stderr:\n") sys.stderr.write(err) raise Exception("Error calling subprocess: " + " ".join(cmd))
def get_update_lines(self): lines = [] lines.append("cat /var/workbench/bind10_commands.txt | bindctl") for zd in self.zds: zname = zd.get("name") zname_u = dnsutil.ufqdn(zname) if self.is_primary_for(zd): lines.append("b10-loadzone %s /var/workbench/zones/%s" % (zname, zname_u)) elif self.is_secondary_for(zd): lines.append("echo \"Xfrin retransfer %s\"" % (zname)) return lines
def add_standard_sign_options(zd): dname = zd.get("name") dname_u = dnsutil.ufqdn(dname) zd.set("signer_script", SIGNER) zd.add("signer_params", "-o") zd.add("signer_params", dname) zd.add("signer_params", "-e") zd.add("signer_params", "20300101000000") zd.add("signer_params", "-f") zd.add("signer_params", "signed/" + dname_u) # Make this stdin too? zd.add("signer_params", "unsigned/" + dname_u) zd.add("signer_keys", dname_u) zd.add("signer_keys", dname_u + ".ksk")
def create_zones(zones, regen): template_files = [ dnsutil.get_template_filename("basic_zone"), dnsutil.get_template_filename("all_ns") ] zds = [] # create the keys first for z in zones: # Check whether the key exists, if not, create keyfile = dnsutil.get_keyfile(z) dnsutil.check_create_key(z, keyfile) for z in zones: zonefile = ZONES_DIR + "/" + dnsutil.ufqdn(z) nsname = z.split(".")[0] zd = zonedata.ZoneData() zd.set("name", z) if nsname != "delegations": zd.add("primary_names", nsname) dnsutil.add_standard_sign_options(zd) zds.append(zd) if filestamps.file_updated(template_files, zonefile) or regen: with open(zonefile, "w") as out_file: dnsutil.add_template(out_file, "basic_zone", z, 3600) if nsname != "delegations": # one NS at apex, start with firstlabel out_file.write(" IN NS %s.%s\n" % (nsname, SERVER_ZONE)) else: # Add all nameservers for the top-level zone dnsutil.add_template(out_file, "all_ns", z, 3600) for deleg in delegation_servers: delname = deleg + "." + z if delname in zones: out_file.write("%s IN NS %s.%s\n" % (delname, deleg, SERVER_ZONE)) zonedata.write_zone_data(env.ZONE_DB_PATH + "/" + OUTPUT_FILE, zds)
def get_zone_chunk(self, zd): # We load most files with the bind backend, except for apexcname.wb.sidnlabs.nl, which we zone2sql into sqlite3 backend # because of https://github.com/PowerDNS/pdns/issues/7437 # Copied thie part mostly from Bind9ConfigGenerator zname = zd.get("name") zname_u = dnsutil.ufqdn(zname) lines = [ "zone \"%s\" {" % zname, " file \"/var/dns-workbench/zones/%s\";" % zname_u ] if self.is_primary_for(zd): lines.append(" type native;") # Secondory stuff left out here - won't use it anyway # again a dirty trick... zone2sql stripped the DNSSEC so that method couldn't be used lines.extend([ "};", "zone \"apexcname.wb.sidnlabs.nl.\" {", " file \"/var/dns-workbench/zones/apexcname.wb.sidnlabs.nl\";", " type native;", "};" ]) return lines
def get_zone_chunk(self, zd): zname = zd.get("name") zname_u = dnsutil.ufqdn(zname) lines = [ "zone \"%s\" {" % zname, " file \"/var/dns-workbench/zones/%s\";" % zname_u ] if self.is_primary_for(zd): lines.append(" type master;") secondary_addrs = [ env.SERVERS[n] for n in zd.get("secondary_names") ] if len(secondary_addrs) > 0: lines.append(" also-notify { %s; };" % "; ".join(secondary_addrs)) elif self.is_secondary_for(zd): lines.append(" type slave;") lines.append(" masters { %s; };" % get_primary_addr(zd)) lines.extend(["};"]) return lines
def get_zone_chunk(self, zd): zname = zd.get("name") zname_u = dnsutil.ufqdn(zname) lines = ["zone:"] lines.append("\tname: \"%s\"" % zname_u) # check zonesdir: in the server: section lines.append("\tzonefile: \"%s\"" % zname_u) # Allow all types of transfers from the entire world lines.append("\tprovide-xfr: 0.0.0.0/0 NOKEY") lines.append("\tprovide-xfr: ::0/0 NOKEY") for tk in self.tsig_keys: lines.append("\tprovide-xfr: 0.0.0.0/0 %s" % tk.get_name()) lines.append("\tprovide-xfr: ::0/0 %s" % tk.get_name()) if self.is_primary_for(zd): for sec in zd.get("secondary_names"): lines.append("\tnotify: %s NOKEY" % env.SERVERS[sec]) elif self.is_secondary_for(zd): master_addr = get_primary_addr(zd) lines.append("\tallow-notify: %s NOKEY" % (master_addr)) lines.append("\trequest-xfr: %s NOKEY" % (master_addr)) return lines
def create_bad_dnssec_tree(regen): zone_list = create_bad_dnssec_tree_zonelist(BASE_ZONE, 4) # For each of those, check whether key exists, and generate # the zone if necessary for zone in zone_list: # Check whether the key exists, if not, create keyfile = dnsutil.get_keyfile(zone) dnsutil.check_create_key(zone, keyfile) used_templates =\ [dnsutil.get_template_filename(t) for t in ["all_ns", "basic_zone" ]] zds = [] for zone in zone_list: # Check whether the key exists, if not, create keyfile = dnsutil.get_keyfile(zone) zonefile = ZONES_DIR + "/" + dnsutil.ufqdn(zone) # Create the zone if filestamps.file_updated(used_templates + [keyfile], zonefile): print("[bad_dnssec] Creating zone " + zone) create_zone(zone, zonefile) # Add entry to db generate_bad_dnssec_zone_entry(zds, zone) zonedata.write_zone_data(env.ZONE_DB_PATH + "/" + OUTPUT_FILE, zds)
def get_zone_chunk(self, zd): zname = zd.get("name") zname_u = dnsutil.ufqdn(zname) lines = [] return lines