diff --git a/modules/records.nix b/modules/records.nix index 32e7fb3..1323369 100644 --- a/modules/records.nix +++ b/modules/records.nix @@ -388,11 +388,108 @@ lib.mapAttrs apply = lib.toList; }; }; + tlsa = { + common = { + description = '' + Used to bind X.509 certificates to domain names. + Can be generated with the `hash-slinger` package: + + ```bash + tlsa --create example.com --certificate /path/to/certificate.pem + ``` + ''; + type = + with lib.types; + let + tlsaSubModule = submodule { + options = { + usage = lib.mkOption { + description = '' + How to verify the certificate. + ''; + example = 3; + type = lib.types.int; + }; + selector = lib.mkOption { + description = '' + Which part of the certificate should be checked. + ''; + example = 0; + type = lib.types.int; + }; + matchingType = lib.mkOption { + description = '' + Whether to store the whole certificate in the certificate association data, or a hash of it. + ''; + example = 1; + type = lib.types.int; + }; + certificateAssociationData = lib.mkOption { + description = '' + The certificate or hash thereof to be matched, in hexadecimal format. + ''; + example = "2b03e032ab48fa5cb9d87c2e4ba1dda8ff9933fd1188f80f8508e132527a3801"; + type = lib.types.str; + }; + }; + }; + in + nullOr (oneOf [ + tlsaSubModule + (listOf (nullOr tlsaSubModule)) + ]); + apply = lib.toList; + }; + }; + sshfp = { + common = { + description = '' + Used to bind SSH host keys fingerprints to domain names. + Can be generated with the `openssh` package: + + ```bash + ssh-keyscan -D example.com + ``` + ''; + type = + with lib.types; + let + tlsaSubModule = submodule { + options = { + algorithm = lib.mkOption { + description = '' + Algorithm of the SSH host key. + ''; + example = 4; + type = lib.types.int; + }; + type = lib.mkOption { + description = '' + Algorith used to generate the fingerprint of the SSH host key. + ''; + example = 1; + type = lib.types.int; + }; + fingerprint = lib.mkOption { + description = '' + Hexadecimal fingerprint of the SSH host key. + ''; + example = "035e39adea06bd15c0b4ae06375f36459a5780bc"; + type = lib.types.str; + }; + }; + }; + in + nullOr (oneOf [ + tlsaSubModule + (listOf (nullOr tlsaSubModule)) + ]); + apply = lib.toList; + }; + }; # loc = lib.mkOption { }; # naptr = lib.mkOption { }; # ptr = lib.mkOption { }; - # sshfp = lib.mkOption { }; - # tlsa = lib.mkOption { }; # zonemd = lib.mkOption { }; } ) diff --git a/utils/tests/zonefiles.nix b/utils/tests/zonefiles.nix index 2b7cea7..d12e0c9 100644 --- a/utils/tests/zonefiles.nix +++ b/utils/tests/zonefiles.nix @@ -69,6 +69,16 @@ ttl = 60; data = [ "v=spf1 a:mail.aq0.de -all" ]; }; + sshfp = { + ttl = 60; + data = [ + { + algorithm = 4; + type = 2; + fingerprint = "f4f4ada530e64b5e574ed4459d7a40424179fd03a766282a2c1060010719626f"; + } + ]; + }; }; "*.example.com" = { alias = { @@ -76,6 +86,19 @@ data = [ "example.com" ]; }; }; + "_443._tcp.example.com" = { + tlsa = { + ttl = 3600; + data = [ + { + usage = 3; + selector = 1; + matchingType = 1; + certificateAssociationData = "9c4b5e3816504bdf4cbcfcc5c1b41ac18f2def723ec0d8299543e6d06471e610"; + } + ]; + }; + }; "_ftp._tcp.example.com" = { uri = { ttl = 3600; @@ -117,6 +140,7 @@ ); expected = '' *.example.com. IN 60 ALIAS example.com + _443._tcp.example.com. IN 3600 TLSA 3 1 1 9c4b5e3816504bdf4cbcfcc5c1b41ac18f2def723ec0d8299543e6d06471e610 _ftp._tcp.example.com. IN 3600 URI 10 5 ftp://example.com/public _xmpp._tcp.example.com. IN 86400 SRV 10 5 5223 xmpp.example.com example.com. IN 60 A 198.51.100.42 @@ -127,6 +151,7 @@ example.com. IN 60 NS ns2.example.com. example.com. IN 60 NS ns3.example.org. example.com. IN 60 SOA ns.example.invalid. admin.example.invalid. ( 1970010100 7200 3600 1209600 60 ) + example.com. IN 60 SSHFP 4 2 f4f4ada530e64b5e574ed4459d7a40424179fd03a766282a2c1060010719626f example.com. IN 60 TXT "v=spf1 a:mail.aq0.de -all" mail.example.com. IN 60 CNAME e-mail.provider.invalid redirect.example.com. IN 60 DNAME example.org diff --git a/utils/zonefiles.nix b/utils/zonefiles.nix index 5ffc3e0..0827b83 100644 --- a/utils/zonefiles.nix +++ b/utils/zonefiles.nix @@ -60,6 +60,10 @@ "SOA ${value.mname}. ${value.rname}. ( ${builtins.toString value.serial} ${builtins.toString value.refresh} ${builtins.toString value.retry} ${builtins.toString value.expire} ${builtins.toString value.ttl} )" else if record == "txt" then "TXT ${utils.zonefiles.formatTxtRecord value}" + else if record == "tlsa" then + "TLSA ${builtins.toString value.usage} ${builtins.toString value.selector} ${builtins.toString value.matchingType} ${value.certificateAssociationData}" + else if record == "sshfp" then + "SSHFP ${builtins.toString value.algorithm} ${builtins.toString value.type} ${value.fingerprint}" else "${lib.toUpper record} ${value}"; /*