0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-13 21:50:33 +03:00

nixos/krb5: cleanup, fix and RFC42-ify

This replaces the krb5 module's options with RFC 42-style krb5.settings
option, while greatly simplifying the code and fixing a few bugs,
namely:

- #243068 krb5: Configuration silently gets ignored when set by
  multiple modules
- not being able to use mkIf etc. inside subattributes of
  krb5.libdefaults, e.g. krb5.libdefaults.default_realm = mkIf ...

See #144575.
Closes #243068.

Co-authored-by: h7x4 <h7x4@nani.wtf>
This commit is contained in:
Marco Rebhan 2023-07-13 01:21:59 +02:00
parent 808d2bd0ae
commit 92a541c0ed
No known key found for this signature in database
12 changed files with 252 additions and 484 deletions

View file

@ -94,6 +94,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- `services.zfs.zed.enableMail` now uses the global `sendmail` wrapper defined by an email module - `services.zfs.zed.enableMail` now uses the global `sendmail` wrapper defined by an email module
(such as msmtp or Postfix). It no longer requires using a special ZFS build with email support. (such as msmtp or Postfix). It no longer requires using a special ZFS build with email support.
- The `krb5` module has been rewritten, moving all options but `krb5.enable` and `krb5.package` into `krb5.settings`.
- Gitea 1.21 upgrade has several breaking changes, including: - Gitea 1.21 upgrade has several breaking changes, including:
- Custom themes and other assets that were previously stored in `custom/public/*` now belong in `custom/public/assets/*` - Custom themes and other assets that were previously stored in `custom/public/*` now belong in `custom/public/assets/*`
- New instances of Gitea using MySQL now ignore the `[database].CHARSET` config option and always use the `utf8mb4` charset, existing instances should migrate via the `gitea doctor convert` CLI command. - New instances of Gitea using MySQL now ignore the `[database].CHARSET` config option and always use the `utf8mb4` charset, existing instances should migrate via the `gitea doctor convert` CLI command.

View file

@ -1,116 +1,59 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
inherit (lib) mdDoc mkIf mkOption mkPackageOption mkRemovedOptionModule;
inherit (lib.types) bool;
mkRemovedOptionModule' = name: reason: mkRemovedOptionModule ["krb5" name] reason;
mkRemovedOptionModuleCfg = name: mkRemovedOptionModule' name ''
The option `krb5.${name}' has been removed. Use `krb5.settings.${name}' for
structured configuration.
'';
cfg = config.krb5; cfg = config.krb5;
format = import ./krb5-conf-format.nix { inherit pkgs lib; } { };
# 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;
indent = " ";
mkRelation = name: value:
if (isList value) then
concatMapStringsSep "\n" (mkRelation name) value
else "${name} = ${mkVal value}";
mkVal = value:
if (value == true) then "true"
else if (value == false) then "false"
else if (isInt value) then (toString value)
else if (isAttrs value) then
let configLines = concatLists
(map (splitString "\n")
(mapAttrsToList mkRelation value));
in
(concatStringsSep "\n${indent}"
([ "{" ] ++ configLines))
+ "\n}"
else value;
mkMappedAttrsOrString = value: concatMapStringsSep "\n"
(line: if builtins.stringLength line > 0
then "${indent}${line}"
else line)
(splitString "\n"
(if isAttrs value then
concatStringsSep "\n"
(mapAttrsToList mkRelation value)
else value));
in { in {
imports = [
###### interface (mkRemovedOptionModuleCfg "libdefaults")
(mkRemovedOptionModuleCfg "realms")
(mkRemovedOptionModuleCfg "domain_realm")
(mkRemovedOptionModuleCfg "capaths")
(mkRemovedOptionModuleCfg "appdefaults")
(mkRemovedOptionModuleCfg "plugins")
(mkRemovedOptionModuleCfg "config")
(mkRemovedOptionModuleCfg "extraConfig")
(mkRemovedOptionModule' "kerberos" ''
The option `krb5.kerberos' has been moved to `krb5.package'.
'')
];
options = { options = {
krb5 = { krb5 = {
enable = mkEnableOption (lib.mdDoc "building krb5.conf, configuration file for Kerberos V"); enable = mkOption {
default = false;
kerberos = mkOption { description = mdDoc "Enable and configure Kerberos utilities";
type = types.package; type = bool;
default = pkgs.krb5;
defaultText = literalExpression "pkgs.krb5";
example = literalExpression "pkgs.heimdal";
description = lib.mdDoc ''
The Kerberos implementation that will be present in
`environment.systemPackages` after enabling this
service.
'';
}; };
libdefaults = mkOption { package = mkPackageOption pkgs "krb5" {
type = with types; either attrs lines; example = "heimdal";
default = {}; };
apply = attrs: filterEmbeddedMetadata attrs;
example = literalExpression '' settings = mkOption {
{ default = { };
type = format.type;
description = mdDoc ''
Structured contents of the {file}`krb5.conf` file. See
{manpage}`krb5.conf(5)` for details about configuration.
'';
example = {
include = [ "/run/secrets/secret-krb5.conf" ];
includedir = [ "/run/secrets/secret-krb5.conf.d" ];
libdefaults = {
default_realm = "ATHENA.MIT.EDU"; default_realm = "ATHENA.MIT.EDU";
}; };
'';
description = lib.mdDoc ''
Settings used by the Kerberos V5 library.
'';
};
realms = mkOption { realms = {
type = with types; either attrs lines;
default = {};
example = literalExpression ''
{
"ATHENA.MIT.EDU" = { "ATHENA.MIT.EDU" = {
admin_server = "athena.mit.edu"; admin_server = "athena.mit.edu";
kdc = [ kdc = [
@ -119,251 +62,25 @@ in {
]; ];
}; };
}; };
'';
apply = attrs: filterEmbeddedMetadata attrs;
description = lib.mdDoc "Realm-specific contact information and settings.";
};
domain_realm = mkOption { domain_realm = {
type = with types; either attrs lines; "mit.edu" = "ATHENA.MIT.EDU";
default = {};
example = literalExpression ''
{
"example.com" = "EXAMPLE.COM";
".example.com" = "EXAMPLE.COM";
}; };
'';
apply = attrs: filterEmbeddedMetadata attrs;
description = lib.mdDoc ''
Map of server hostnames to Kerberos realms.
'';
};
capaths = mkOption { logging = {
type = with types; either attrs lines; kdc = "SYSLOG:NOTICE";
default = {}; admin_server = "SYSLOG:NOTICE";
example = literalExpression '' default = "SYSLOG:NOTICE";
{
"ATHENA.MIT.EDU" = {
"EXAMPLE.COM" = ".";
};
"EXAMPLE.COM" = {
"ATHENA.MIT.EDU" = ".";
};
}; };
''; };
apply = attrs: filterEmbeddedMetadata attrs;
description = lib.mdDoc ''
Authentication paths for non-hierarchical cross-realm authentication.
'';
};
appdefaults = mkOption {
type = with types; either attrs lines;
default = {};
example = literalExpression ''
{
pam = {
debug = false;
ticket_lifetime = 36000;
renew_lifetime = 36000;
max_timeout = 30;
timeout_shift = 2;
initial_timeout = 1;
};
};
'';
apply = attrs: filterEmbeddedMetadata attrs;
description = lib.mdDoc ''
Settings used by some Kerberos V5 applications.
'';
};
plugins = mkOption {
type = with types; either attrs lines;
default = {};
example = literalExpression ''
{
ccselect = {
disable = "k5identity";
};
};
'';
apply = attrs: filterEmbeddedMetadata attrs;
description = lib.mdDoc ''
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 = lib.mdDoc ''
These lines go to the end of `krb5.conf` verbatim.
`krb5.conf` may include any of the relations that are
valid for `kdc.conf` (see `man kdc.conf`),
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 = lib.mdDoc ''
Verbatim `krb5.conf` configuration. Note that this
is mutually exclusive with configuration via
`libdefaults`, `realms`,
`domain_realm`, `capaths`,
`appdefaults`, `plugins` and
`extraConfig` configuration options. Consult
`man krb5.conf` for documentation.
'';
};
defaultRealm = mkOption {
type = with types; nullOr str;
default = null;
example = "ATHENA.MIT.EDU";
description = lib.mdDoc ''
DEPRECATED, please use
`krb5.libdefaults.default_realm`.
'';
};
domainRealm = mkOption {
type = with types; nullOr str;
default = null;
example = "athena.mit.edu";
description = lib.mdDoc ''
DEPRECATED, please create a map of server hostnames to Kerberos realms
in `krb5.domain_realm`.
'';
};
kdc = mkOption {
type = with types; nullOr str;
default = null;
example = "kerberos.mit.edu";
description = lib.mdDoc ''
DEPRECATED, please pass a `kdc` attribute to a realm
in `krb5.realms`.
'';
};
kerberosAdminServer = mkOption {
type = with types; nullOr str;
default = null;
example = "kerberos.mit.edu";
description = lib.mdDoc ''
DEPRECATED, please pass an `admin_server` attribute
to a realm in `krb5.realms`.
'';
}; };
}; };
}; };
###### implementation
config = mkIf cfg.enable { config = mkIf cfg.enable {
environment = {
environment.systemPackages = [ cfg.kerberos ]; systemPackages = [ cfg.package ];
etc."krb5.conf".source = format.generate "krb5.conf" cfg.settings;
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.
'';
}
];
}; };
} }

View file

@ -0,0 +1,88 @@
{ 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 mdDoc mkOption singleton splitString;
inherit (lib.types) attrsOf bool coercedTo either int listOf oneOf path
str submodule;
in
{ }: {
type = let
section = attrsOf relation;
relation = either (attrsOf value) value;
value = either (listOf atom) atom;
atom = oneOf [int str bool];
in submodule {
freeformType = attrsOf section;
options = {
include = mkOption {
default = [ ];
description = mdDoc ''
Files to include in the Kerberos configuration.
'';
type = coercedTo path singleton (listOf path);
};
includedir = mkOption {
default = [ ];
description = mdDoc ''
Directories containing files to include in the Kerberos configuration.
'';
type = coercedTo path singleton (listOf path);
};
module = mkOption {
default = [ ];
description = mdDoc ''
Modules to obtain Kerberos configuration from.
'';
type = coercedTo path singleton (listOf path);
};
};
};
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 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}
'';
}

View file

@ -3,7 +3,7 @@
let let
inherit (lib) mkOption mkIf types length attrNames; inherit (lib) mkOption mkIf types length attrNames;
cfg = config.services.kerberos_server; cfg = config.services.kerberos_server;
kerberos = config.krb5.kerberos; kerberos = config.krb5.package;
aclEntry = { aclEntry = {
options = { options = {

View file

@ -4,7 +4,7 @@ let
inherit (lib) mkIf concatStringsSep concatMapStrings toList mapAttrs inherit (lib) mkIf concatStringsSep concatMapStrings toList mapAttrs
mapAttrsToList; mapAttrsToList;
cfg = config.services.kerberos_server; cfg = config.services.kerberos_server;
kerberos = config.krb5.kerberos; kerberos = config.krb5.package;
stateDir = "/var/heimdal"; stateDir = "/var/heimdal";
aclFiles = mapAttrs aclFiles = mapAttrs
(name: {acl, ...}: pkgs.writeText "${name}.acl" (concatMapStrings (( (name: {acl, ...}: pkgs.writeText "${name}.acl" (concatMapStrings ((

View file

@ -4,7 +4,7 @@ let
inherit (lib) mkIf concatStrings concatStringsSep concatMapStrings toList inherit (lib) mkIf concatStrings concatStringsSep concatMapStrings toList
mapAttrs mapAttrsToList; mapAttrs mapAttrsToList;
cfg = config.services.kerberos_server; cfg = config.services.kerberos_server;
kerberos = config.krb5.kerberos; kerberos = config.krb5.package;
stateDir = "/var/lib/krb5kdc"; stateDir = "/var/lib/krb5kdc";
PIDFile = "/run/kdc.pid"; PIDFile = "/run/kdc.pid";
aclMap = { aclMap = {

View file

@ -9,14 +9,16 @@ import ../make-test-python.nix ({pkgs, ...}: {
}; };
krb5 = { krb5 = {
enable = true; enable = true;
kerberos = pkgs.heimdal; package = pkgs.heimdal;
libdefaults = { settings = {
default_realm = "FOO.BAR"; libdefaults = {
}; default_realm = "FOO.BAR";
realms = { };
"FOO.BAR" = { realms = {
admin_server = "machine"; "FOO.BAR" = {
kdc = "machine"; admin_server = "machine";
kdc = "machine";
};
}; };
}; };
}; };

View file

@ -9,14 +9,16 @@ import ../make-test-python.nix ({pkgs, ...}: {
}; };
krb5 = { krb5 = {
enable = true; enable = true;
kerberos = pkgs.krb5; package = pkgs.krb5;
libdefaults = { settings = {
default_realm = "FOO.BAR"; libdefaults = {
}; default_realm = "FOO.BAR";
realms = { };
"FOO.BAR" = { realms = {
admin_server = "machine"; "FOO.BAR" = {
kdc = "machine"; admin_server = "machine";
kdc = "machine";
};
}; };
}; };
}; };

View file

@ -1,5 +1,4 @@
{ system ? builtins.currentSystem }: { system ? builtins.currentSystem }:
{ {
example-config = import ./example-config.nix { inherit system; }; example-config = import ./example-config.nix { inherit system; };
deprecated-config = import ./deprecated-config.nix { inherit system; };
} }

View file

@ -1,50 +0,0 @@
# Verifies that the configuration suggested in deprecated example values
# will result in the expected output.
import ../make-test-python.nix ({ pkgs, ...} : {
name = "krb5-with-deprecated-config";
meta = with pkgs.lib.maintainers; {
maintainers = [ eqyiel ];
};
nodes.machine =
{ ... }: {
krb5 = {
enable = true;
defaultRealm = "ATHENA.MIT.EDU";
domainRealm = "athena.mit.edu";
kdc = "kerberos.mit.edu";
kerberosAdminServer = "kerberos.mit.edu";
};
};
testScript =
let snapshot = pkgs.writeText "krb5-with-deprecated-config.conf" ''
[libdefaults]
default_realm = ATHENA.MIT.EDU
[realms]
ATHENA.MIT.EDU = {
admin_server = kerberos.mit.edu
kdc = kerberos.mit.edu
}
[domain_realm]
.athena.mit.edu = ATHENA.MIT.EDU
athena.mit.edu = ATHENA.MIT.EDU
[capaths]
[appdefaults]
[plugins]
'';
in ''
machine.succeed(
"diff /etc/krb5.conf ${snapshot}"
)
'';
})

View file

@ -11,79 +11,60 @@ import ../make-test-python.nix ({ pkgs, ...} : {
{ pkgs, ... }: { { pkgs, ... }: {
krb5 = { krb5 = {
enable = true; enable = true;
kerberos = pkgs.krb5; package = pkgs.krb5;
libdefaults = { settings = {
default_realm = "ATHENA.MIT.EDU"; includedir = [
}; "/etc/krb5.conf.d"
realms = { ];
"ATHENA.MIT.EDU" = { include = [
admin_server = "athena.mit.edu"; "/etc/krb5-extra.conf"
kdc = [ ];
"athena01.mit.edu" libdefaults = {
"athena02.mit.edu" default_realm = "ATHENA.MIT.EDU";
]; };
realms = {
"ATHENA.MIT.EDU" = {
admin_server = "athena.mit.edu";
kdc = [
"athena01.mit.edu"
"athena02.mit.edu"
];
};
};
domain_realm = {
"example.com" = "EXAMPLE.COM";
".example.com" = "EXAMPLE.COM";
};
capaths = {
"ATHENA.MIT.EDU" = {
"EXAMPLE.COM" = ".";
};
"EXAMPLE.COM" = {
"ATHENA.MIT.EDU" = ".";
};
};
appdefaults = {
pam = {
debug = false;
ticket_lifetime = 36000;
renew_lifetime = 36000;
max_timeout = 30;
timeout_shift = 2;
initial_timeout = 1;
};
};
plugins.ccselect.disable = "k5identity";
logging = {
kdc = "SYSLOG:NOTICE";
admin_server = "SYSLOG:NOTICE";
default = "SYSLOG:NOTICE";
}; };
}; };
domain_realm = {
"example.com" = "EXAMPLE.COM";
".example.com" = "EXAMPLE.COM";
};
capaths = {
"ATHENA.MIT.EDU" = {
"EXAMPLE.COM" = ".";
};
"EXAMPLE.COM" = {
"ATHENA.MIT.EDU" = ".";
};
};
appdefaults = {
pam = {
debug = false;
ticket_lifetime = 36000;
renew_lifetime = 36000;
max_timeout = 30;
timeout_shift = 2;
initial_timeout = 1;
};
};
plugins = {
ccselect = {
disable = "k5identity";
};
};
extraConfig = ''
[logging]
kdc = SYSLOG:NOTICE
admin_server = SYSLOG:NOTICE
default = SYSLOG:NOTICE
'';
}; };
}; };
testScript = testScript =
let snapshot = pkgs.writeText "krb5-with-example-config.conf" '' let snapshot = pkgs.writeText "krb5-with-example-config.conf" ''
[libdefaults]
default_realm = ATHENA.MIT.EDU
[realms]
ATHENA.MIT.EDU = {
admin_server = athena.mit.edu
kdc = athena01.mit.edu
kdc = athena02.mit.edu
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
[capaths]
ATHENA.MIT.EDU = {
EXAMPLE.COM = .
}
EXAMPLE.COM = {
ATHENA.MIT.EDU = .
}
[appdefaults] [appdefaults]
pam = { pam = {
debug = false debug = false
@ -94,15 +75,40 @@ import ../make-test-python.nix ({ pkgs, ...} : {
timeout_shift = 2 timeout_shift = 2
} }
[capaths]
ATHENA.MIT.EDU = {
EXAMPLE.COM = .
}
EXAMPLE.COM = {
ATHENA.MIT.EDU = .
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
[libdefaults]
default_realm = ATHENA.MIT.EDU
[logging]
admin_server = SYSLOG:NOTICE
default = SYSLOG:NOTICE
kdc = SYSLOG:NOTICE
[plugins] [plugins]
ccselect = { ccselect = {
disable = k5identity disable = k5identity
} }
[logging] [realms]
kdc = SYSLOG:NOTICE ATHENA.MIT.EDU = {
admin_server = SYSLOG:NOTICE admin_server = athena.mit.edu
default = SYSLOG:NOTICE kdc = athena01.mit.edu
kdc = athena02.mit.edu
}
include /etc/krb5-extra.conf
includedir /etc/krb5.conf.d
''; '';
in '' in ''
machine.succeed( machine.succeed(

View file

@ -1,15 +1,17 @@
import ../make-test-python.nix ({ pkgs, lib, ... }: import ../make-test-python.nix ({ pkgs, lib, ... }:
let let
krb5 = krb5 = {
{ enable = true; enable = true;
domain_realm."nfs.test" = "NFS.TEST"; settings = {
domain_realm."nfs.test" = "NFS.TEST";
libdefaults.default_realm = "NFS.TEST"; libdefaults.default_realm = "NFS.TEST";
realms."NFS.TEST" = realms."NFS.TEST" = {
{ admin_server = "server.nfs.test"; admin_server = "server.nfs.test";
kdc = "server.nfs.test"; kdc = "server.nfs.test";
}; };
}; };
};
hosts = hosts =
'' ''