depot/third_party/nixpkgs/nixos/modules/security/krb5/krb5-conf-format.nix

204 lines
4.8 KiB
Nix

{ pkgs, lib, ... }:
# Based on
# - https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html
# - https://manpages.debian.org/unstable/heimdal-docs/krb5.conf.5heimdal.en.html
let
inherit (lib)
boolToString
concatMapStringsSep
concatStringsSep
filter
isAttrs
isBool
isList
mapAttrsToList
mkOption
singleton
splitString
;
inherit (lib.types)
attrsOf
bool
coercedTo
either
enum
int
listOf
oneOf
path
str
submodule
;
in
{
enableKdcACLEntries ? false,
}:
rec {
sectionType =
let
relation = oneOf [
(listOf (attrsOf value))
(attrsOf value)
value
];
value = either (listOf atom) atom;
atom = oneOf [
int
str
bool
];
in
attrsOf relation;
type =
let
aclEntry = submodule {
options = {
principal = mkOption {
type = str;
description = "Which principal the rule applies to";
};
access = mkOption {
type = either (listOf (enum [
"add"
"cpw"
"delete"
"get"
"list"
"modify"
])) (enum [ "all" ]);
default = "all";
description = "The changes the principal is allowed to make.";
};
target = mkOption {
type = str;
default = "*";
description = "The principals that 'access' applies to.";
};
};
};
realm = submodule (
{ name, ... }:
{
freeformType = sectionType;
options = {
acl = mkOption {
type = listOf aclEntry;
default = [
{
principal = "*/admin";
access = "all";
}
{
principal = "admin";
access = "all";
}
];
description = ''
The privileges granted to a user.
'';
};
};
}
);
in
submodule {
freeformType = attrsOf sectionType;
options =
{
include = mkOption {
default = [ ];
description = ''
Files to include in the Kerberos configuration.
'';
type = coercedTo path singleton (listOf path);
};
includedir = mkOption {
default = [ ];
description = ''
Directories containing files to include in the Kerberos configuration.
'';
type = coercedTo path singleton (listOf path);
};
module = mkOption {
default = [ ];
description = ''
Modules to obtain Kerberos configuration from.
'';
type = coercedTo path singleton (listOf path);
};
}
// (lib.optionalAttrs enableKdcACLEntries {
realms = mkOption {
type = attrsOf realm;
description = ''
The realm(s) to serve keys for.
'';
};
});
};
generate =
let
indent = str: concatMapStringsSep "\n" (line: " " + line) (splitString "\n" str);
formatToplevel =
args@{
include ? [ ],
includedir ? [ ],
module ? [ ],
...
}:
let
sections = removeAttrs args [
"include"
"includedir"
"module"
];
in
concatStringsSep "\n" (
filter (x: x != "") [
(concatStringsSep "\n" (mapAttrsToList formatSection sections))
(concatMapStringsSep "\n" (m: "module ${m}") module)
(concatMapStringsSep "\n" (i: "include ${i}") include)
(concatMapStringsSep "\n" (i: "includedir ${i}") includedir)
]
);
formatSection = name: section: ''
[${name}]
${indent (concatStringsSep "\n" (mapAttrsToList formatRelation section))}
'';
formatRelation =
name: relation:
if isAttrs relation then
''
${name} = {
${indent (concatStringsSep "\n" (mapAttrsToList formatValue relation))}
}''
else if isList relation then
concatMapStringsSep "\n" (formatRelation name) relation
else
formatValue name relation;
formatValue =
name: value:
if isList value then concatMapStringsSep "\n" (formatAtom name) value else formatAtom name value;
formatAtom =
name: atom:
let
v = if isBool atom then boolToString atom else toString atom;
in
"${name} = ${v}";
in
name: value:
pkgs.writeText name ''
${formatToplevel value}
'';
}