{ config, lib, pkgs, ... }: with lib; let hostname = config.instance.hostname; domain-name = config.fudo.services.auth.domain; domain = config.fudo.domains.${domain-name}; 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; optionalOrNull = pred: val: if pred then val else null; cfg = config.fudo.services.auth; in { options.fudo.services.auth = with types; { domain = mkOption { type = str; description = "Domain for which authentication server will operate."; default = config.fudo.hosts.${hostname}.domain; }; ldap = { hostname = mkOption { type = str; description = "Fully-qualified (and public-addressable) domain name of this host."; default = config.instance.host-fqdn; }; state-directory = mkOption { type = str; description = "Directory at which to store peristent ldap-related data."; }; }; kerberos = { hostname = mkOption { type = str; description = "Fully-qualified (and public-addressable) domain name of this host."; 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."; }; ipropd-keytab = mkOption { type = nullOr str; description = "ipropd keytab for kerberos database propagation."; }; }; }; config.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 ]; }; }; 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}"; }); kdc = mkIf (kerberos-master || kerberos-slave) { enable = true; realm = domain.gssapi-realm; bind-addresses = (pkgs.lib.network.host-ips config hostname) ++ [ "127.0.0.1" ] ++ (optional config.networking.enableIPv6 "::1"); state-directory = cfg.kerberos.state-directory; master-key-file = cfg.kerberos.master-key-file; master-config = mkIf (kerberos-master) { acl = let admin-entries = genAttrs config.instance.local-admins (admin: { perms = [ "add" "change-password" "list" ]; }); in admin-entries // { "*/root".perms = [ "all" ]; }; }; slave-config = mkIf (kerberos-slave) { master-host = domain.kerberos-master; ipropd-keytab = cfg.kerberos.ipropd-keytab; }; }; }; dns.domains.${domain-name} = let make-srv-record = port: hostname: { port = port; host = hostname; }; get-fqdn = host: "${host}.${config.fudo.hosts.${host}.domain}"; kerberos-masters = optional (kerberized-domain) domain.kerberos-master; kerberos-servers = map get-fqdn (kerberos-masters ++ domain.kerberos-slaves); master-servers = map get-fqdn kerberos-masters; ldap-servers = map get-fqdn domain.ldap-servers; in { zone-definition.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; }; 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; }; }; }; }; }