mirror of
https://git.pvv.ntnu.no/Drift/pvv-nixos-config.git
synced 2025-12-13 05:37:14 +01:00
WIP: init buskerud/salsa
This commit is contained in:
101
hosts/buskerud/containers/salsa/modules/kerberos/default.nix
Normal file
101
hosts/buskerud/containers/salsa/modules/kerberos/default.nix
Normal file
@@ -0,0 +1,101 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
cfg = config.services.kerberos_server;
|
||||
inherit (config.security.krb5) package;
|
||||
|
||||
format = import ../krb5/krb5-conf-format.nix { inherit pkgs lib; } { };
|
||||
in
|
||||
|
||||
{
|
||||
imports = [
|
||||
(lib.mkRenamedOptionModule [ "services" "kerberos_server" "realms" ] [ "services" "kerberos_server" "settings" "realms" ])
|
||||
|
||||
./mit.nix
|
||||
./heimdal.nix
|
||||
];
|
||||
|
||||
options = {
|
||||
services.kerberos_server = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "the kerberos authentication server");
|
||||
|
||||
settings = let
|
||||
aclEntry = types.submodule {
|
||||
options = {
|
||||
principal = mkOption {
|
||||
type = types.str;
|
||||
description = lib.mdDoc "Which principal the rule applies to";
|
||||
};
|
||||
access = mkOption {
|
||||
type = types.either
|
||||
(types.listOf (types.enum ["add" "cpw" "delete" "get" "list" "modify"]))
|
||||
(types.enum ["all"]);
|
||||
default = "all";
|
||||
description = lib.mdDoc "The changes the principal is allowed to make.";
|
||||
};
|
||||
target = mkOption {
|
||||
type = types.str;
|
||||
default = "*";
|
||||
description = lib.mdDoc "The principals that 'access' applies to.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
realm = types.submodule ({ name, ... }: {
|
||||
freeformType = format.sectionType;
|
||||
options = {
|
||||
acl = mkOption {
|
||||
type = types.listOf aclEntry;
|
||||
default = [
|
||||
{ principal = "*/admin"; access = "all"; }
|
||||
{ principal = "admin"; access = "all"; }
|
||||
];
|
||||
description = lib.mdDoc ''
|
||||
The privileges granted to a user.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
in mkOption {
|
||||
type = types.submodule (format.type.getSubModules ++ [{
|
||||
options = {
|
||||
realms = mkOption {
|
||||
type = types.attrsOf realm;
|
||||
description = lib.mdDoc ''
|
||||
The realm(s) to serve keys for.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}]);
|
||||
description = ''
|
||||
Settings for the kerberos server of choice.
|
||||
|
||||
See the following documentation:
|
||||
- Heimdal: {manpage}`kdc.conf(5)`
|
||||
- MIT Kerberos: <https://web.mit.edu/kerberos/krb5-1.21/doc/admin/conf_files/kdc_conf.html>
|
||||
'';
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ package ];
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.settings.realms != { };
|
||||
message = "The server needs at least one realm";
|
||||
}
|
||||
{
|
||||
assertion = lib.length (lib.attrNames cfg.settings.realms) <= 1;
|
||||
message = "Only one realm per server is currently supported.";
|
||||
}
|
||||
];
|
||||
|
||||
systemd.slices.system-kerberos-server = { };
|
||||
systemd.targets.kerberos-server = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
87
hosts/buskerud/containers/salsa/modules/kerberos/heimdal.nix
Normal file
87
hosts/buskerud/containers/salsa/modules/kerberos/heimdal.nix
Normal file
@@ -0,0 +1,87 @@
|
||||
{ pkgs, config, lib, ... } :
|
||||
|
||||
let
|
||||
inherit (lib) mapAttrs;
|
||||
cfg = config.services.kerberos_server;
|
||||
package = config.security.krb5.package;
|
||||
|
||||
aclConfigs = lib.pipe cfg.settings.realms [
|
||||
(mapAttrs (name: { acl, ... }: lib.concatMapStringsSep "\n" (
|
||||
{ principal, access, target, ... }:
|
||||
"${principal}\t${lib.concatStringsSep "," (lib.toList access)}\t${target}"
|
||||
) acl))
|
||||
(lib.mapAttrsToList (name: text:
|
||||
{
|
||||
dbname = "/var/lib/heimdal/heimdal";
|
||||
acl_file = pkgs.writeText "${name}.acl" text;
|
||||
}
|
||||
))
|
||||
];
|
||||
|
||||
finalConfig = cfg.settings // {
|
||||
realms = mapAttrs (_: v: removeAttrs v [ "acl" ]) (cfg.settings.realms or { });
|
||||
kdc = (cfg.settings.kdc or { }) // {
|
||||
database = aclConfigs;
|
||||
};
|
||||
};
|
||||
|
||||
format = import ../krb5/krb5-conf-format.nix { inherit pkgs lib; } { };
|
||||
|
||||
kdcConfFile = format.generate "kdc.conf" finalConfig;
|
||||
in
|
||||
|
||||
{
|
||||
config = lib.mkIf (cfg.enable && package.passthru.implementation == "heimdal") {
|
||||
environment.etc."heimdal-kdc/kdc.conf".source = kdcConfFile;
|
||||
|
||||
systemd.tmpfiles.settings."10-heimdal" = let
|
||||
databases = lib.pipe finalConfig.kdc.database [
|
||||
(map (dbAttrs: dbAttrs.dbname or null))
|
||||
(lib.filter (x: x != null))
|
||||
lib.unique
|
||||
];
|
||||
in lib.genAttrs databases (_: {
|
||||
d = {
|
||||
user = "root";
|
||||
group = "root";
|
||||
mode = "0700";
|
||||
};
|
||||
});
|
||||
|
||||
systemd.services.kadmind = {
|
||||
description = "Kerberos Administration Daemon";
|
||||
partOf = [ "kerberos-server.target" ];
|
||||
wantedBy = [ "kerberos-server.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${package}/libexec/kadmind --config-file=/etc/heimdal-kdc/kdc.conf";
|
||||
Slice = "system-kerberos-server.slice";
|
||||
StateDirectory = "heimdal";
|
||||
};
|
||||
restartTriggers = [ kdcConfFile ];
|
||||
};
|
||||
|
||||
systemd.services.kdc = {
|
||||
description = "Key Distribution Center daemon";
|
||||
partOf = [ "kerberos-server.target" ];
|
||||
wantedBy = [ "kerberos-server.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${package}/libexec/kdc --config-file=/etc/heimdal-kdc/kdc.conf";
|
||||
Slice = "system-kerberos-server.slice";
|
||||
StateDirectory = "heimdal";
|
||||
};
|
||||
restartTriggers = [ kdcConfFile ];
|
||||
};
|
||||
|
||||
systemd.services.kpasswdd = {
|
||||
description = "Kerberos Password Changing daemon";
|
||||
partOf = [ "kerberos-server.target" ];
|
||||
wantedBy = [ "kerberos-server.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${package}/libexec/kpasswdd";
|
||||
Slice = "system-kerberos-server.slice";
|
||||
StateDirectory = "heimdal";
|
||||
};
|
||||
restartTriggers = [ kdcConfFile ];
|
||||
};
|
||||
};
|
||||
}
|
||||
77
hosts/buskerud/containers/salsa/modules/kerberos/mit.nix
Normal file
77
hosts/buskerud/containers/salsa/modules/kerberos/mit.nix
Normal file
@@ -0,0 +1,77 @@
|
||||
{ pkgs, config, lib, ... } :
|
||||
|
||||
let
|
||||
inherit (lib) mapAttrs;
|
||||
cfg = config.services.kerberos_server;
|
||||
package = config.security.krb5.package;
|
||||
PIDFile = "/run/kdc.pid";
|
||||
|
||||
format = import ../krb5/krb5-conf-format.nix { inherit pkgs lib; } { };
|
||||
|
||||
aclMap = {
|
||||
add = "a"; cpw = "c"; delete = "d"; get = "i"; list = "l"; modify = "m";
|
||||
all = "*";
|
||||
};
|
||||
|
||||
aclConfigs = lib.pipe cfg.settings.realms [
|
||||
(mapAttrs (name: { acl, ... }: lib.concatMapStringsSep "\n" (
|
||||
{ principal, access, target, ... }: let
|
||||
access_code = map (a: aclMap.${a}) (lib.toList access);
|
||||
in "${principal} ${lib.concatStrings access_code} ${target}"
|
||||
) acl))
|
||||
|
||||
(lib.concatMapAttrs (name: text: {
|
||||
${name} = {
|
||||
acl_file = pkgs.writeText "${name}.acl" text;
|
||||
};
|
||||
}))
|
||||
];
|
||||
|
||||
finalConfig = cfg.settings // {
|
||||
realms = mapAttrs (n: v: (removeAttrs v [ "acl" ]) // aclConfigs.${n}) (cfg.settings.realms or { });
|
||||
};
|
||||
|
||||
kdcConfFile = format.generate "kdc.conf" finalConfig;
|
||||
env = {
|
||||
# What Debian uses, could possibly link directly to Nix store?
|
||||
KRB5_KDC_PROFILE = "/etc/krb5kdc/kdc.conf";
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
config = lib.mkIf (cfg.enable && package.passthru.implementation == "krb5") {
|
||||
environment = {
|
||||
etc."krb5kdc/kdc.conf".source = kdcConfFile;
|
||||
variables = env;
|
||||
};
|
||||
|
||||
systemd.services.kadmind = {
|
||||
description = "Kerberos Administration Daemon";
|
||||
partOf = [ "kerberos-server.target" ];
|
||||
wantedBy = [ "kerberos-server.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${package}/bin/kadmind -nofork";
|
||||
Slice = "system-kerberos-server.slice";
|
||||
StateDirectory = "krb5kdc";
|
||||
};
|
||||
restartTriggers = [ kdcConfFile ];
|
||||
environment = env;
|
||||
};
|
||||
|
||||
systemd.services.kdc = {
|
||||
description = "Key Distribution Center daemon";
|
||||
partOf = [ "kerberos-server.target" ];
|
||||
wantedBy = [ "kerberos-server.target" ];
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
PIDFile = PIDFile;
|
||||
ExecStart = "${package}/bin/krb5kdc -P ${PIDFile}";
|
||||
Slice = "system-kerberos-server.slice";
|
||||
StateDirectory = "krb5kdc";
|
||||
};
|
||||
restartTriggers = [ kdcConfFile ];
|
||||
environment = env;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
104
hosts/buskerud/containers/salsa/modules/krb5/default.nix
Normal file
104
hosts/buskerud/containers/salsa/modules/krb5/default.nix
Normal file
@@ -0,0 +1,104 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
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
|
||||
`security.krb5.settings.${name}' for structured configuration.
|
||||
'';
|
||||
|
||||
cfg = config.security.krb5;
|
||||
format = import ./krb5-conf-format.nix { inherit pkgs lib; } { };
|
||||
in {
|
||||
imports = [
|
||||
(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 `security.krb5.package'.
|
||||
'')
|
||||
];
|
||||
|
||||
options = {
|
||||
security.krb5 = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = mdDoc "Enable and configure Kerberos utilities";
|
||||
type = bool;
|
||||
};
|
||||
|
||||
package = mkPackageOption pkgs "krb5" {
|
||||
example = "heimdal";
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
realms = {
|
||||
"ATHENA.MIT.EDU" = {
|
||||
admin_server = "athena.mit.edu";
|
||||
kdc = [
|
||||
"athena01.mit.edu"
|
||||
"athena02.mit.edu"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
domain_realm = {
|
||||
"mit.edu" = "ATHENA.MIT.EDU";
|
||||
};
|
||||
|
||||
logging = {
|
||||
kdc = "SYSLOG:NOTICE";
|
||||
admin_server = "SYSLOG:NOTICE";
|
||||
default = "SYSLOG:NOTICE";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
assertions = mkIf (cfg.enable || config.services.kerberos_server.enable) [(let
|
||||
implementation = cfg.package.passthru.implementation or "<NOT SET>";
|
||||
in {
|
||||
assertion = lib.elem implementation [ "krb5" "heimdal" ];
|
||||
message = ''
|
||||
`security.krb5.package` must be one of:
|
||||
|
||||
- krb5
|
||||
- heimdal
|
||||
|
||||
Currently chosen implementation: ${implementation}
|
||||
'';
|
||||
})];
|
||||
|
||||
environment = mkIf cfg.enable {
|
||||
systemPackages = [ cfg.package ];
|
||||
etc."krb5.conf".source = format.generate "krb5.conf" cfg.settings;
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = builtins.attrValues {
|
||||
inherit (lib.maintainers) dblsaiko h7x4;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
{ 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
|
||||
{ }: 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 = submodule {
|
||||
freeformType = attrsOf sectionType;
|
||||
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 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}
|
||||
'';
|
||||
}
|
||||
Reference in New Issue
Block a user