From 7aaab9eb30e749a8715ffb10774f35674b17223e Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 7 Jun 2023 23:34:00 +0000 Subject: [PATCH] WIP: DNS: split the zone generation out of trust-dns this is in preparation for upstreaming parts of this into nixpkgs --- hosts/by-name/servo/services/trust-dns.nix | 2 +- modules/default.nix | 1 + modules/services/trust-dns.nix | 134 +++------------------ 3 files changed, 16 insertions(+), 121 deletions(-) diff --git a/hosts/by-name/servo/services/trust-dns.nix b/hosts/by-name/servo/services/trust-dns.nix index 66b35759a..2fd209252 100644 --- a/hosts/by-name/servo/services/trust-dns.nix +++ b/hosts/by-name/servo/services/trust-dns.nix @@ -60,7 +60,7 @@ zone-dir = "/var/lib/trust-dns"; zone-wan = "${zone-dir}/wan/uninsane.org.zone"; zone-lan = "${zone-dir}/lan/uninsane.org.zone"; - zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.services.trust-dns.generatedZones."uninsane.org"; + zone-template = config.sane.services.trust-dns.zones."uninsane.org".file; in pkgs.writeShellScriptBin "named" '' # compute wan/lan values mkdir -p ${zone-dir}/{ovpn,wan,lan} diff --git a/modules/default.nix b/modules/default.nix index e5bc063e8..1e09ea95f 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -2,6 +2,7 @@ { imports = [ + ./dns.nix ./feeds.nix ./fs ./ids.nix diff --git a/modules/services/trust-dns.nix b/modules/services/trust-dns.nix index ae6568720..d40d82f1d 100644 --- a/modules/services/trust-dns.nix +++ b/modules/services/trust-dns.nix @@ -7,50 +7,6 @@ with lib; let cfg = config.sane.services.trust-dns; toml = pkgs.formats.toml { }; - recordFormatters = { - # quote rules for zone files: - # - any character may be encoded by `\DDD`, where `DDD` represents its ascii value in base 8. - # - any non-digit `X` may be encoded by `\X`. - # - stated in: : 5.1 Format - # - visible in - # for us, we can just replace `\` => `\\ and `"` -> `\"` - TXT = value: "\"" + (lib.escape [ "\\" "\"" ] value) + "\""; - }; - fmtRecord = proto: rrtype: name: value: - let - formatter = recordFormatters."${rrtype}" or lib.id; - in - "${name}\t${proto}\t${rrtype}\t${formatter value}"; - fmtRecordList = proto: rrtype: name: values: concatStringsSep - "\n" - (map (fmtRecord proto rrtype name) values) - ; - fmtRecordAttrs = proto: rrtype: rrAttrs: - concatStringsSep - "\n" - ( - attrValues ( - mapAttrs - (name: fmtRecordList proto rrtype name) - rrAttrs - ) - ); - fmtIncludes = paths: concatStringsSep - "\n" - (map (path: "$INCLUDE ${path}") paths); - - genZone = zcfg: '' - $TTL ${toString zcfg.TTL} - ${fmtRecordAttrs "IN" "SOA" zcfg.inet.SOA} - ${fmtRecordAttrs "IN" "A" zcfg.inet.A} - ${fmtRecordAttrs "IN" "CNAME" zcfg.inet.CNAME} - ${fmtRecordAttrs "IN" "MX" zcfg.inet.MX} - ${fmtRecordAttrs "IN" "NS" zcfg.inet.NS} - ${fmtRecordAttrs "IN" "SRV" zcfg.inet.SRV} - ${fmtRecordAttrs "IN" "TXT" zcfg.inet.TXT} - ${fmtIncludes zcfg.include} - ${zcfg.extraConfig} - ''; configFile = toml.generate "trust-dns.toml" { listen_addrs_ipv4 = cfg.listenAddrsIPv4; @@ -58,20 +14,10 @@ let mapAttrs (zname: zcfg: rec { zone = if zcfg.name == null then zname else zcfg.name; zone_type = "Primary"; - file = if zcfg.file == null then - pkgs.writeText "${zone}.zone" (genZone zcfg) - else - zcfg.file; + file = zcfg.file; }) cfg.zones ); }; - - # (listOf ty) type which also accepts single-assignment of `ty`. - # it's used to allow the user to write: - # CNAME."foo" = "bar"; - # as shorthand for - # CNAME."foo" = [ "bar" ]; - listOrUnit = ty: types.coercedTo ty (elem: [ elem ]) (types.listOf ty); in { options = { @@ -106,89 +52,37 @@ in }; # reference zones = mkOption { - type = types.attrsOf (types.submodule { + type = types.attrsOf (types.submodule ({ config, name, ... }: { options = { name = mkOption { type = types.nullOr types.str; description = "zone name. defaults to the attribute name in zones"; + default = name; + }; + text = mkOption { + type = types.nullOr types.str; # TODO: types.lines? default = null; }; - TTL = mkOption { - type = types.int; - description = "default TTL"; - default = 3600; - }; - include = mkOption { - type = types.listOf types.str; - description = "paths of other zone files to $INCLUDE into this one"; - default = []; - }; - extraConfig = mkOption { - type = types.lines; - description = "extra lines to append to the zone file"; - default = ""; - }; - inet = { - SOA = mkOption { - type = types.attrsOf (listOrUnit types.str); - description = "Start of Authority record(s)"; - default = {}; - }; - A = mkOption { - type = types.attrsOf (listOrUnit types.str); - description = "IPv4 address record(s)"; - default = {}; - }; - CNAME = mkOption { - type = types.attrsOf (listOrUnit types.str); - description = "canonical name record(s)"; - default = {}; - }; - MX = mkOption { - type = types.attrsOf (listOrUnit types.str); - description = "mail exchanger record(s)"; - default = {}; - }; - NS = mkOption { - type = types.attrsOf (listOrUnit types.str); - description = "name server record(s)"; - default = {}; - }; - SRV = mkOption { - type = types.attrsOf (listOrUnit types.str); - description = "service record(s)"; - default = {}; - }; - TXT = mkOption { - type = types.attrsOf (listOrUnit types.str); - description = "text record(s)"; - default = {}; - }; - }; - file = mkOption { - type = types.nullOr types.str; - default = null; + type = types.nullOr types.str; # TODO: types.path? description = '' - instead of using the generated zone file, use the specified path (user should populate the file specified here). + runtime path to a .zone file. + if omitted, will be generated from the `text` option. ''; }; }; - }); + + config = { + file = lib.mkIf (config.text != null) (pkgs.writeText "${config.name}.zone" config.text); + }; + })); default = {}; description = "Declarative zone config"; }; - - generatedZones = mkOption { - type = types.attrsOf types.str; - description = "generated zone text for each zone"; - }; }; }; config = mkIf cfg.enable { - sane.services.trust-dns.generatedZones = mapAttrs (zone: zcfg: genZone zcfg) cfg.zones; - sane.ports.ports."53" = { protocol = [ "udp" "tcp" ]; visibleTo.lan = true;