2020-04-24 23:36:52 +00:00
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
|
|
|
|
let
|
|
|
|
|
|
|
|
cfg = config.krb5;
|
|
|
|
|
|
|
|
# This is to provide support for old configuration options (as much as is
|
|
|
|
# reasonable). This can be removed after 18.03 was released.
|
|
|
|
defaultConfig = {
|
|
|
|
libdefaults = optionalAttrs (cfg.defaultRealm != null)
|
|
|
|
{ default_realm = cfg.defaultRealm; };
|
|
|
|
|
|
|
|
realms = optionalAttrs (lib.all (value: value != null) [
|
|
|
|
cfg.defaultRealm cfg.kdc cfg.kerberosAdminServer
|
|
|
|
]) {
|
|
|
|
${cfg.defaultRealm} = {
|
|
|
|
kdc = cfg.kdc;
|
|
|
|
admin_server = cfg.kerberosAdminServer;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
domain_realm = optionalAttrs (lib.all (value: value != null) [
|
|
|
|
cfg.domainRealm cfg.defaultRealm
|
|
|
|
]) {
|
|
|
|
".${cfg.domainRealm}" = cfg.defaultRealm;
|
|
|
|
${cfg.domainRealm} = cfg.defaultRealm;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
mergedConfig = (recursiveUpdate defaultConfig {
|
|
|
|
inherit (config.krb5)
|
|
|
|
kerberos libdefaults realms domain_realm capaths appdefaults plugins
|
|
|
|
extraConfig config;
|
|
|
|
});
|
|
|
|
|
|
|
|
filterEmbeddedMetadata = value: if isAttrs value then
|
|
|
|
(filterAttrs
|
|
|
|
(attrName: attrValue: attrName != "_module" && attrValue != null)
|
|
|
|
value)
|
|
|
|
else value;
|
|
|
|
|
2020-09-25 04:45:31 +00:00
|
|
|
indent = " ";
|
2020-04-24 23:36:52 +00:00
|
|
|
|
2020-09-25 04:45:31 +00:00
|
|
|
mkRelation = name: value:
|
|
|
|
if (isList value) then
|
|
|
|
concatMapStringsSep "\n" (mkRelation name) value
|
|
|
|
else "${name} = ${mkVal value}";
|
2020-04-24 23:36:52 +00:00
|
|
|
|
2020-09-25 04:45:31 +00:00
|
|
|
mkVal = value:
|
2020-04-24 23:36:52 +00:00
|
|
|
if (value == true) then "true"
|
|
|
|
else if (value == false) then "false"
|
|
|
|
else if (isInt value) then (toString value)
|
|
|
|
else if (isAttrs value) then
|
2020-09-25 04:45:31 +00:00
|
|
|
let configLines = concatLists
|
|
|
|
(map (splitString "\n")
|
|
|
|
(mapAttrsToList mkRelation value));
|
|
|
|
in
|
|
|
|
(concatStringsSep "\n${indent}"
|
|
|
|
([ "{" ] ++ configLines))
|
|
|
|
+ "\n}"
|
2020-04-24 23:36:52 +00:00
|
|
|
else value;
|
|
|
|
|
|
|
|
mkMappedAttrsOrString = value: concatMapStringsSep "\n"
|
|
|
|
(line: if builtins.stringLength line > 0
|
2020-09-25 04:45:31 +00:00
|
|
|
then "${indent}${line}"
|
2020-04-24 23:36:52 +00:00
|
|
|
else line)
|
|
|
|
(splitString "\n"
|
|
|
|
(if isAttrs value then
|
|
|
|
concatStringsSep "\n"
|
|
|
|
(mapAttrsToList mkRelation value)
|
|
|
|
else value));
|
|
|
|
|
|
|
|
in {
|
|
|
|
|
|
|
|
###### interface
|
|
|
|
|
|
|
|
options = {
|
|
|
|
krb5 = {
|
|
|
|
enable = mkEnableOption "building krb5.conf, configuration file for Kerberos V";
|
|
|
|
|
|
|
|
kerberos = mkOption {
|
|
|
|
type = types.package;
|
|
|
|
default = pkgs.krb5Full;
|
2021-10-06 13:57:05 +00:00
|
|
|
defaultText = literalExpression "pkgs.krb5Full";
|
|
|
|
example = literalExpression "pkgs.heimdal";
|
2020-04-24 23:36:52 +00:00
|
|
|
description = ''
|
|
|
|
The Kerberos implementation that will be present in
|
|
|
|
<literal>environment.systemPackages</literal> after enabling this
|
|
|
|
service.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
libdefaults = mkOption {
|
|
|
|
type = with types; either attrs lines;
|
|
|
|
default = {};
|
|
|
|
apply = attrs: filterEmbeddedMetadata attrs;
|
2021-10-06 13:57:05 +00:00
|
|
|
example = literalExpression ''
|
2020-04-24 23:36:52 +00:00
|
|
|
{
|
|
|
|
default_realm = "ATHENA.MIT.EDU";
|
|
|
|
};
|
|
|
|
'';
|
|
|
|
description = ''
|
|
|
|
Settings used by the Kerberos V5 library.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
realms = mkOption {
|
|
|
|
type = with types; either attrs lines;
|
|
|
|
default = {};
|
2021-10-06 13:57:05 +00:00
|
|
|
example = literalExpression ''
|
2020-04-24 23:36:52 +00:00
|
|
|
{
|
|
|
|
"ATHENA.MIT.EDU" = {
|
|
|
|
admin_server = "athena.mit.edu";
|
2020-09-25 04:45:31 +00:00
|
|
|
kdc = [
|
|
|
|
"athena01.mit.edu"
|
|
|
|
"athena02.mit.edu"
|
|
|
|
];
|
2020-04-24 23:36:52 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
'';
|
|
|
|
apply = attrs: filterEmbeddedMetadata attrs;
|
|
|
|
description = "Realm-specific contact information and settings.";
|
|
|
|
};
|
|
|
|
|
|
|
|
domain_realm = mkOption {
|
|
|
|
type = with types; either attrs lines;
|
|
|
|
default = {};
|
2021-10-06 13:57:05 +00:00
|
|
|
example = literalExpression ''
|
2020-04-24 23:36:52 +00:00
|
|
|
{
|
|
|
|
"example.com" = "EXAMPLE.COM";
|
|
|
|
".example.com" = "EXAMPLE.COM";
|
|
|
|
};
|
|
|
|
'';
|
|
|
|
apply = attrs: filterEmbeddedMetadata attrs;
|
|
|
|
description = ''
|
|
|
|
Map of server hostnames to Kerberos realms.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
capaths = mkOption {
|
|
|
|
type = with types; either attrs lines;
|
|
|
|
default = {};
|
2021-10-06 13:57:05 +00:00
|
|
|
example = literalExpression ''
|
2020-04-24 23:36:52 +00:00
|
|
|
{
|
|
|
|
"ATHENA.MIT.EDU" = {
|
|
|
|
"EXAMPLE.COM" = ".";
|
|
|
|
};
|
|
|
|
"EXAMPLE.COM" = {
|
|
|
|
"ATHENA.MIT.EDU" = ".";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
'';
|
|
|
|
apply = attrs: filterEmbeddedMetadata attrs;
|
|
|
|
description = ''
|
|
|
|
Authentication paths for non-hierarchical cross-realm authentication.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
appdefaults = mkOption {
|
|
|
|
type = with types; either attrs lines;
|
|
|
|
default = {};
|
2021-10-06 13:57:05 +00:00
|
|
|
example = literalExpression ''
|
2020-04-24 23:36:52 +00:00
|
|
|
{
|
|
|
|
pam = {
|
|
|
|
debug = false;
|
|
|
|
ticket_lifetime = 36000;
|
|
|
|
renew_lifetime = 36000;
|
|
|
|
max_timeout = 30;
|
|
|
|
timeout_shift = 2;
|
|
|
|
initial_timeout = 1;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
'';
|
|
|
|
apply = attrs: filterEmbeddedMetadata attrs;
|
|
|
|
description = ''
|
|
|
|
Settings used by some Kerberos V5 applications.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
plugins = mkOption {
|
|
|
|
type = with types; either attrs lines;
|
|
|
|
default = {};
|
2021-10-06 13:57:05 +00:00
|
|
|
example = literalExpression ''
|
2020-04-24 23:36:52 +00:00
|
|
|
{
|
|
|
|
ccselect = {
|
|
|
|
disable = "k5identity";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
'';
|
|
|
|
apply = attrs: filterEmbeddedMetadata attrs;
|
|
|
|
description = ''
|
|
|
|
Controls plugin module registration.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
extraConfig = mkOption {
|
|
|
|
type = with types; nullOr lines;
|
|
|
|
default = null;
|
|
|
|
example = ''
|
|
|
|
[logging]
|
|
|
|
kdc = SYSLOG:NOTICE
|
|
|
|
admin_server = SYSLOG:NOTICE
|
|
|
|
default = SYSLOG:NOTICE
|
|
|
|
'';
|
|
|
|
description = ''
|
|
|
|
These lines go to the end of <literal>krb5.conf</literal> verbatim.
|
|
|
|
<literal>krb5.conf</literal> may include any of the relations that are
|
|
|
|
valid for <literal>kdc.conf</literal> (see <literal>man
|
|
|
|
kdc.conf</literal>), but it is not a recommended practice.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkOption {
|
|
|
|
type = with types; nullOr lines;
|
|
|
|
default = null;
|
|
|
|
example = ''
|
|
|
|
[libdefaults]
|
|
|
|
default_realm = EXAMPLE.COM
|
|
|
|
|
|
|
|
[realms]
|
|
|
|
EXAMPLE.COM = {
|
|
|
|
admin_server = kerberos.example.com
|
|
|
|
kdc = kerberos.example.com
|
|
|
|
default_principal_flags = +preauth
|
|
|
|
}
|
|
|
|
|
|
|
|
[domain_realm]
|
|
|
|
example.com = EXAMPLE.COM
|
|
|
|
.example.com = EXAMPLE.COM
|
|
|
|
|
|
|
|
[logging]
|
|
|
|
kdc = SYSLOG:NOTICE
|
|
|
|
admin_server = SYSLOG:NOTICE
|
|
|
|
default = SYSLOG:NOTICE
|
|
|
|
'';
|
|
|
|
description = ''
|
|
|
|
Verbatim <literal>krb5.conf</literal> configuration. Note that this
|
|
|
|
is mutually exclusive with configuration via
|
|
|
|
<literal>libdefaults</literal>, <literal>realms</literal>,
|
|
|
|
<literal>domain_realm</literal>, <literal>capaths</literal>,
|
|
|
|
<literal>appdefaults</literal>, <literal>plugins</literal> and
|
|
|
|
<literal>extraConfig</literal> configuration options. Consult
|
|
|
|
<literal>man krb5.conf</literal> for documentation.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
defaultRealm = mkOption {
|
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
example = "ATHENA.MIT.EDU";
|
|
|
|
description = ''
|
|
|
|
DEPRECATED, please use
|
|
|
|
<literal>krb5.libdefaults.default_realm</literal>.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
domainRealm = mkOption {
|
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
example = "athena.mit.edu";
|
|
|
|
description = ''
|
|
|
|
DEPRECATED, please create a map of server hostnames to Kerberos realms
|
|
|
|
in <literal>krb5.domain_realm</literal>.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
kdc = mkOption {
|
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
example = "kerberos.mit.edu";
|
|
|
|
description = ''
|
|
|
|
DEPRECATED, please pass a <literal>kdc</literal> attribute to a realm
|
|
|
|
in <literal>krb5.realms</literal>.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
kerberosAdminServer = mkOption {
|
|
|
|
type = with types; nullOr str;
|
|
|
|
default = null;
|
|
|
|
example = "kerberos.mit.edu";
|
|
|
|
description = ''
|
|
|
|
DEPRECATED, please pass an <literal>admin_server</literal> attribute
|
|
|
|
to a realm in <literal>krb5.realms</literal>.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
###### implementation
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
|
|
|
|
environment.systemPackages = [ cfg.kerberos ];
|
|
|
|
|
|
|
|
environment.etc."krb5.conf".text = if isString cfg.config
|
|
|
|
then cfg.config
|
|
|
|
else (''
|
|
|
|
[libdefaults]
|
|
|
|
${mkMappedAttrsOrString mergedConfig.libdefaults}
|
|
|
|
|
|
|
|
[realms]
|
|
|
|
${mkMappedAttrsOrString mergedConfig.realms}
|
|
|
|
|
|
|
|
[domain_realm]
|
|
|
|
${mkMappedAttrsOrString mergedConfig.domain_realm}
|
|
|
|
|
|
|
|
[capaths]
|
|
|
|
${mkMappedAttrsOrString mergedConfig.capaths}
|
|
|
|
|
|
|
|
[appdefaults]
|
|
|
|
${mkMappedAttrsOrString mergedConfig.appdefaults}
|
|
|
|
|
|
|
|
[plugins]
|
|
|
|
${mkMappedAttrsOrString mergedConfig.plugins}
|
|
|
|
'' + optionalString (mergedConfig.extraConfig != null)
|
|
|
|
("\n" + mergedConfig.extraConfig));
|
|
|
|
|
|
|
|
warnings = flatten [
|
|
|
|
(optional (cfg.defaultRealm != null) ''
|
|
|
|
The option krb5.defaultRealm is deprecated, please use
|
|
|
|
krb5.libdefaults.default_realm.
|
|
|
|
'')
|
|
|
|
(optional (cfg.domainRealm != null) ''
|
|
|
|
The option krb5.domainRealm is deprecated, please use krb5.domain_realm.
|
|
|
|
'')
|
|
|
|
(optional (cfg.kdc != null) ''
|
|
|
|
The option krb5.kdc is deprecated, please pass a kdc attribute to a
|
|
|
|
realm in krb5.realms.
|
|
|
|
'')
|
|
|
|
(optional (cfg.kerberosAdminServer != null) ''
|
|
|
|
The option krb5.kerberosAdminServer is deprecated, please pass an
|
|
|
|
admin_server attribute to a realm in krb5.realms.
|
|
|
|
'')
|
|
|
|
];
|
|
|
|
|
|
|
|
assertions = [
|
|
|
|
{ assertion = !((builtins.any (value: value != null) [
|
|
|
|
cfg.defaultRealm cfg.domainRealm cfg.kdc cfg.kerberosAdminServer
|
|
|
|
]) && ((builtins.any (value: value != {}) [
|
|
|
|
cfg.libdefaults cfg.realms cfg.domain_realm cfg.capaths
|
|
|
|
cfg.appdefaults cfg.plugins
|
|
|
|
]) || (builtins.any (value: value != null) [
|
|
|
|
cfg.config cfg.extraConfig
|
|
|
|
])));
|
|
|
|
message = ''
|
|
|
|
Configuration of krb5.conf by deprecated options is mutually exclusive
|
|
|
|
with configuration by section. Please migrate your config using the
|
|
|
|
attributes suggested in the warnings.
|
|
|
|
'';
|
|
|
|
}
|
|
|
|
{ assertion = !(cfg.config != null
|
|
|
|
&& ((builtins.any (value: value != {}) [
|
|
|
|
cfg.libdefaults cfg.realms cfg.domain_realm cfg.capaths
|
|
|
|
cfg.appdefaults cfg.plugins
|
|
|
|
]) || (builtins.any (value: value != null) [
|
|
|
|
cfg.extraConfig cfg.defaultRealm cfg.domainRealm cfg.kdc
|
|
|
|
cfg.kerberosAdminServer
|
|
|
|
])));
|
|
|
|
message = ''
|
|
|
|
Configuration of krb5.conf using krb.config is mutually exclusive with
|
|
|
|
configuration by section. If you want to mix the two, you can pass
|
|
|
|
lines to any configuration section or lines to krb5.extraConfig.
|
|
|
|
'';
|
|
|
|
}
|
|
|
|
];
|
|
|
|
};
|
|
|
|
}
|