diff --git a/hosts/dagali/TODO.md b/hosts/dagali/TODO.md
new file mode 100644
index 0000000..f134ca6
--- /dev/null
+++ b/hosts/dagali/TODO.md
@@ -0,0 +1,63 @@
+# Tracking document for new PVV kerberos auth stack
+
+![Bensinstasjon på heimdal](https://bydelsnytt.no/wp-content/uploads/2022/08/esso_heimdal003.jpg)
+
+
+ Bensinstasjon på heimdal
+
+
+### TODO:
+
+- [ ] setup heimdal
+ - [x] ensure running with systemd
+ - [x] compile smbk5pwd (part of openldap)
+ - [ ] set `modify -a -disallow-all-tix,requires-pre-auth default` declaratively
+ - [ ] fully initialize PVV.NTNU.NO
+ - [x] `kadmin -l init PVV.NTNU.NO`
+ - [x] add oysteikt/admin@PVV.NTNU.NO principal
+ - [x] add oysteikt@PVV.NTNU.NO principal
+ - [ ] add krbtgt@PVV.NTNU.NO principal?
+ - why is this needed, and where is it documented?
+ - `kadmin check` seems to work under sudo?
+ - Fix FQDN: https://github.com/NixOS/nixpkgs/issues/94011
+ https://github.com/NixOS/nixpkgs/issues/261269
+
+- [ ] setup cyrus sasl
+ - [x] ensure running with systemd
+ - [x] verify GSSAPI support plugin is installed
+ - `nix-shell -p cyrus_sasl --command pluginviewer`
+ - [x] create "host/localhost@PVV.NTNU.NO" and export to keytab
+ - [x] verify cyrus sasl is able to talk to heimdal
+ - `sudo testsaslauthd -u oysteikt -p `
+ - [ ] provide ldap principal to cyrus sasl through keytab
+
+- [ ] setup openldap
+ - [x] ensure running with systemd
+ - [ ] verify openldap is able to talk to cyrus sasl
+ - [ ] create user for oysteikt in openldap
+ - [ ] authenticate openldap login through sasl
+ - does this require creating an ldap user?
+
+- [ ] fix smbk5pwd integration
+ - [x] add smbk5pwd schemas to openldap
+ - [x] create openldap db for smbk5pwd with overlays
+ - [ ] test to ensure that user sync is working
+ - [ ] test as user source (replace passwd)
+ - [ ] test as PAM auth source
+ - [ ] test as auth source for 3rd party appliation
+
+- [ ] Set up ldap administration panel
+ - Doesn't seem like there are many good ones out there. Maybe phpLDAPAdmin?
+
+- [ ] Set up kerberos SRV DNS entry
+
+### Information and URLS
+
+- OpenLDAP SASL: https://www.openldap.org/doc/admin24/sasl.html
+- Use a keytab: https://kb.iu.edu/d/aumh
+- 2 ways for openldap to auth: https://security.stackexchange.com/questions/65093/how-to-test-ldap-that-authenticates-with-kerberos
+- Cyrus guide OpenLDAP + SASL + GSSAPI: https://www.cyrusimap.org/sasl/sasl/faqs/openldap-sasl-gssapi.html
+- Configuring GSSAPI and Cyrus SASL: https://web.mit.edu/darwin/src/modules/passwordserver_sasl/cyrus_sasl/doc/gssapi.html
+- PVV Kerberos docs: https://wiki.pvv.ntnu.no/wiki/Drift/Kerberos
+- OpenLDAP smbk5pwd source: https://git.openldap.org/nivanova/openldap/-/tree/master/contrib/slapd-modules/smbk5pwd
+- saslauthd(8): https://linux.die.net/man/8/saslauthd
diff --git a/hosts/dagali/configuration.nix b/hosts/dagali/configuration.nix
index 499d3b6..5c64273 100644
--- a/hosts/dagali/configuration.nix
+++ b/hosts/dagali/configuration.nix
@@ -5,6 +5,10 @@
./hardware-configuration.nix
../../base.nix
../../misc/metrics-exporters.nix
+
+ ./services/heimdal.nix
+ ./services/openldap.nix
+ ./services/cyrus-sasl.nix
];
# buskerud does not support efi?
@@ -13,6 +17,9 @@
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/sda";
+ # resolved messes up FQDN coming from nscd
+ services.resolved.enable = false;
+
networking.hostName = "dagali";
networking.search = [ "pvv.ntnu.no" "pvv.org" ];
networking.nameservers = [ "129.241.0.200" "129.241.0.201" ];
diff --git a/hosts/dagali/services/cyrus-sasl.nix b/hosts/dagali/services/cyrus-sasl.nix
new file mode 100644
index 0000000..c9c8a28
--- /dev/null
+++ b/hosts/dagali/services/cyrus-sasl.nix
@@ -0,0 +1,21 @@
+{ config, ... }:
+let
+ cfg = config.services.saslauthd;
+in
+{
+ # TODO: This is seemingly required for openldap to authenticate
+ # against kerberos, but I have no idea how to configure it as
+ # such. Does it need a keytab? There's a binary "testsaslauthd"
+ # that follows with `pkgs.cyrus_sasl` that might be useful.
+ services.saslauthd = {
+ enable = true;
+ mechanism = "kerberos5";
+ config = ''
+ mech_list: gs2-krb5 gssapi
+ keytab: /etc/krb5.keytab
+ '';
+ };
+
+ # TODO: maybe the upstream module should consider doing this?
+ environment.systemPackages = [ cfg.package ];
+}
diff --git a/hosts/dagali/services/heimdal.nix b/hosts/dagali/services/heimdal.nix
new file mode 100644
index 0000000..0b07e2e
--- /dev/null
+++ b/hosts/dagali/services/heimdal.nix
@@ -0,0 +1,80 @@
+{ config, pkgs, lib, ... }:
+let
+
+ realm = "PVV.NTNU.NO";
+
+ cfg = config.security.krb5;
+in
+{
+ security.krb5 = {
+ enable = true;
+
+ # NOTE: This has a small edit that moves an include header to $dev/include.
+ # It is required in order to build smbk5pwd, because of some nested includes.
+ # We should open an issue upstream (heimdal, not nixpkgs), but this patch
+ # will do for now.
+ # package = pkgs.callPackage ./package.nix {
+ # inherit (pkgs.apple_sdk.frameworks)
+ # CoreFoundation Security SystemConfiguration;
+ # };
+ package = pkgs.heimdal.overrideAttrs (prev: {
+ postInstall = prev.postInstall + ''
+ cp include/heim_threads.h $dev/include
+ '';
+ });
+
+ settings = {
+ # logging.kdc = "CONSOLE";
+ realms.${realm} = {
+ admin_server = "dagali.pvv.ntnu.no";
+ kdc = [ "localhost" ];
+ };
+
+ kadmin.default_keys = lib.concatStringsSep " " [
+ "aes256-cts-hmac-sha1-96:pw-salt"
+ "aes128-cts-hmac-sha1-96:pw-salt"
+ ];
+
+ libdefaults.default_etypes = lib.concatStringsSep " " [
+ "aes256-cts-hmac-sha1-96"
+ "aes128-cts-hmac-sha1-96"
+ ];
+
+ libdefaults = {
+ default_realm = realm;
+ };
+
+ domain_realm = {
+ "pvv.ntnu.no" = realm;
+ ".pvv.ntnu.no" = realm;
+ };
+
+ logging = {
+ kdc = "SYSLOG:DEBUG:AUTH";
+ admin_server = "SYSLOG:DEBUG:AUTH";
+ default = "SYSLOG:DEBUG:AUTH";
+ };
+ };
+ };
+
+ services.kerberos_server = {
+ enable = true;
+ settings = {
+ realms.${realm} = {
+ dbname = "/var/heimdal/heimdal";
+ mkey = "/var/heimdal/mkey";
+ };
+ # kadmin.default_keys = lib.concatStringsSep " " [
+ # "aes256-cts-hmac-sha1-96:pw-salt"
+ # "aes128-cts-hmac-sha1-96:pw-salt"
+ # ];
+
+ # libdefaults.default_etypes = lib.concatStringsSep " " [
+ # "aes256-cts-hmac-sha1-96"
+ # "aes128-cts-hmac-sha1-96"
+ # ];
+
+ # password_quality.min_length = 8;
+ };
+ };
+}
diff --git a/hosts/dagali/services/openldap.nix b/hosts/dagali/services/openldap.nix
new file mode 100644
index 0000000..5d8fca1
--- /dev/null
+++ b/hosts/dagali/services/openldap.nix
@@ -0,0 +1,121 @@
+{ config, pkgs, lib, ... }:
+{
+ services.openldap = let
+ dn = "dc=kerberos,dc=pvv,dc=ntnu,dc=no";
+ cfg = config.services.openldap;
+
+ heimdal = config.security.krb5.package;
+ in {
+ enable = true;
+
+ # NOTE: this is a custom build of openldap with support for
+ # perl and kerberos.
+ package = pkgs.openldap.overrideAttrs (prev: {
+ # https://github.com/openldap/openldap/blob/master/configure
+ configureFlags = prev.configureFlags ++ [
+ # Connect to slapd via UNIX socket
+ "--enable-local"
+ # Cyrus SASL
+ "--enable-spasswd"
+ # Reverse hostname lookups
+ "--enable-rlookups"
+ # perl
+ "--enable-perl"
+ ];
+
+ buildInputs = prev.buildInputs ++ [
+ pkgs.perl
+ # NOTE: do not upstream this, it might not work with
+ # MIT in the same way
+ heimdal
+ ];
+
+ extraContribModules = prev.extraContribModules ++ [
+ # https://git.openldap.org/openldap/openldap/-/tree/master/contrib/slapd-modules
+ "smbk5pwd"
+ ];
+ });
+
+ settings = {
+ attrs = {
+ olcLogLevel = [ "stats" "config" "args" ];
+
+ # olcAuthzRegexp = ''
+ # gidNumber=.*\\\+uidNumber=0,cn=peercred,cn=external,cn=auth
+ # "uid=heimdal,${dn2}"
+ # '';
+
+ # olcSaslSecProps = "minssf=0";
+ };
+
+ children = {
+ "cn=schema".includes = let
+ # NOTE: needed for smbk5pwd.so module
+ schemaToLdif = name: path: pkgs.runCommandNoCC name {
+ buildInputs = with pkgs; [ schema2ldif ];
+ } ''
+ schema2ldif "${path}" > $out
+ '';
+
+ hdb-ldif = schemaToLdif "hdb.ldif" "${heimdal.src}/lib/hdb/hdb.schema";
+ samba-ldif = schemaToLdif "samba.ldif" "${heimdal.src}/tests/ldap/samba.schema";
+ in [
+ "${cfg.package}/etc/schema/core.ldif"
+ "${cfg.package}/etc/schema/cosine.ldif"
+ "${cfg.package}/etc/schema/nis.ldif"
+ "${cfg.package}/etc/schema/inetorgperson.ldif"
+ "${hdb-ldif}"
+ "${samba-ldif}"
+ ];
+
+ # NOTE: installation of smbk5pwd.so module
+ # https://git.openldap.org/openldap/openldap/-/tree/master/contrib/slapd-modules/smbk5pwd
+ "cn=module{0}".attrs = {
+ objectClass = [ "olcModuleList" ];
+ olcModuleLoad = [ "${cfg.package}/lib/modules/smbk5pwd.so" ];
+ };
+
+ # NOTE: activation of smbk5pwd.so module for {1}mdb
+ "olcOverlay={0}smbk5pwd,olcDatabase={1}mdb".attrs = {
+ objectClass = [ "olcOverlayConfig" "olcSmbK5PwdConfig" ];
+ olcOverlay = "{0}smbk5pwd";
+ olcSmbK5PwdEnable = [ "krb5" "samba" ];
+ olcSmbK5PwdMustChange = toString (60 * 60 * 24 * 30);
+ };
+
+ "olcDatabase={1}mdb".attrs = {
+ objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ];
+
+ olcDatabase = "{1}mdb";
+
+ olcSuffix = dn;
+
+ # TODO: PW is supposed to be a secret, but it's probably fine for testing
+ olcRootDN = "cn=admin,${dn}";
+
+ # TODO: replace with proper secret
+ olcRootPW.path = pkgs.writeText "olcRootPW" "pass";
+
+ olcDbDirectory = "/var/lib/openldap/test-smbk5pwd-db";
+ olcDbIndex = "objectClass eq";
+
+ olcAccess = [
+ ''{0}to attrs=userPassword,shadowLastChange
+ by dn.exact=cn=admin,${dn} write
+ by self write
+ by anonymous auth
+ by * none''
+
+ ''{1}to dn.base=""
+ by * read''
+
+ /* allow read on anything else */
+ # ''{2}to *
+ # by cn=admin,${dn} write by dn.exact=gidNumber=0+uidNumber=0+cn=peercred,cn=external write
+ # by * read''
+ ];
+ };
+ };
+ };
+ };
+}