1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#
# SPDX-FileCopyrightText: 2020 Kirill Elagin <https://kir.elagin.me/>
#
# SPDX-License-Identifier: MPL-2.0 or MIT
#
# This is a “fake” record type, not actually part of DNS.
# It gets compiled down to a TXT record.
# RFC 6376
{ lib }:
let
inherit (lib) dns mkOption types;
in
rec {
rtype = "TXT";
options = {
selector = mkOption {
type = types.str;
example = "mail";
description = "DKIM selector name";
};
h = mkOption {
type = types.listOf types.str;
default = [];
example = ["sha1" "sha256"];
description = "Acceptable hash algorithms. Empty means all of them";
apply = lib.concatStringsSep ":";
};
k = mkOption {
type = types.nullOr types.str;
default = "rsa";
example = "rsa";
description = "Key type";
};
n = mkOption {
type = types.str;
default = "";
example = "Just any kind of arbitrary notes.";
description = "Notes that might be of interest to a human";
};
p = mkOption {
type = types.str;
example = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDwIRP/UC3SBsEmGqZ9ZJW3/DkMoGeLnQg1fWn7/zYtIxN2SnFCjxOCKG9v3b4jYfcTNh5ijSsq631uBItLa7od+v/RtdC2UzJ1lWT947qR+Rcac2gbto/NMqJ0fzfVjH4OuKhitdY9tf6mcwGjaNBcWToIMmPSPDdQPNUYckcQ2QIDAQAB";
description = "Public-key data (base64)";
};
s = mkOption {
type = types.listOf (types.enum ["*" "email"]);
default = ["*"];
example = ["email"];
description = "Service Type";
apply = lib.concatStringsSep ":";
};
t = mkOption {
type = types.listOf (types.enum ["y" "s"]);
default = [];
example = ["y"];
description = "Flags";
apply = lib.concatStringsSep ":";
};
};
dataToString = data:
let
items = ["v=DKIM1"] ++ lib.pipe data [
(builtins.intersectAttrs options) # remove garbage list `_module`
(lib.filterAttrs (_k: v: v != null && v != ""))
(lib.filterAttrs (k: _v: k != "selector"))
(lib.mapAttrsToList (k: v: "${k}=${v}"))
];
result = lib.concatStringsSep "; " items + ";";
in dns.util.writeCharacterString result;
nameFixup = name: self:
"${self.selector}._domainkey.${name}";
}