grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / security / krb5 / krb5-conf-format.nix
blob3e5e64ae0cb0496f51b122b246c4e110f65dd3c5
1 { pkgs, lib, ... }:
3 # Based on
4 # - https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html
5 # - https://manpages.debian.org/unstable/heimdal-docs/krb5.conf.5heimdal.en.html
7 let
8   inherit (lib) boolToString concatMapStringsSep concatStringsSep filter
9     isAttrs isBool isList mapAttrsToList mkOption singleton splitString;
10   inherit (lib.types) attrsOf bool coercedTo either enum int listOf oneOf
11     path str submodule;
14   enableKdcACLEntries ? false
15 }: rec {
16   sectionType = let
17     relation = oneOf [
18       (listOf (attrsOf value))
19       (attrsOf value)
20       value
21     ];
22     value = either (listOf atom) atom;
23     atom = oneOf [int str bool];
24   in attrsOf relation;
26   type = let
27     aclEntry = submodule {
28       options = {
29         principal = mkOption {
30           type = str;
31           description = "Which principal the rule applies to";
32         };
33         access = mkOption {
34           type = either
35             (listOf (enum ["add" "cpw" "delete" "get" "list" "modify"]))
36             (enum ["all"]);
37           default = "all";
38           description = "The changes the principal is allowed to make.";
39         };
40         target = mkOption {
41           type = str;
42           default = "*";
43           description = "The principals that 'access' applies to.";
44         };
45       };
46     };
48     realm = submodule ({ name, ... }: {
49       freeformType = sectionType;
50       options = {
51         acl = mkOption {
52           type = listOf aclEntry;
53           default = [
54             { principal = "*/admin"; access = "all"; }
55             { principal = "admin"; access = "all"; }
56           ];
57           description = ''
58             The privileges granted to a user.
59           '';
60         };
61       };
62     });
63   in submodule {
64     freeformType = attrsOf sectionType;
65     options = {
66       include = mkOption {
67         default = [ ];
68         description = ''
69           Files to include in the Kerberos configuration.
70         '';
71         type = coercedTo path singleton (listOf path);
72       };
73       includedir = mkOption {
74         default = [ ];
75         description = ''
76           Directories containing files to include in the Kerberos configuration.
77         '';
78         type = coercedTo path singleton (listOf path);
79       };
80       module = mkOption {
81         default = [ ];
82         description = ''
83           Modules to obtain Kerberos configuration from.
84         '';
85         type = coercedTo path singleton (listOf path);
86       };
88     }
89     //
90     (lib.optionalAttrs enableKdcACLEntries {
91       realms = mkOption {
92         type = attrsOf realm;
93         description = ''
94           The realm(s) to serve keys for.
95         '';
96       };
97     });
98   };
100   generate = let
101     indent = str: concatMapStringsSep "\n" (line: "  " + line) (splitString "\n" str);
103     formatToplevel = args @ {
104       include ? [ ],
105       includedir ? [ ],
106       module ? [ ],
107       ...
108     }: let
109       sections = removeAttrs args [ "include" "includedir" "module" ];
110     in concatStringsSep "\n" (filter (x: x != "") [
111       (concatStringsSep "\n" (mapAttrsToList formatSection sections))
112       (concatMapStringsSep "\n" (m: "module ${m}") module)
113       (concatMapStringsSep "\n" (i: "include ${i}") include)
114       (concatMapStringsSep "\n" (i: "includedir ${i}") includedir)
115     ]);
117     formatSection = name: section: ''
118       [${name}]
119       ${indent (concatStringsSep "\n" (mapAttrsToList formatRelation section))}
120     '';
122     formatRelation = name: relation:
123       if isAttrs relation
124       then ''
125         ${name} = {
126         ${indent (concatStringsSep "\n" (mapAttrsToList formatValue relation))}
127         }''
128       else if isList relation
129       then
130         concatMapStringsSep "\n" (formatRelation name) relation
131       else formatValue name relation;
133     formatValue = name: value:
134       if isList value
135       then concatMapStringsSep "\n" (formatAtom name) value
136       else formatAtom name value;
138     formatAtom = name: atom: let
139       v = if isBool atom then boolToString atom else toString atom;
140     in "${name} = ${v}";
141   in
142     name: value: pkgs.writeText name ''
143       ${formatToplevel value}
144     '';