2023-05-16 22:40:08 -07:00
|
|
|
{ config, pkgs, ... }:
|
2021-12-12 16:49:47 -08:00
|
|
|
|
2023-05-16 22:40:08 -07:00
|
|
|
with pkgs.lib;
|
2021-12-12 16:49:47 -08:00
|
|
|
let
|
|
|
|
hostname = config.instance.hostname;
|
2021-12-18 12:10:42 -08:00
|
|
|
domain-name = config.fudo.services.auth.domain;
|
2021-12-12 16:49:47 -08:00
|
|
|
domain = config.fudo.domains.${domain-name};
|
|
|
|
|
2023-05-16 22:40:08 -07:00
|
|
|
realm = domain.gssapi-realm;
|
|
|
|
|
2022-03-16 09:49:35 -07:00
|
|
|
zone-name = domain.zone;
|
|
|
|
|
2021-12-12 16:49:47 -08:00
|
|
|
ldap-server = elem hostname domain.ldap-servers;
|
|
|
|
|
|
|
|
kerberos-master = hostname == domain.kerberos-master;
|
|
|
|
kerberos-slave = elem hostname domain.kerberos-slaves;
|
|
|
|
|
|
|
|
kerberized-domain = domain.kerberos-master != null;
|
|
|
|
|
2021-12-18 12:10:42 -08:00
|
|
|
optionalOrNull = pred: val: if pred then val else null;
|
|
|
|
|
|
|
|
cfg = config.fudo.services.auth;
|
|
|
|
|
2023-05-16 22:40:08 -07:00
|
|
|
host-secrets = config.fudo.secrets.host-secrets."${hostname}";
|
|
|
|
|
|
|
|
krb-user = config.fudo.auth.kerberos.user;
|
|
|
|
krb-group = config.fudo.auth.kerberos.group;
|
|
|
|
|
2021-12-12 16:49:47 -08:00
|
|
|
in {
|
|
|
|
options.fudo.services.auth = with types; {
|
2021-12-18 12:10:42 -08:00
|
|
|
domain = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Domain for which authentication server will operate.";
|
|
|
|
default = config.fudo.hosts.${hostname}.domain;
|
|
|
|
};
|
|
|
|
|
2021-12-12 16:49:47 -08:00
|
|
|
ldap = {
|
|
|
|
hostname = mkOption {
|
|
|
|
type = str;
|
2023-05-16 22:40:08 -07:00
|
|
|
description =
|
|
|
|
"Fully-qualified (and public-addressable) domain name of this host.";
|
2021-12-12 16:49:47 -08:00
|
|
|
default = config.instance.host-fqdn;
|
|
|
|
};
|
|
|
|
|
|
|
|
state-directory = mkOption {
|
|
|
|
type = str;
|
2023-05-16 22:40:08 -07:00
|
|
|
description =
|
|
|
|
"Directory at which to store peristent ldap-related data.";
|
2021-12-12 16:49:47 -08:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
kerberos = {
|
|
|
|
hostname = mkOption {
|
|
|
|
type = str;
|
2023-05-16 22:40:08 -07:00
|
|
|
description =
|
|
|
|
"Fully-qualified (and public-addressable) domain name of this host.";
|
2021-12-12 16:49:47 -08:00
|
|
|
default = config.instance.host-fqdn;
|
|
|
|
};
|
|
|
|
|
|
|
|
state-directory = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Directory at which to store peristent KDC-related data.";
|
|
|
|
};
|
|
|
|
|
|
|
|
master-key-file = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Path (on the build server) to the KDC master key file.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2022-03-16 09:49:35 -07:00
|
|
|
config = {
|
2023-05-16 22:40:08 -07:00
|
|
|
systemd = {
|
|
|
|
tmpfiles.rules = mkIf (kerberos-master || kerberos-slave) [
|
|
|
|
"d ${cfg.kerberos.state-directory} 0700 ${krb-user} ${krb-group} - -"
|
|
|
|
];
|
|
|
|
|
|
|
|
paths.heimdal-kdc-initialize = mkIf kerberos-master {
|
|
|
|
wantedBy = [ "heimdal-kdc.service" ];
|
|
|
|
pathConfig = {
|
|
|
|
PathModified = host-secrets.kdc-principals.target-file;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
services = {
|
2023-11-13 10:59:41 -08:00
|
|
|
heimdal-kdc-initialize = mkIf (kerberos-master || kerberos-slave) (let
|
|
|
|
db = config.fudo.auth.kerberos.kdc.database;
|
|
|
|
principals = host-secrets.kdc-principals.target-file;
|
|
|
|
master-key = host-secrets.realm-master-key.target-file;
|
|
|
|
in {
|
2023-05-16 22:40:08 -07:00
|
|
|
requires = [
|
|
|
|
host-secrets.kdc-principals.service
|
|
|
|
host-secrets.realm-master-key.service
|
|
|
|
];
|
2023-10-15 21:31:16 -07:00
|
|
|
after = [
|
|
|
|
host-secrets.kdc-principals.service
|
|
|
|
host-secrets.realm-master-key.service
|
|
|
|
];
|
2023-05-16 22:40:08 -07:00
|
|
|
description = "Initialize and update the Heimdal KDC database.";
|
|
|
|
path = with pkgs; [ kdcMergePrincipals coreutils ];
|
2023-11-13 10:59:41 -08:00
|
|
|
serviceConfig = {
|
2023-05-16 22:40:08 -07:00
|
|
|
User = krb-user;
|
|
|
|
Group = krb-group;
|
2023-11-13 10:59:41 -08:00
|
|
|
Type = "oneshot";
|
2023-05-16 22:40:08 -07:00
|
|
|
ExecStart = let
|
|
|
|
init-db-cmd = concatStringsSep " " [
|
|
|
|
"${pkgs.kdcMergePrincipals}/bin/kdc-merge-principals"
|
|
|
|
"--create"
|
|
|
|
"--database=${db}"
|
|
|
|
"--principals=${principals}"
|
|
|
|
"--key=${master-key}"
|
|
|
|
"--realm=${realm}"
|
|
|
|
"--verbose"
|
|
|
|
];
|
2023-10-14 16:15:26 -07:00
|
|
|
script = pkgs.writeShellScript "heimdal-kdc-initialize.sh" ''
|
|
|
|
chown ${krb-user}:${krb-group} ${db}
|
|
|
|
chmod 0700 ${db}
|
|
|
|
${init-db-cmd}
|
|
|
|
'';
|
|
|
|
in "+${script}";
|
2023-05-16 22:40:08 -07:00
|
|
|
};
|
2023-10-15 21:31:16 -07:00
|
|
|
unitConfig.ConditionPathExists = [ db principals master-key ];
|
2023-11-13 10:59:41 -08:00
|
|
|
});
|
2023-05-16 22:40:08 -07:00
|
|
|
heimdal-kdc = mkIf kerberos-master {
|
|
|
|
requires = [ "heimdal-kdc-initialize.service" ];
|
|
|
|
after = [ "heimdal-kdc-initialize.service" ];
|
|
|
|
};
|
|
|
|
heimdal-kdc-secondary = mkIf kerberos-slave {
|
|
|
|
requires = [ "heimdal-kdc-initialize.service" ];
|
|
|
|
after = [ "heimdal-kdc-initialize.service" ];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2022-03-16 09:49:35 -07:00
|
|
|
fudo = {
|
|
|
|
acme.host-domains.${hostname} = mkIf (ldap-server) {
|
|
|
|
${cfg.ldap.hostname}.local-copies.openldap = {
|
|
|
|
user = config.services.openldap.user;
|
|
|
|
part-of = [ config.fudo.auth.ldap-server.systemd-target ];
|
|
|
|
};
|
2021-12-12 16:49:47 -08:00
|
|
|
};
|
|
|
|
|
2023-05-16 22:40:08 -07:00
|
|
|
secrets.host-secrets."${hostname}" = let
|
|
|
|
realm-key =
|
|
|
|
config.fudo.secrets.files.kerberos.realm-master-keys."${realm}";
|
|
|
|
in {
|
|
|
|
realm-master-key = mkIf (kerberos-master || kerberos-slave) {
|
|
|
|
source-file = realm-key;
|
|
|
|
target-file = "/run/kdc/realm.key";
|
|
|
|
user = krb-user;
|
|
|
|
group = krb-group;
|
|
|
|
};
|
|
|
|
|
|
|
|
kdc-principals = mkIf (kerberos-master || kerberos-slave) {
|
|
|
|
source-file =
|
|
|
|
config.fudo.secrets.files.kerberos.realm-principals."${realm}";
|
|
|
|
target-file = "/run/kdc/realm.principals";
|
|
|
|
user = krb-user;
|
|
|
|
group = krb-group;
|
|
|
|
};
|
|
|
|
kadmind-keytab = mkIf kerberos-master {
|
|
|
|
source-file = extractFudoKeytab {
|
|
|
|
inherit realm;
|
|
|
|
principals = [ "kadmin/admin" ];
|
|
|
|
};
|
|
|
|
target-file = "/run/kdc/kadmind.keytab";
|
|
|
|
user = krb-user;
|
|
|
|
group = krb-group;
|
|
|
|
};
|
|
|
|
kpasswdd-keytab = mkIf kerberos-master {
|
|
|
|
source-file = extractFudoKeytab {
|
|
|
|
inherit realm;
|
|
|
|
principals = [ "kadmin/changepw" ];
|
|
|
|
};
|
|
|
|
target-file = "/run/kdc/kpasswdd.keytab";
|
|
|
|
user = krb-user;
|
|
|
|
group = krb-group;
|
|
|
|
};
|
|
|
|
hprop-keytab =
|
|
|
|
mkIf (kerberos-master && (domain.kerberos-slaves != [ ])) {
|
|
|
|
source-file = extractFudoKeytab {
|
|
|
|
inherit realm;
|
|
|
|
principals = [ "kadmin/hprop" ];
|
2022-03-16 09:49:35 -07:00
|
|
|
};
|
2023-05-16 22:40:08 -07:00
|
|
|
target-file = "/run/kdc/hprop.keytab";
|
|
|
|
user = krb-user;
|
|
|
|
group = krb-group;
|
2022-03-16 09:49:35 -07:00
|
|
|
};
|
2023-05-16 22:40:08 -07:00
|
|
|
|
|
|
|
hpropd-keytab = mkIf kerberos-slave {
|
|
|
|
source-file = extractFudoHostKeytab {
|
|
|
|
inherit hostname realm;
|
|
|
|
services = [ "hprop" ];
|
|
|
|
};
|
|
|
|
target-file = "/run/kdc/hpropd.keytab";
|
|
|
|
user = krb-user;
|
|
|
|
group = krb-group;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
auth = {
|
|
|
|
ldap-server = mkIf ldap-server (let
|
|
|
|
ldap-cert-copy =
|
|
|
|
config.fudo.acme.host-domains.${hostname}.${cfg.ldap.hostname}.local-copies.openldap;
|
|
|
|
in {
|
|
|
|
enable = ldap-server;
|
|
|
|
base = "dc=fudo,dc=org";
|
|
|
|
organization = "Fudo";
|
|
|
|
listen-uris = [ "ldap:///" "ldaps:///" ];
|
|
|
|
required-services = [ ldap-cert-copy.service ];
|
|
|
|
|
|
|
|
# TODO: Maybe filter to Fudo-only?
|
|
|
|
users = config.fudo.users;
|
|
|
|
groups = config.fudo.groups;
|
|
|
|
system-users = config.fudo.system-users;
|
|
|
|
|
|
|
|
state-directory = "${cfg.ldap.state-directory}";
|
|
|
|
|
|
|
|
ssl-chain = ldap-cert-copy.chain;
|
|
|
|
ssl-certificate = ldap-cert-copy.certificate;
|
|
|
|
ssl-private-key = ldap-cert-copy.private-key;
|
|
|
|
ssl-ca-certificate = "${pkgs.letsencrypt-ca}";
|
|
|
|
});
|
|
|
|
|
|
|
|
kerberos = {
|
|
|
|
inherit realm;
|
|
|
|
kdc = mkIf (kerberos-master || kerberos-slave) {
|
|
|
|
state-directory = cfg.kerberos.state-directory;
|
|
|
|
master-key-file = host-secrets.realm-master-key.target-file;
|
|
|
|
primary = mkIf kerberos-master {
|
|
|
|
enable = true;
|
|
|
|
acl = let
|
|
|
|
adminEntries = genAttrs config.instance.local-admins
|
|
|
|
(admin: { perms = [ "add" "change-password" "list" ]; });
|
|
|
|
in adminEntries // { "*/root".perms = [ "all" ]; };
|
|
|
|
secondary-servers = map getHostFqdn domain.kerberos-slaves;
|
|
|
|
keytabs = {
|
|
|
|
kadmind = host-secrets.kadmind-keytab.target-file;
|
|
|
|
kpasswdd = host-secrets.kpasswdd-keytab.target-file;
|
|
|
|
hprop = host-secrets.hprop-keytab.target-file;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
secondary = mkIf kerberos-slave {
|
|
|
|
enable = true;
|
|
|
|
keytabs.hpropd = host-secrets.hpropd-keytab.target-file;
|
|
|
|
};
|
2021-12-12 16:49:47 -08:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-10-14 16:15:26 -07:00
|
|
|
zones."${zone-name}" = let
|
2022-03-16 09:49:35 -07:00
|
|
|
make-srv-record = port: hostname: {
|
|
|
|
port = port;
|
|
|
|
host = hostname;
|
|
|
|
};
|
2021-12-12 16:49:47 -08:00
|
|
|
|
2023-05-16 22:40:08 -07:00
|
|
|
get-fqdn = host: "${host}.${config.fudo.hosts.${host}.domain}";
|
2021-12-12 16:49:47 -08:00
|
|
|
|
2023-05-16 22:40:08 -07:00
|
|
|
kerberos-master-hosts =
|
|
|
|
optional (kerberized-domain) domain.kerberos-master;
|
2021-12-12 16:49:47 -08:00
|
|
|
|
2023-05-16 22:40:08 -07:00
|
|
|
kerberos-servers =
|
|
|
|
map get-fqdn (kerberos-master-hosts ++ domain.kerberos-slaves);
|
2021-12-12 16:49:47 -08:00
|
|
|
|
2022-03-16 09:49:35 -07:00
|
|
|
kerberos-masters = map get-fqdn kerberos-master-hosts;
|
2021-12-12 16:49:47 -08:00
|
|
|
|
2022-03-16 09:49:35 -07:00
|
|
|
ldap-servers = map get-fqdn domain.ldap-servers;
|
|
|
|
in {
|
2023-05-16 22:40:08 -07:00
|
|
|
gssapi-realm = realm;
|
|
|
|
|
2022-03-16 09:49:35 -07:00
|
|
|
srv-records = {
|
|
|
|
tcp = {
|
|
|
|
kerberos = map (make-srv-record 88) kerberos-servers;
|
|
|
|
kerberos-adm = map (make-srv-record 749) kerberos-masters;
|
|
|
|
ldap = map (make-srv-record 389) ldap-servers;
|
|
|
|
ldaps = map (make-srv-record 636) ldap-servers;
|
|
|
|
};
|
2021-12-12 16:49:47 -08:00
|
|
|
|
2022-03-16 09:49:35 -07:00
|
|
|
udp = {
|
|
|
|
kerberos = map (make-srv-record 88) kerberos-servers;
|
|
|
|
kerberos-master = map (make-srv-record 88) kerberos-masters;
|
|
|
|
kpasswd = map (make-srv-record 464) kerberos-masters;
|
|
|
|
};
|
2021-12-12 16:49:47 -08:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|