From 1c2ec9ca5d5394940438d1eaa8ab6bb06d8f53c2 Mon Sep 17 00:00:00 2001 From: jaysa Date: Wed, 6 May 2026 11:53:24 -0700 Subject: [PATCH 01/52] eel draft --- hosts/servers/eel.nix | 29 ++++ modules/auth.nix | 2 +- modules/kerberos-server.nix | 65 ++++++++ modules/ldap-server.nix | 214 +++++++++++++++++++++++++ modules/ldap-server/ocf.schema.ldif | 86 ++++++++++ modules/ldap-server/puppet.schema.ldif | 25 +++ 6 files changed, 420 insertions(+), 1 deletion(-) create mode 100644 hosts/servers/eel.nix create mode 100644 modules/kerberos-server.nix create mode 100644 modules/ldap-server.nix create mode 100644 modules/ldap-server/ocf.schema.ldif create mode 100644 modules/ldap-server/puppet.schema.ldif diff --git a/hosts/servers/eel.nix b/hosts/servers/eel.nix new file mode 100644 index 00000000..5cbb077e --- /dev/null +++ b/hosts/servers/eel.nix @@ -0,0 +1,29 @@ +{ + pkgs, + lib, + config, + ... +}: + +{ + imports = [ ../../hardware/virtualized.nix ]; + + networking.hostName = "eel"; + + ocf.network = { + enable = true; + lastOctet = 97; + }; + + ocf.kerberosServer.enable = true; + ocf.ldapServer.enable = true; + + # Cert covers both service names as SANs so ldaps:// and kerberos clients + # connecting to ldap.ocf.berkeley.edu / kerberos.ocf.berkeley.edu are happy + ocf.acme.extraCerts = [ + "ldap.ocf.berkeley.edu" + "kerberos.ocf.berkeley.edu" + ]; + + system.stateVersion = "25.11"; +} diff --git a/modules/auth.nix b/modules/auth.nix index 915de38a..4cc392f2 100644 --- a/modules/auth.nix +++ b/modules/auth.nix @@ -122,7 +122,7 @@ in security.krb5 = { enable = true; - package = pkgs.heimdal; + package = pkgs.krb5; settings = { realms."OCF.BERKELEY.EDU" = { diff --git a/modules/kerberos-server.nix b/modules/kerberos-server.nix new file mode 100644 index 00000000..70cbd657 --- /dev/null +++ b/modules/kerberos-server.nix @@ -0,0 +1,65 @@ +{ + lib, + config, + pkgs, + ... +}: + +let + cfg = config.ocf.kerberosServer; +in +{ + options.ocf.kerberosServer = { + enable = lib.mkEnableOption "OCF Kerberos KDC server (MIT krb5)"; + }; + + config = lib.mkIf cfg.enable { + services.kerberos_server = { + enable = true; + realms."OCF.BERKELEY.EDU" = { + acl = [ + # Staff /admin principals have full KDC access + { + principal = "*/admin"; + access = [ "all" ]; + } + # Staff /root principals can change any principal's password + { + principal = "*/root"; + access = [ "change-password" ]; + target = "*@OCF.BERKELEY.EDU"; + } + # create/admin is used by account creation tooling (ocflib) + { + principal = "create/admin"; + access = [ + "add" + "get" + "change-password" + ]; + target = "*@OCF.BERKELEY.EDU"; + } + ]; + }; + }; + + # TODO: port the password quality check to MIT krb5. + # Firestorm used Heimdal's external-check interface + # (modules/ocf_kerberos/files/check-pass-strength, backed by ocflib validators). + # MIT krb5 requires a pwqual shared-library plugin instead — the script logic + # can be kept but needs a C wrapper that implements the MIT pwqual API. + + environment.systemPackages = [ pkgs.krb5 ]; + + # Ensure the KDC state directory exists before agenix deploys secrets into it + systemd.tmpfiles.rules = [ + "d /var/lib/krb5kdc 0700 root root -" + ]; + + # The KDC database lives in /var/lib/krb5kdc/ and must be initialized manually: + # kdb5_util create -r OCF.BERKELEY.EDU -s + # For migration from Heimdal, extract principals and re-key them under MIT krb5. + # The stash file (.k5.OCF.BERKELEY.EDU) is created by kdb5_util and unlocks the + # database at boot — back it up alongside the database dump. + }; +} diff --git a/modules/ldap-server.nix b/modules/ldap-server.nix new file mode 100644 index 00000000..12db8420 --- /dev/null +++ b/modules/ldap-server.nix @@ -0,0 +1,214 @@ +{ + lib, + config, + pkgs, + ... +}: + +let + cfg = config.ocf.ldapServer; + fqdn = "${config.networking.hostName}.ocf.berkeley.edu"; + certDir = "/var/lib/acme/${fqdn}"; +in +{ + options.ocf.ldapServer = { + enable = lib.mkEnableOption "OCF OpenLDAP server"; + }; + + config = lib.mkIf cfg.enable { + # Keytab for the ldap/@OCF.BERKELEY.EDU service principal. + # The path is exposed to slapd via the KRB5_KTNAME environment variable. + age.secrets.ldap-keytab = { + rekeyFile = ../secrets/master-keyed/ldap-keytab.age; + path = "/etc/openldap/ldap.keytab"; + owner = "openldap"; + group = "openldap"; + mode = "0400"; + }; + + # Allow openldap to read ACME certificates + security.acme.certs.${fqdn}.group = lib.mkDefault "openldap"; + + # Cyrus SASL configuration for slapd GSSAPI authentication. + # The keytab path comes from KRB5_KTNAME in the service environment, not here. + environment.etc."sasl2/slapd.conf" = { + text = '' + mech_list: GSSAPI + pwcheck_method: saslauthd + ''; + mode = "0444"; + }; + + # saslauthd validates Kerberos credentials for services that use it + services.saslauthd = { + enable = true; + mechanism = "kerberos5"; + }; + + services.openldap = { + enable = true; + # ldaps only — no unencrypted ldap:// + urlList = [ "ldaps:///" ]; + settings = { + attrs = { + olcLogLevel = [ "0" ]; + + # TLS — cert issued for ${fqdn} with ldap.ocf.berkeley.edu as a SAN + olcTLSCACertificateFile = "/etc/ssl/certs/ca-certificates.crt"; + olcTLSCertificateFile = "${certDir}/cert.pem"; + olcTLSCertificateKeyFile = "${certDir}/key.pem"; + olcTLSVerifyClient = "never"; + olcTLSCipherSuite = "SECURE256:!AES-128-CBC:!ARCFOUR-128:!CAMELLIA-128-CBC:!3DES-CBC:!CAMELLIA-128-CBC"; + + # SASL/GSSAPI realm — map Kerberos principals to LDAP DNs + olcSaslRealm = "OCF.BERKELEY.EDU"; + olcAuthzRegexp = [ + # Regular users → their ou=People entry + "{0}uid=([^,/]+),cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth uid=$1,ou=People,dc=OCF,dc=Berkeley,dc=EDU" + # Hosts → their ou=Hosts entry + "{1}uid=host/([^,/]+)\\.ocf\\.berkeley\\.edu,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth cn=$1,ou=Hosts,dc=OCF,dc=Berkeley,dc=EDU" + ]; + }; + + children = { + "cn=schema" = { + includes = [ + "${pkgs.openldap}/etc/schema/core.ldif" + "${pkgs.openldap}/etc/schema/cosine.ldif" + "${pkgs.openldap}/etc/schema/nis.ldif" + ./ldap-server/puppet.schema.ldif + ./ldap-server/ocf.schema.ldif + ]; + }; + + "olcDatabase={0}config" = { + attrs = { + objectClass = [ "olcDatabaseConfig" ]; + olcDatabase = "{0}config"; + # Only local root (via SASL EXTERNAL) may modify cn=config + olcAccess = [ + "{0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break" + ]; + }; + }; + + "olcDatabase={1}mdb" = { + attrs = { + objectClass = [ + "olcDatabaseConfig" + "olcMdbConfig" + ]; + olcDatabase = "{1}mdb"; + olcDbDirectory = "/var/lib/openldap/data"; + olcSuffix = "dc=OCF,dc=Berkeley,dc=EDU"; + # No rootDN password — all admin access is via SASL/GSSAPI + olcSizeLimit = "-1"; + olcDbMaxSize = "2147483648"; # 2 GiB + olcDbIndex = [ + "objectClass eq" + "uid,uidNumber eq" + "memberUid,uniqueMember eq" + "cn eq,sub" + "calnetUid,oslGid,callinkOid eq,pres" + ]; + # TODO: load the ocfvirt overlay (custom shared library from ocf/ldap-api). + # In slapd.conf it was: moduleload ocfvirt / overlay ocfvirt + # It needs to be packaged as a NixOS derivation and loaded via + # olcModulePath / olcModuleLoad before this database config. + olcAccess = [ + # Root DSE is readable by everyone + "{0}to dn.base=\"\" by * read" + # Only /admin (with GSSAPI) can write userPassword; owner can read; anonymous can auth + "{1}to dn.subtree=\"ou=People,dc=OCF,dc=Berkeley,dc=EDU\" attrs=userPassword by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/admin,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" write by sasl_ssf=56 self read by sasl_ssf=56 anonymous auth by * none" + # Hosts can update their own puppet environment; /admin can write; users can read over SSL + "{2}to dn.subtree=\"ou=Hosts,dc=OCF,dc=Berkeley,dc=EDU\" attrs=environment by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/admin,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" write by sasl_ssf=56 self write by sasl_ssf=56 users read by tls_ssf=256 anonymous read" + # Sorried users cannot change their own shell + "{3}to dn.subtree=\"ou=People,dc=OCF,dc=Berkeley,dc=EDU\" filter=(loginShell=/opt/share/utils/bin/sorried) attrs=loginShell by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/admin,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" write by sasl_ssf=56 users read by tls_ssf=256 anonymous read" + # Non-sorried users can change their own shell + "{4}to dn.subtree=\"ou=People,dc=OCF,dc=Berkeley,dc=EDU\" attrs=loginShell by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/admin,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" write by sasl_ssf=56 self write by sasl_ssf=56 users read by tls_ssf=256 anonymous read" + # mail: /admin and /root can read; smtp service can read; owner can write + "{5}to dn.subtree=\"ou=People,dc=OCF,dc=Berkeley,dc=EDU\" attrs=mail by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/admin,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" write by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/root,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" read by sasl_ssf=56 dn=\"uid=smtp/anthrax.ocf.berkeley.edu,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth\" read by sasl_ssf=56 self write by * none" + # Everything else: /admin can write; authenticated users can read over GSSAPI; anonymous can read over TLS + "{6}to * by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/admin,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" write by sasl_ssf=56 users read by tls_ssf=256 anonymous read" + ]; + }; + }; + }; + }; + }; + + systemd.services.openldap = { + serviceConfig = { + # Point slapd at the GSSAPI keytab + Environment = "KRB5_KTNAME=/etc/openldap/ldap.keytab"; + }; + }; + + # KDC must start after slapd so SASL/GSSAPI is available for KDC → LDAP lookups + systemd.services.krb5kdc.after = [ "openldap.service" ]; + + networking.firewall.allowedTCPPorts = [ 636 ]; + + systemd.tmpfiles.rules = [ + "d /var/lib/openldap/data 0700 openldap openldap -" + "d /etc/openldap 0750 openldap openldap -" + "d /var/backups/ldap 0700 root root -" + ]; + + # SSH deploy key for pushing the LDAP backup to github.com:ocf/ldap + age.secrets.ldap-github-deploy-key = { + rekeyFile = ../secrets/master-keyed/ldap-github-deploy-key.age; + path = "/root/.ssh/id_rsa_ldap_backup"; + owner = "root"; + group = "root"; + mode = "0600"; + }; + + # Pin GitHub's host key so the backup push doesn't need to prompt + programs.ssh.knownHosts."github.com" = { + publicKeyType = "ssh-rsa"; + publicKey = "AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="; + }; + + systemd.services.ldap-git-backup = { + description = "LDAP git backup"; + after = [ "slapd.service" ]; + requires = [ "slapd.service" ]; + path = [ + pkgs.git + pkgs.openldap + ]; + serviceConfig = { + Type = "oneshot"; + User = "root"; + UMask = "0077"; + }; + script = '' + BACKUP_DIR=/var/backups/ldap + + [ -d "$BACKUP_DIR/.git" ] || git -C "$BACKUP_DIR" init -q + + slapcat -n 0 > "$BACKUP_DIR/ldap-config.ldif" + slapcat -n 1 > "$BACKUP_DIR/ldap-data.ldif" + + git -C "$BACKUP_DIR" add ldap-config.ldif ldap-data.ldif + git -C "$BACKUP_DIR" commit -q -m 'ldap-git-backup' --allow-empty \ + ldap-config.ldif ldap-data.ldif + git -C "$BACKUP_DIR" gc --auto --quiet + + GIT_SSH_COMMAND="ssh -i ${config.age.secrets.ldap-github-deploy-key.path}" \ + git -C "$BACKUP_DIR" push -q git@github.com:ocf/ldap master + ''; + }; + + systemd.timers.ldap-git-backup = { + description = "Run LDAP git backup daily"; + wantedBy = [ "timers.target" ]; + timerConfig = { + # Run before rsnapshot so the backup server gets a fresh daily snapshot + OnCalendar = "*-*-* 01:00:00"; + Persistent = true; + }; + }; + }; +} diff --git a/modules/ldap-server/ocf.schema.ldif b/modules/ldap-server/ocf.schema.ldif new file mode 100644 index 00000000..ced30fa8 --- /dev/null +++ b/modules/ldap-server/ocf.schema.ldif @@ -0,0 +1,86 @@ +dn: cn=ocf,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: ocf +olcAttributeTypes: ( 1.3.6.1.4.1.41759.1.2.1 + NAME 'calnetUid' + DESC 'An integer identifying a user in the CalNet Directory' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.41759.1.3.1 + NAME 'oslGid' + DESC 'An integer identifying a student organization (deprecated)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.41759.1.4.1 + NAME 'callinkOid' + DESC 'An integer identifying an organization in CalLink' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.41759.1.5.1 + NAME 'lastRenewal' + DESC 'Last virtual host renewal date' + EQUALITY generalizedTimeMatch + ORDERING generalizedTimeOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.41759.1.6.1 + NAME 'creationTime' + DESC 'Account creation date' + EQUALITY generalizedTimeMatch + ORDERING generalizedTimeOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.41759.1.7.1 + NAME 'ocfEmail' + DESC 'OCF email address' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} + SINGLE-VALUE ) +olcObjectClasses: ( 1.3.6.1.4.1.41759.1.1.1 + NAME 'ocfAccount' + DESC 'Attributes for OCF accounts' + SUP posixAccount + AUXILIARY + MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory $ loginShell ) + MAY ( calnetUid $ oslGid $ callinkOid $ mail $ lastRenewal $ creationTime $ ocfEmail ) ) +olcAttributeTypes: ( 1.3.6.1.4.1.41759.2.2.1 + NAME 'type' + DESC 'Host type' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.41759.2.2.2 + NAME 'dnsCname' + DESC 'DNS CNAME record' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: ( 1.3.6.1.4.1.41759.2.2.3 + NAME 'dnsA' + DESC 'DNS A record' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: ( 1.3.6.1.4.1.41759.2.2.4 + NAME 'ip6HostNumber' + DESC 'IPv6 address, as represented by RFC1884 section 2.2.2' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} ) +olcObjectClasses: ( 1.3.6.1.4.1.41759.2.1.2 + NAME 'ip6Host' + DESC 'Host optionally supporting IPv6' + SUP top + AUXILIARY + MUST ( cn ) + MAY ( ip6HostNumber $ manager $ description $ l ) ) +olcObjectClasses: ( 1.3.6.1.4.1.41759.2.1.1 + NAME 'ocfDevice' + DESC 'Attributes for OCF hosts' + SUP ( ipHost $ ip6Host $ ieee802Device $ puppetClient ) + AUXILIARY + MUST ( cn $ type ) + MAY ( environment $ dnsCname $ dnsA ) ) diff --git a/modules/ldap-server/puppet.schema.ldif b/modules/ldap-server/puppet.schema.ldif new file mode 100644 index 00000000..40b882b2 --- /dev/null +++ b/modules/ldap-server/puppet.schema.ldif @@ -0,0 +1,25 @@ +dn: cn=puppet,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: puppet +olcAttributeTypes: ( 1.3.6.1.4.1.34380.1.1.3.10 NAME 'puppetClass' + DESC 'Puppet Node Class' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.34380.1.1.3.9 NAME 'parentNode' + DESC 'Puppet Parent Node' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.34380.1.1.3.11 NAME 'environment' + DESC 'Puppet Node Environment' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.3.6.1.4.1.34380.1.1.3.12 NAME 'puppetVar' + DESC 'A variable setting for puppet' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcObjectClasses: ( 1.3.6.1.4.1.34380.1.1.1.2 NAME 'puppetClient' + SUP top + AUXILIARY + DESC 'Puppet Client objectclass' + MAY ( puppetClass $ parentNode $ environment $ puppetVar ) ) From dc768aad07eea2197a9fb458a5f397675dee8445 Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 05:58:38 -0700 Subject: [PATCH 02/52] ldap and krb modules --- flake.nix | 1 + hosts/servers/eel.nix | 2 - modules/kerberos-server.nix | 65 ------ .../kerberos-server/check-pass-strength.py | 42 ++++ modules/kerberos-server/default.nix | 77 +++++++ .../default.nix} | 59 ++--- modules/ldap-server/ldap-lint.py | 208 ++++++++++++++++++ pkgs/ldap-git-backup.nix | 26 +++ 8 files changed, 388 insertions(+), 92 deletions(-) delete mode 100644 modules/kerberos-server.nix create mode 100644 modules/kerberos-server/check-pass-strength.py create mode 100644 modules/kerberos-server/default.nix rename modules/{ldap-server.nix => ldap-server/default.nix} (84%) create mode 100755 modules/ldap-server/ldap-lint.py create mode 100644 pkgs/ldap-git-backup.nix diff --git a/flake.nix b/flake.nix index 2947d08a..c6a872d1 100644 --- a/flake.nix +++ b/flake.nix @@ -284,6 +284,7 @@ ocf-cosmic-applets = ocf-cosmic-applets.packages.${final.stdenv.hostPlatform.system}.default; ocf-cosmic-greeter = final.callPackage ./pkgs/ocf-cosmic-greeter.nix { }; ocf-hplip = final.callPackage ./pkgs/ocf-hplip.nix { }; + ldap-git-backup = final.callPackage ./pkgs/ldap-git-backup.nix { }; }; agenix-rekey = agenix-rekey.configure { diff --git a/hosts/servers/eel.nix b/hosts/servers/eel.nix index 5cbb077e..ff2432fd 100644 --- a/hosts/servers/eel.nix +++ b/hosts/servers/eel.nix @@ -18,8 +18,6 @@ ocf.kerberosServer.enable = true; ocf.ldapServer.enable = true; - # Cert covers both service names as SANs so ldaps:// and kerberos clients - # connecting to ldap.ocf.berkeley.edu / kerberos.ocf.berkeley.edu are happy ocf.acme.extraCerts = [ "ldap.ocf.berkeley.edu" "kerberos.ocf.berkeley.edu" diff --git a/modules/kerberos-server.nix b/modules/kerberos-server.nix deleted file mode 100644 index 70cbd657..00000000 --- a/modules/kerberos-server.nix +++ /dev/null @@ -1,65 +0,0 @@ -{ - lib, - config, - pkgs, - ... -}: - -let - cfg = config.ocf.kerberosServer; -in -{ - options.ocf.kerberosServer = { - enable = lib.mkEnableOption "OCF Kerberos KDC server (MIT krb5)"; - }; - - config = lib.mkIf cfg.enable { - services.kerberos_server = { - enable = true; - realms."OCF.BERKELEY.EDU" = { - acl = [ - # Staff /admin principals have full KDC access - { - principal = "*/admin"; - access = [ "all" ]; - } - # Staff /root principals can change any principal's password - { - principal = "*/root"; - access = [ "change-password" ]; - target = "*@OCF.BERKELEY.EDU"; - } - # create/admin is used by account creation tooling (ocflib) - { - principal = "create/admin"; - access = [ - "add" - "get" - "change-password" - ]; - target = "*@OCF.BERKELEY.EDU"; - } - ]; - }; - }; - - # TODO: port the password quality check to MIT krb5. - # Firestorm used Heimdal's external-check interface - # (modules/ocf_kerberos/files/check-pass-strength, backed by ocflib validators). - # MIT krb5 requires a pwqual shared-library plugin instead — the script logic - # can be kept but needs a C wrapper that implements the MIT pwqual API. - - environment.systemPackages = [ pkgs.krb5 ]; - - # Ensure the KDC state directory exists before agenix deploys secrets into it - systemd.tmpfiles.rules = [ - "d /var/lib/krb5kdc 0700 root root -" - ]; - - # The KDC database lives in /var/lib/krb5kdc/ and must be initialized manually: - # kdb5_util create -r OCF.BERKELEY.EDU -s - # For migration from Heimdal, extract principals and re-key them under MIT krb5. - # The stash file (.k5.OCF.BERKELEY.EDU) is created by kdb5_util and unlocks the - # database at boot — back it up alongside the database dump. - }; -} diff --git a/modules/kerberos-server/check-pass-strength.py b/modules/kerberos-server/check-pass-strength.py new file mode 100644 index 00000000..fb665892 --- /dev/null +++ b/modules/kerberos-server/check-pass-strength.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Enforce OCF account password complexity. + +Designed to be used as an external password check program by Heimdal. Uses +ocflib to validate password strength with the same requirements as all other +password changing tools. + +Details on interface Heimdal uses: +http://www.h5l.org/manual/HEAD/info/heimdal/Password-changing.html + +Example usage: +$ echo -e "principal: ckuehl@OCF.BERKELEY.EDU\nnew-password: hello" | ./check-pass-strength +""" +import sys + +import ocflib.account.utils as utils +import ocflib.account.validators as validators + + +if __name__ == '__main__': + data = {} + while True: + line = sys.stdin.readline().rstrip('\n') + if line == 'end' or not line: + break + else: + line = line.split(':') + assert len(line) == 2, 'Could not parse input: ' + str(line) + data[line[0]] = line[1][1:] + try: + username = utils.extract_username_from_principal(data['principal']) + password = data['new-password'] + except (KeyError, ValueError): + print('Did not receive principal or password from input', file=sys.stderr) + sys.exit(1) + else: + try: + validators.validate_password(username, password) + except ValueError as e: + print(e, file=sys.stderr) + else: + print('APPROVED') diff --git a/modules/kerberos-server/default.nix b/modules/kerberos-server/default.nix new file mode 100644 index 00000000..c61b1e2a --- /dev/null +++ b/modules/kerberos-server/default.nix @@ -0,0 +1,77 @@ +{ + lib, + config, + pkgs, + ... +}: + +let + cfg = config.ocf.kerberosServer; + + # check-pass-strength wrapped with a Python environment that has ocflib. + checkPassStrength = pkgs.writeShellScript "check-pass-strength" '' + exec ${pkgs.python3.withPackages (ps: [ ps.ocflib ])}/bin/python3 \ + ${./check-pass-strength.py} "$@" + ''; +in +{ + options.ocf.kerberosServer = { + enable = lib.mkEnableOption "OCF Kerberos KDC server (Heimdal)"; + }; + + # The KDC database lives in /var/lib/heimdal/ and must be initialized manually: + # kadmin -l init OCF.BERKELEY.EDU + # For migration between hosts, dump with: kadmin -l dump + # and restore with: kadmin -l load + + config = lib.mkIf cfg.enable { + # Use Heimdal instead of MIT krb5. Heimdal supports an external password + # quality check program natively, eliminating the need for a C plugin. + security.krb5.package = pkgs.heimdal; + + services.kerberos_server = { + enable = true; + settings = { + realms."OCF.BERKELEY.EDU" = { + acl = [ + # Staff /admin principals have full KDC access + { + principal = "*/admin"; + access = [ "all" ]; + } + # Staff /root principals can change any principal's password + { + principal = "*/root"; + access = [ "change-password" ]; + target = "*@OCF.BERKELEY.EDU"; + } + # create/admin is used by account creation tooling (ocflib) + { + principal = "create/admin"; + access = [ + "add" + "get" + "change-password" + ]; + target = "*@OCF.BERKELEY.EDU"; + } + ]; + }; + + # a wrapper for ocflib's `validate_password`. more complex than doing + # it natively, but good to standardize password requirements across + # ocf/utils and ocf/ocfweb. heimdal's external password checking like + # this might not be easily possible in MIT...? consider if migrating + # off of heimdal kerb. + + password_quality = { + policies = "external-check"; + external_program = "${checkPassStrength}"; + }; + }; + }; + + environment.systemPackages = [ pkgs.heimdal ]; + + }; +} diff --git a/modules/ldap-server.nix b/modules/ldap-server/default.nix similarity index 84% rename from modules/ldap-server.nix rename to modules/ldap-server/default.nix index 12db8420..7002f7c9 100644 --- a/modules/ldap-server.nix +++ b/modules/ldap-server/default.nix @@ -9,6 +9,11 @@ let cfg = config.ocf.ldapServer; fqdn = "${config.networking.hostName}.ocf.berkeley.edu"; certDir = "/var/lib/acme/${fqdn}"; + + ldapLint = pkgs.writeShellScript "ldap-lint" '' + exec ${pkgs.python312.withPackages (ps: [ ps.ocflib ps.dnspython ])}/bin/python3 \ + ${./ldap-lint.py} "$@" + ''; in { options.ocf.ldapServer = { @@ -26,7 +31,7 @@ in mode = "0400"; }; - # Allow openldap to read ACME certificates + # slapd process runs as openldap user and needs to read acme certs, but acme certs are owned by acme user and acme group by default. security.acme.certs.${fqdn}.group = lib.mkDefault "openldap"; # Cyrus SASL configuration for slapd GSSAPI authentication. @@ -39,7 +44,7 @@ in mode = "0444"; }; - # saslauthd validates Kerberos credentials for services that use it + # TODO: try removing, not sure if this is necessary, but it was present in the ocf_ldap puppet module... not moving yet for this migration from puppet to nix services.saslauthd = { enable = true; mechanism = "kerberos5"; @@ -70,14 +75,15 @@ in ]; }; + # TODO: once all debian hosts deployed to with puppet are deprecated, remove puppet.schema.ldif children = { "cn=schema" = { includes = [ "${pkgs.openldap}/etc/schema/core.ldif" "${pkgs.openldap}/etc/schema/cosine.ldif" "${pkgs.openldap}/etc/schema/nis.ldif" - ./ldap-server/puppet.schema.ldif - ./ldap-server/ocf.schema.ldif + ./puppet.schema.ldif + ./ocf.schema.ldif ]; }; @@ -111,10 +117,17 @@ in "cn eq,sub" "calnetUid,oslGid,callinkOid eq,pres" ]; - # TODO: load the ocfvirt overlay (custom shared library from ocf/ldap-api). - # In slapd.conf it was: moduleload ocfvirt / overlay ocfvirt - # It needs to be packaged as a NixOS derivation and loaded via - # olcModulePath / olcModuleLoad before this database config. + + # Note: the puppet slapd used ocf/ldap-overlay to synthesize + # ocfEmail dynamically from uid (for some reason?). since + # migrating from puppet to nix, we now store ocfEmail directly on + # user entries and populate by ocflib on account + # creation/modification (see ocfweb). + + # ocfEmail is only currently used in the rt and waddles (ai + # chatbot) repos anyway, no real reason for it to exist. may + # delete soon anyway. + olcAccess = [ # Root DSE is readable by everyone "{0}to dn.base=\"\" by * read" @@ -125,6 +138,7 @@ in # Sorried users cannot change their own shell "{3}to dn.subtree=\"ou=People,dc=OCF,dc=Berkeley,dc=EDU\" filter=(loginShell=/opt/share/utils/bin/sorried) attrs=loginShell by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/admin,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" write by sasl_ssf=56 users read by tls_ssf=256 anonymous read" # Non-sorried users can change their own shell + "{4}to dn.subtree=\"ou=People,dc=OCF,dc=Berkeley,dc=EDU\" attrs=loginShell by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/admin,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" write by sasl_ssf=56 self write by sasl_ssf=56 users read by tls_ssf=256 anonymous read" # mail: /admin and /root can read; smtp service can read; owner can write "{5}to dn.subtree=\"ou=People,dc=OCF,dc=Berkeley,dc=EDU\" attrs=mail by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/admin,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" write by sasl_ssf=56 dn.regex=\"^uid=[^,/]+/root,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth$\" read by sasl_ssf=56 dn=\"uid=smtp/anthrax.ocf.berkeley.edu,cn=OCF.BERKELEY.EDU,cn=GSSAPI,cn=auth\" read by sasl_ssf=56 self write by * none" @@ -147,6 +161,8 @@ in # KDC must start after slapd so SASL/GSSAPI is available for KDC → LDAP lookups systemd.services.krb5kdc.after = [ "openldap.service" ]; + environment.systemPackages = [ ldapLint ]; + networking.firewall.allowedTCPPorts = [ 636 ]; systemd.tmpfiles.rules = [ @@ -172,32 +188,25 @@ in systemd.services.ldap-git-backup = { description = "LDAP git backup"; - after = [ "slapd.service" ]; - requires = [ "slapd.service" ]; + after = [ "openldap.service" ]; + requires = [ "openldap.service" ]; path = [ - pkgs.git + pkgs.ldap-git-backup pkgs.openldap + pkgs.git ]; serviceConfig = { Type = "oneshot"; User = "root"; UMask = "0077"; }; + environment = { + GIT_SSH_COMMAND = "ssh -i ${config.age.secrets.ldap-github-deploy-key.path}"; + }; script = '' - BACKUP_DIR=/var/backups/ldap - - [ -d "$BACKUP_DIR/.git" ] || git -C "$BACKUP_DIR" init -q - - slapcat -n 0 > "$BACKUP_DIR/ldap-config.ldif" - slapcat -n 1 > "$BACKUP_DIR/ldap-data.ldif" - - git -C "$BACKUP_DIR" add ldap-config.ldif ldap-data.ldif - git -C "$BACKUP_DIR" commit -q -m 'ldap-git-backup' --allow-empty \ - ldap-config.ldif ldap-data.ldif - git -C "$BACKUP_DIR" gc --auto --quiet - - GIT_SSH_COMMAND="ssh -i ${config.age.secrets.ldap-github-deploy-key.path}" \ - git -C "$BACKUP_DIR" push -q git@github.com:ocf/ldap master + ldap-git-backup --backup-dir /var/backups/ldap \ + --ldif-cmd "${pkgs.openldap}/bin/slapcat" + git -C /var/backups/ldap push -q git@github.com:ocf/ldap master ''; }; diff --git a/modules/ldap-server/ldap-lint.py b/modules/ldap-server/ldap-lint.py new file mode 100755 index 00000000..0b85e8ec --- /dev/null +++ b/modules/ldap-server/ldap-lint.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python3 +"""Check the sanity of our LDAP database. + +Currently checks the Hosts OU for: + * Duplicate IP addresses + * Duplicate MAC addresses + * Missing IP address + * Existence of MAC address (should be present only on type=desktop) + * Invalid or missing type + * Host not in DNS or mismatched IP + * Unrecognized puppetVar (often typos) + * Reverse DNS for IP exists and matches hostname + * IP is not an OCF address + * IPv6 does not match IPv4 + * Does not have an IPv6 address + +It also does some checks around users and kerberos principals: + * All users with a /root principal should also have a /admin principal + * All ocfroot members should be in ocfstaff too + * All ocfroot members should have a /root and /admin principal +""" +import subprocess +import sys +from ipaddress import ip_address +from operator import itemgetter + +import dns +from ocflib.infra.hosts import HOST_TYPES_WITH_IPV6 +from ocflib.infra.ldap import ldap_connection +from ocflib.infra.ldap import OCF_LDAP_GROUP +from ocflib.infra.ldap import OCF_LDAP_HOSTS +from ocflib.infra.net import ipv4_to_ipv6 +from ocflib.infra.net import ipv6_to_ipv4 +from ocflib.infra.net import is_ocf_ip +from ocflib.infra.net import OCF_SUBNET_V6_COMPAT +from ocflib.misc.shell import bold +from ocflib.misc.shell import red + + +RECOGNIZED_TYPES = frozenset({ + 'desktop', + 'dhcp', + 'ipmi', + 'printer', + 'server', + 'staffvm', + 'switch', + 'vip', + 'wifi', +}) + +# inclusive +STAFFVM_RANGE = (ip_address('169.229.226.200'), ip_address('169.229.226.252')) + + +def lookup_dns(host, rtype='A'): + """Return string representation of first record, or None.""" + try: + return str(dns.resolver.query(host, rtype)[0]) or None + except dns.resolver.NXDOMAIN: + return None + + +def check_hosts(c, complain): + seen_macs = {} + seen_ips = {} + + c.search( + OCF_LDAP_HOSTS, + '(cn=*)', + attributes=['cn', 'type', 'macAddress', 'ipHostNumber', 'ip6HostNumber', 'puppetVar', 'puppetClass'], + ) + for attrs in map(itemgetter('attributes'), c.response): + cn = attrs['cn'][0] + type_ = attrs['type'] + + if type_ not in RECOGNIZED_TYPES: + complain(cn, 'has unknown type ' + type_) + + if attrs['macAddress']: + mac_addr = attrs['macAddress'][0].lower() + + if type_ != 'desktop': + complain(cn, 'has a MAC address but not a desktop') + + if mac_addr in seen_macs: + complain(cn, 'has same MAC address as ' + seen_macs[mac_addr]) + else: + seen_macs[mac_addr] = cn + elif type_ == 'desktop': + complain(cn, 'has no MAC address but is a desktop') + + ip = ip_address(attrs['ipHostNumber'][0]) + in_staffvm_range = STAFFVM_RANGE[0] <= ip <= STAFFVM_RANGE[1] + if type_ == 'staffvm' and not in_staffvm_range and not cn.startswith('hozer-'): + complain(cn, 'is a staff VM, but not in staffvm IP range') + elif type_ != 'staffvm' and in_staffvm_range: + complain(cn, 'is in staffvm IP range, but not a staffvm') + if not is_ocf_ip(ip): + complain(cn, 'has the IP address {}, which is not an OCF IP'.format(ip)) + ip6s = [ip_address(ip6) for ip6 in attrs['ip6HostNumber']] + for ip6 in ip6s: + if not is_ocf_ip(ip6): + complain(cn, 'has the IP address {}, which is not an OCF IP'.format(ip6)) + if ip6 in OCF_SUBNET_V6_COMPAT and ipv6_to_ipv4(ip6) != ip: + complain(cn, 'has the IPv6 address {}, which does not match its IPv4 address'.format(ip6)) + if (len(ip6s) > 0 or type_ in HOST_TYPES_WITH_IPV6) and ipv4_to_ipv6(ip) not in ip6s: + complain(cn, 'does not have an ip6HostNumber attribute matching its ipHostNumber') + + ip = attrs['ipHostNumber'][0] + dns_ip = lookup_dns(cn + '.ocf.berkeley.edu') + + if not dns_ip: + complain(cn, 'has no A record in DNS') + else: + if ip in seen_ips: + complain(cn, 'has same IP address as ' + seen_ips[ip]) + else: + seen_ips[ip] = cn + + if dns_ip != ip: + complain(cn, 'ldap ip {} doesn\'t match dns ip {}'.format(ip, dns_ip)) + + ptr = lookup_dns(dns.reversename.from_address(ip), rtype='PTR') + + if ptr: + if ptr.lower() != cn + '.ocf.berkeley.edu.': + complain(cn, 'bad reverse DNS for {}: {}'.format(ip, ptr)) + else: + complain(cn, 'missing reverse DNS for {}'.format(ip)) + + # TODO: remove these from schema + for puppet_var in attrs.get('puppetVar', []): + complain(cn, 'has puppetVar: {}'.format(puppet_var)) + + for puppet_class in attrs.get('puppetClass', []): + complain(cn, 'has puppetClass: {}'.format(puppet_class)) + + +def get_kadmin_users(filter_query): + """Using kadmin -l as root means that we don't have to get a kerberos + principal for this script and it can always check the local kerberos, which + is nice""" + process = subprocess.run( + ('kadmin', '-l', 'list', filter_query), + stdout=subprocess.PIPE, + ) + principals = process.stdout.decode('utf-8').split('\n') + + # Only return usernames, not the full principal name, since the suffix + # isn't useful + return {principal.split('/')[0] for principal in principals} + + +def get_users_in_group(c, group): + """This is useful over the (much simpler) list_group from ocflib since it + uses the local LDAP instead of the cached user groups, so it validates the + actual source of truth and can also work on dev-ldap""" + c.search( + OCF_LDAP_GROUP, + '(cn={})'.format(group), + attributes=['memberUid'], + ) + return set(c.response[0]['attributes']['memberUid']) + + +def check_users(c, complain): + ocfstaff = get_users_in_group(c, 'ocfstaff') + ocfroot = get_users_in_group(c, 'ocfroot') + + admin_users = get_kadmin_users('*/admin') + root_users = get_kadmin_users('*/root') + + for user in (admin_users - root_users): + if user not in ('create', 'kadmin'): + complain(user + '/admin', 'no corresponding {}/root principal'.format(user)) + + for user in (root_users - admin_users): + complain(user + '/root', 'no corresponding {}/admin principal'.format(user)) + + for user in ocfroot: + if user not in ocfstaff: + complain(user, 'in ocfroot but not ocfstaff') + + if user not in root_users: + complain(user, 'in ocfroot but has no root principal') + + if user not in admin_users: + complain(user, 'in ocfroot but has no admin principal') + + +def main(): + retval = 0 + + def complain(cn, error): + nonlocal retval + retval = 1 + print(bold(red('[{}] '.format(cn))) + error) + + with ldap_connection('localhost') as c: + check_hosts(c, complain) + check_users(c, complain) + + return retval + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix new file mode 100644 index 00000000..82d63dff --- /dev/null +++ b/pkgs/ldap-git-backup.nix @@ -0,0 +1,26 @@ +{ stdenv, fetchFromGitHub, perl, perlPackages, git, makeWrapper }: + +stdenv.mkDerivation { + pname = "ldap-git-backup"; + version = "unstable-2023-01-27"; + + src = fetchFromGitHub { + owner = "elmar"; + repo = "ldap-git-backup"; + rev = "6e0ea0e9bd2b8a52965b06e63c30100508a29428"; + hash = "sha256-En8MBrSRj2zAs+/3XMRhT96UplkpawdBy3OCLYCWn0s="; + }; + + nativeBuildInputs = [ makeWrapper perl ]; + + buildInputs = [ + perl + perlPackages.Git + ]; + + postInstall = '' + wrapProgram $out/sbin/ldap-git-backup \ + --prefix PATH : ${git}/bin \ + --prefix PERL5LIB : ${perlPackages.Git}/${perl.libPrefix} + ''; +} From 2eebbd374c77efdf0b696b0894a37814e96a7a7d Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 06:27:25 -0700 Subject: [PATCH 03/52] nix fmt --- modules/kerberos-server/default.nix | 10 +++---- modules/ldap-server/default.nix | 27 +++++++++++------- pkgs/ldap-git-backup.nix | 14 +++++++-- .../eel/ldap-github-deploy-key.age | Bin 0 -> 3330 bytes 4 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 secrets/master-keyed/eel/ldap-github-deploy-key.age diff --git a/modules/kerberos-server/default.nix b/modules/kerberos-server/default.nix index c61b1e2a..fd8866ec 100644 --- a/modules/kerberos-server/default.nix +++ b/modules/kerberos-server/default.nix @@ -58,11 +58,11 @@ in ]; }; - # a wrapper for ocflib's `validate_password`. more complex than doing - # it natively, but good to standardize password requirements across - # ocf/utils and ocf/ocfweb. heimdal's external password checking like - # this might not be easily possible in MIT...? consider if migrating - # off of heimdal kerb. + # a wrapper for ocflib's `validate_password`. more complex than doing + # it natively, but good to standardize password requirements across + # ocf/utils and ocf/ocfweb. heimdal's external password checking like + # this might not be easily possible in MIT...? consider if migrating + # off of heimdal kerb. password_quality = { policies = "external-check"; diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 7002f7c9..d6830632 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -11,7 +11,12 @@ let certDir = "/var/lib/acme/${fqdn}"; ldapLint = pkgs.writeShellScript "ldap-lint" '' - exec ${pkgs.python312.withPackages (ps: [ ps.ocflib ps.dnspython ])}/bin/python3 \ + exec ${ + pkgs.python312.withPackages (ps: [ + ps.ocflib + ps.dnspython + ]) + }/bin/python3 \ ${./ldap-lint.py} "$@" ''; in @@ -75,7 +80,7 @@ in ]; }; - # TODO: once all debian hosts deployed to with puppet are deprecated, remove puppet.schema.ldif + # TODO: once all debian hosts deployed to with puppet are deprecated, remove puppet.schema.ldif children = { "cn=schema" = { includes = [ @@ -118,15 +123,15 @@ in "calnetUid,oslGid,callinkOid eq,pres" ]; - # Note: the puppet slapd used ocf/ldap-overlay to synthesize - # ocfEmail dynamically from uid (for some reason?). since - # migrating from puppet to nix, we now store ocfEmail directly on - # user entries and populate by ocflib on account - # creation/modification (see ocfweb). + # Note: the puppet slapd used ocf/ldap-overlay to synthesize + # ocfEmail dynamically from uid (for some reason?). since + # migrating from puppet to nix, we now store ocfEmail directly on + # user entries and populate by ocflib on account + # creation/modification (see ocfweb). - # ocfEmail is only currently used in the rt and waddles (ai - # chatbot) repos anyway, no real reason for it to exist. may - # delete soon anyway. + # ocfEmail is only currently used in the rt and waddles (ai + # chatbot) repos anyway, no real reason for it to exist. may + # delete soon anyway. olcAccess = [ # Root DSE is readable by everyone @@ -173,7 +178,7 @@ in # SSH deploy key for pushing the LDAP backup to github.com:ocf/ldap age.secrets.ldap-github-deploy-key = { - rekeyFile = ../secrets/master-keyed/ldap-github-deploy-key.age; + rekeyFile = ../secrets/master-keyed/eel/ldap-github-deploy-key.age; path = "/root/.ssh/id_rsa_ldap_backup"; owner = "root"; group = "root"; diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix index 82d63dff..122d9839 100644 --- a/pkgs/ldap-git-backup.nix +++ b/pkgs/ldap-git-backup.nix @@ -1,4 +1,11 @@ -{ stdenv, fetchFromGitHub, perl, perlPackages, git, makeWrapper }: +{ + stdenv, + fetchFromGitHub, + perl, + perlPackages, + git, + makeWrapper, +}: stdenv.mkDerivation { pname = "ldap-git-backup"; @@ -11,7 +18,10 @@ stdenv.mkDerivation { hash = "sha256-En8MBrSRj2zAs+/3XMRhT96UplkpawdBy3OCLYCWn0s="; }; - nativeBuildInputs = [ makeWrapper perl ]; + nativeBuildInputs = [ + makeWrapper + perl + ]; buildInputs = [ perl diff --git a/secrets/master-keyed/eel/ldap-github-deploy-key.age b/secrets/master-keyed/eel/ldap-github-deploy-key.age new file mode 100644 index 0000000000000000000000000000000000000000..ed8d68c158c8169401763675c735d734c99941b1 GIT binary patch literal 3330 zcmY+EcUV-1w#5;M%9sQd4T2)YD^cf>VfxHPP0pE_GrjjgefP}FnKQkesaURp29=;< z#6s+1VnYaOG$B|50i&^?q5&Hk3n*8`jsia3`-}H|`|thRdwpvy7)5drx5*#%25cVp z7al)K2oZ5PvomxgDwW90u(_#9f(LMDRCtY?tfOd9l7(S4lQ5%1s<7w!TtU?3BTE&a zU5(R4X)?0|Z_|Z*9Ib%O5wY3fs6U8G5TV({G~@L?I@`{YG9fc#2muaoNeW(&Yv#gA zaaf3%m?8sRE%EpOx7G`rh#(V*-~pN47g6KfIwF~^m)KznY}3019IgeR&~ z^q`9s^00|)pHa+J4u9?)D-3kVH!s)FmrTzRH(?s zal!>km>sbJVJoOWRZ71(B4#su1$Z}0PuWNu6Y3m}-k!oldF1&392mc%=gr$heULB%(u6oP;j2 z@zrdrLE^-_5FKU#Rq8M()*~zq*{2KXI2Ocf^oymD;82z90GG}Qkise*OG4Bkb|n!| zm|=2A$8hSTWMU*B!;>Jf%mYDcoRkzsa#d8k9p=D9%#UJhuE#7eOJJ=XV#&RrFf0TG zh{eMc4J8l&iyxsFJVX>vq4}hI6^kxZ`PrbCz~*TA!UB_@E9YyBN*@%)A#Qz8Ep-D? z71eEa08m)R;u@V%i&Mt)V=^fLk|PBWND2D*jv*>(ED%krV;Mr2fQb>*5{pYFbGve* zEHXs`2pqPs)<;&@Xda!GkK@VIE)F09I5IvW4*F?KGcybueSljCYvV;VtAVd;;4B+>;KDxlBHJ2VXsEWHc2pvP7&l-jnW|Eh@vnj zO1IioRM_Ic?2v9SaRI$!@GFXhNe%>21?Kk2VS-ogcE~^iO`!1v2`sAGWAz5vK6Hpm z9&gkf5{O-FvsOrq+9Py5M32f924}8NYtdk=AQL5vP$rje&&Byw1IN((W#UQgK1^3kafkFA%20R}ZZgy3`9 zoPJ7(MzQ1?3_-vej`HLnQ(z`U4Mf-$mf0A&cE4HWLD*`XjPErXl@5pxTGa%%h#Wy6 z3ufepg&Mq9?$yBxh7XjweL)X?sFz3@KU-`f)BIw!PecfENdy&NYsFy58xAT_k3hs0 zqBa$z_p|soNNwY@B)W*x1{%l~KS1&PZ&XlHVDJJJs`rXCemdx|=AzP}t>KUdSu&p& zbWt2;i_8Sk*}MWL*8|Y)2C2QkW0R|u47tJ*hz=%>X$C>5AM}{q03uNYbaFlcQIM1t zg@6ueO+whAw>Zcoz`>>cU$^G5U@em%pOb_75g0>oQbS1Pb25U=h!OyKJ}Yc;k%^!X zmI4tV1msfH^jxV+EaL}(2n){;(oKLL^gGyo1w3e+oSX~>4TDq=M%M(mMuXRHBtTj+ z%^C3W!9lzFg|@*>2p_S)A=rfL`RKuq;lmYE6(#mfAGn5yla z2u%Iu-1r1bHP##ZUCqGpiLrT&yNhSMC0Bbk+Q%g!5&qV|9`%J$D`t zBu;+vedmqjderz)dCLHFAie2mYs1L%(~sRdV0e-H?tN@oNwND_;q6b02QKwAFX#*G z8BJchrzSDp^1FKR)ic&FUf|QeS=c1(ugEgJ++okUz5Py@#AX-vDyGfc*q%NrUKbP| zXtf>Qu>7l$^)C-jqaQ45lf~?B$@ta&DnEcSGIZjl`O}Z2KRH>rb5(4fX=Qf*`R4-- zzmFVoj{AJ2=WFkc6-9xfY7PCx7Ak*ul(&kYkkn^6Mt^nEwsj)o*oVaFH@Du1M~jAu zrAOC=H8+*Zly{e$T700EC#zj|dt9raDu2(Z>nTf*#t*c4(6zM_HS4$fWKVrv{Ed|< zU0cU-cg7;;c#{m+&ynhuIP6yG!fRvBU!}gkx~=@;rKq%`_h5YQKW}XaRd0w-KHuE= zv-ogoQQ?N{soCosDQz9sg~K-7X*DNNB~7VyDHrPlcMZI_v&(&8`H4;Sou9p5T}>T*=>azLU-xjQCwGr5y7}Qx%6s)Mv_+2# zoP1~Mn%5k;yr!u1**7b%%mBvfV&ZDw6wUm5H}B_f7lnGh#Ry}elRNT{-hbT4S9K{} ziKBL=b^NjOT_|&}?xS#$`f}aO&EVE8KOAJobsTZcSXA8D0d6xV^V%nE-t=v)XY`w? zH&6FZ{;}(B%>`%Z!>a8M>anJy8Y$8q_hb*Ygij?mBpy68Jp-qU8Qx|~`!rLz=eM@A zoyfNTT2VbJ`NpUs%2@Z>a9wt>s`B7J9@#ftO?7Y+SnXn+{>#y2pmJ(ldxra5DoD3fBkYC=jEBC8?4PRt7?H1vi z9d!fdsAWWV*3Q45CcnfCo;UfuT_qj!pMSGs8ToiZN>=rTCmsFE|GR&E38f(|yYTYH zihcN^gwllY_>MW0o4cettJZzglz*b+kS8m(Mo@4oao2CpNbYO5tGm04AEr(?bF@1- zFXL3&#R=6b_sti-Smp&(iP4L~PZG9{xwddsz4q5Hcaqi}nL?a2d=B&Ib7b1oxaAAe z243ai8SMDRmfdGE&m8j2+gSO!aeLdV@?=I5);F@U>4ER=;gv#u1F(@@QSTqNcWL|6 z@LuiQr5|5U%e--I^>3AnzgMm*YTHj8GkoO~1lM4{(Kj>y>t~e5d68FpQ&PW}(Z{ae z0mTiwoUxFZQ{K5e&GqHWEU=w=qxsUEwWotvt*Ixopmy`JvsI^iv(`&~k}W7b@wyb{ z2ZD=*<@OVA#!S0lYA#SeT2(Subl32g_gsC=alzeLdGAW##i9F3T;cE2P9-_UVN0gicx*vU?Ic{!y|J#<&UyYf{d0#vC;r#tCg}dBD`}gFlO73|%-q8U&4KBeVe>wf;3r!!2~)y3&MRKMP8_8faV&r4%IzgW@d6vXoXp#HVxN$j=m{Aby( zGpkNNsQC|u3>=E{9{om|Ga1I8})K5 zrRU7m3V$}#x{2KU6YF;D@2RDqhYwJX{4?z#z4^O}5p`4&tFVg_GrjCydVJaZ%97dB X3y;Gv@ Date: Thu, 7 May 2026 07:41:52 -0700 Subject: [PATCH 04/52] move kerberos-kdc into auth module dir --- hosts/servers/eel.nix | 2 +- modules/{auth.nix => auth/default.nix} | 6 +++--- .../kerberos-kdc}/check-pass-strength.py | 0 .../{kerberos-server => auth/kerberos-kdc}/default.nix | 8 ++------ 4 files changed, 6 insertions(+), 10 deletions(-) rename modules/{auth.nix => auth/default.nix} (94%) rename modules/{kerberos-server => auth/kerberos-kdc}/check-pass-strength.py (100%) rename modules/{kerberos-server => auth/kerberos-kdc}/default.nix (88%) diff --git a/hosts/servers/eel.nix b/hosts/servers/eel.nix index ff2432fd..a101c1e3 100644 --- a/hosts/servers/eel.nix +++ b/hosts/servers/eel.nix @@ -15,7 +15,7 @@ lastOctet = 97; }; - ocf.kerberosServer.enable = true; + ocf.kerberosKdc.enable = true; ocf.ldapServer.enable = true; ocf.acme.extraCerts = [ diff --git a/modules/auth.nix b/modules/auth/default.nix similarity index 94% rename from modules/auth.nix rename to modules/auth/default.nix index 4cc392f2..57b80b4f 100644 --- a/modules/auth.nix +++ b/modules/auth/default.nix @@ -7,7 +7,7 @@ let cfg = config.ocf.auth; - keytabSecretPath = ../secrets/master-keyed/keytabs + "/${config.networking.hostName}.age"; + keytabSecretPath = ../../secrets/master-keyed/keytabs + "/${config.networking.hostName}.age"; hasKeytab = builtins.pathExists keytabSecretPath; in { @@ -16,7 +16,7 @@ in }; config = lib.mkIf cfg.enable { - age.secrets.root-password-hash.rekeyFile = ../secrets/master-keyed/root-password-hash.age; + age.secrets.root-password-hash.rekeyFile = ../../secrets/master-keyed/root-password-hash.age; # Per-host keytab for GSSAPI SSH authentication # Only configured if the host has a keytab in secrets/master-keyed/keytabs/.age @@ -122,7 +122,7 @@ in security.krb5 = { enable = true; - package = pkgs.krb5; + package = pkgs.heimdal; settings = { realms."OCF.BERKELEY.EDU" = { diff --git a/modules/kerberos-server/check-pass-strength.py b/modules/auth/kerberos-kdc/check-pass-strength.py similarity index 100% rename from modules/kerberos-server/check-pass-strength.py rename to modules/auth/kerberos-kdc/check-pass-strength.py diff --git a/modules/kerberos-server/default.nix b/modules/auth/kerberos-kdc/default.nix similarity index 88% rename from modules/kerberos-server/default.nix rename to modules/auth/kerberos-kdc/default.nix index fd8866ec..182a2322 100644 --- a/modules/kerberos-server/default.nix +++ b/modules/auth/kerberos-kdc/default.nix @@ -6,7 +6,7 @@ }: let - cfg = config.ocf.kerberosServer; + cfg = config.ocf.kerberosKdc; # check-pass-strength wrapped with a Python environment that has ocflib. checkPassStrength = pkgs.writeShellScript "check-pass-strength" '' @@ -15,7 +15,7 @@ let ''; in { - options.ocf.kerberosServer = { + options.ocf.kerberosKdc = { enable = lib.mkEnableOption "OCF Kerberos KDC server (Heimdal)"; }; @@ -25,10 +25,6 @@ in # and restore with: kadmin -l load config = lib.mkIf cfg.enable { - # Use Heimdal instead of MIT krb5. Heimdal supports an external password - # quality check program natively, eliminating the need for a C plugin. - security.krb5.package = pkgs.heimdal; - services.kerberos_server = { enable = true; settings = { From 9ebc0e50058f5cad6826efdff508b1fc37f5cf3b Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 07:48:37 -0700 Subject: [PATCH 05/52] use cpw instead of change-password in heimdal acl --- modules/auth/kerberos-kdc/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auth/kerberos-kdc/default.nix b/modules/auth/kerberos-kdc/default.nix index 182a2322..58d52205 100644 --- a/modules/auth/kerberos-kdc/default.nix +++ b/modules/auth/kerberos-kdc/default.nix @@ -38,7 +38,7 @@ in # Staff /root principals can change any principal's password { principal = "*/root"; - access = [ "change-password" ]; + access = [ "cpw" ]; target = "*@OCF.BERKELEY.EDU"; } # create/admin is used by account creation tooling (ocflib) @@ -47,7 +47,7 @@ in access = [ "add" "get" - "change-password" + "cpw" ]; target = "*@OCF.BERKELEY.EDU"; } From ba0900a8e286bb98fa49c177c3332b59d009f9c4 Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 07:58:37 -0700 Subject: [PATCH 06/52] publicKeyType should just be publicKey --- modules/ldap-server/default.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index d6830632..2e942a70 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -187,8 +187,7 @@ in # Pin GitHub's host key so the backup push doesn't need to prompt programs.ssh.knownHosts."github.com" = { - publicKeyType = "ssh-rsa"; - publicKey = "AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="; + publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="; }; systemd.services.ldap-git-backup = { From 52cd212ca57d9160ca3035f01d8e27991e96351d Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 08:02:04 -0700 Subject: [PATCH 07/52] specify 312 --- modules/auth/kerberos-kdc/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auth/kerberos-kdc/default.nix b/modules/auth/kerberos-kdc/default.nix index 58d52205..b7da5b2b 100644 --- a/modules/auth/kerberos-kdc/default.nix +++ b/modules/auth/kerberos-kdc/default.nix @@ -10,7 +10,7 @@ let # check-pass-strength wrapped with a Python environment that has ocflib. checkPassStrength = pkgs.writeShellScript "check-pass-strength" '' - exec ${pkgs.python3.withPackages (ps: [ ps.ocflib ])}/bin/python3 \ + exec ${pkgs.python312.withPackages (ps: [ ps.ocflib ])}/bin/python3 \ ${./check-pass-strength.py} "$@" ''; in From 2c97b1fc11e69f31f701032ac0be5ab8e6aba5c5 Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 08:19:36 -0700 Subject: [PATCH 08/52] add buildPerlPackage --- pkgs/ldap-git-backup.nix | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix index 122d9839..fc6df7d6 100644 --- a/pkgs/ldap-git-backup.nix +++ b/pkgs/ldap-git-backup.nix @@ -1,13 +1,10 @@ { - stdenv, fetchFromGitHub, - perl, perlPackages, git, - makeWrapper, }: -stdenv.mkDerivation { +perlPackages.buildPerlPackage { pname = "ldap-git-backup"; version = "unstable-2023-01-27"; @@ -18,19 +15,10 @@ stdenv.mkDerivation { hash = "sha256-En8MBrSRj2zAs+/3XMRhT96UplkpawdBy3OCLYCWn0s="; }; - nativeBuildInputs = [ - makeWrapper - perl - ]; - - buildInputs = [ - perl - perlPackages.Git - ]; + propagatedBuildInputs = [ perlPackages.Git ]; postInstall = '' wrapProgram $out/sbin/ldap-git-backup \ - --prefix PATH : ${git}/bin \ - --prefix PERL5LIB : ${perlPackages.Git}/${perl.libPrefix} + --prefix PATH : ${git}/bin ''; } From 3853184a437d96d46e20d07d612e465eb3e9cacb Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 08:30:24 -0700 Subject: [PATCH 09/52] ok, custom installPhase --- pkgs/ldap-git-backup.nix | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix index fc6df7d6..aadfbe55 100644 --- a/pkgs/ldap-git-backup.nix +++ b/pkgs/ldap-git-backup.nix @@ -1,10 +1,13 @@ { + stdenv, fetchFromGitHub, + perl, perlPackages, git, + makeWrapper, }: -perlPackages.buildPerlPackage { +stdenv.mkDerivation { pname = "ldap-git-backup"; version = "unstable-2023-01-27"; @@ -15,10 +18,20 @@ perlPackages.buildPerlPackage { hash = "sha256-En8MBrSRj2zAs+/3XMRhT96UplkpawdBy3OCLYCWn0s="; }; - propagatedBuildInputs = [ perlPackages.Git ]; + nativeBuildInputs = [ + makeWrapper + perl + ]; - postInstall = '' + buildInputs = [ + perl + perlPackages.Git + ]; + + installPhase = '' + install -Dm755 ldap-git-backup $out/sbin/ldap-git-backup wrapProgram $out/sbin/ldap-git-backup \ - --prefix PATH : ${git}/bin + --prefix PATH : ${git}/bin \ + --prefix PERL5LIB : ${perlPackages.Git}/${perl.libPrefix} ''; } From bcf878354dece868ca04e40b6d1b68c5d761532c Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 08:33:32 -0700 Subject: [PATCH 10/52] only need nativeBuildInputs makeWrapper --- pkgs/ldap-git-backup.nix | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix index aadfbe55..179f6282 100644 --- a/pkgs/ldap-git-backup.nix +++ b/pkgs/ldap-git-backup.nix @@ -18,15 +18,7 @@ stdenv.mkDerivation { hash = "sha256-En8MBrSRj2zAs+/3XMRhT96UplkpawdBy3OCLYCWn0s="; }; - nativeBuildInputs = [ - makeWrapper - perl - ]; - - buildInputs = [ - perl - perlPackages.Git - ]; + nativeBuildInputs = [ makeWrapper ]; installPhase = '' install -Dm755 ldap-git-backup $out/sbin/ldap-git-backup From 0352865cf3f7578c97ef5d6526ff417c95572701 Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 14:14:22 -0700 Subject: [PATCH 11/52] writeShellScriptBin --- modules/ldap-server/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 2e942a70..8eb49de9 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -10,7 +10,7 @@ let fqdn = "${config.networking.hostName}.ocf.berkeley.edu"; certDir = "/var/lib/acme/${fqdn}"; - ldapLint = pkgs.writeShellScript "ldap-lint" '' + ldapLint = pkgs.writeShellScriptBin "ldap-lint" '' exec ${ pkgs.python312.withPackages (ps: [ ps.ocflib From 9655a2e315bc061c252205d9920b8774805febff Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Thu, 7 May 2026 21:56:14 -0700 Subject: [PATCH 12/52] mkIf localDeployment --- modules/managed-deployment.nix | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/managed-deployment.nix b/modules/managed-deployment.nix index 9e4eb72b..4893eb00 100644 --- a/modules/managed-deployment.nix +++ b/modules/managed-deployment.nix @@ -30,8 +30,11 @@ in default = true; }; - config = lib.mkIf cfg.enable { - deployment.allowLocalDeployment = true; # for debugging and deploying when github actions deployment breaks + # colmena-only option, will break regular builds without mkIf + config = lib.mkIf cfg.enable (lib.mkMerge [ + (lib.mkIf (options ? deployment) { + deployment.allowLocalDeployment = true; # for debugging and deploying when github actions deployment breaks + }) nix.settings.trusted-users = [ deploy-user ]; From 19c6b9fe074f0489aa17f32adf0a3e48c988d144 Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Thu, 7 May 2026 22:01:09 -0700 Subject: [PATCH 13/52] fix format --- modules/managed-deployment.nix | 121 +++++++++++++++++---------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/modules/managed-deployment.nix b/modules/managed-deployment.nix index 4893eb00..153dfa76 100644 --- a/modules/managed-deployment.nix +++ b/modules/managed-deployment.nix @@ -2,6 +2,7 @@ pkgs, lib, config, + options, ... }: @@ -30,73 +31,73 @@ in default = true; }; - # colmena-only option, will break regular builds without mkIf config = lib.mkIf cfg.enable (lib.mkMerge [ (lib.mkIf (options ? deployment) { deployment.allowLocalDeployment = true; # for debugging and deploying when github actions deployment breaks }) + { + nix.settings.trusted-users = [ deploy-user ]; - nix.settings.trusted-users = [ deploy-user ]; + users.groups.${deploy-user} = { }; - users.groups.${deploy-user} = { }; - - users.users.${deploy-user} = { - isNormalUser = true; - group = deploy-user; - createHome = false; - home = "/var/empty"; - openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDMuiOUsjVJSi+0WeMHKquQmwoyz/c3N7HhjJwzz21B3" # github-actions - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGlViRB5HH1bTaS1S7TcqVBSuxKdrbdhL2CmhDqc/t6A" # oliverni - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILOaJJvOUG08qr3yeeQRB71M30cdPMuO69nsf0CodALa" # jaysa - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDLsEX5PgyQwdOtdOo0U+yWdpOu9gOsqpQRXo7xKww5FAAAABHNzaDo=" # jaysa hardware token - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMdAe7sPMxaidnqOah3UVrjt41KFHHOYleS1VWGH+ZUc" # storce - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICW8L5pydSCGwBstSlXWNSQh//wmRB03RmAWaT3u7+8hAAAABHNzaDo=" # sbwilliams primary hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIsQXwbC4lVR8qMbduDWHVNvjfqD1m8yYbjdEOGCNVNPAAAABHNzaDo=" # sbwilliams secondary hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIe3xdiMA4u6OhEEa8gw1w26G8mBvAC6SXbbgR0sSWO7AAAABHNzaDo=" # michaelzls hardware token 1 - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICWs4Daof6LfwMw6376xOfuPgBnZNxnPWpoUvcWdlql5AAAABHNzaDo=" # michaelzls hardware token 2 - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3DDYaYibt/VjeYDR7cO8tZA2iJUhPBh6jFrB1mBxJA" # chamburr - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDLsEX5PgyQwdOtdOo0U+yWdpOu9gOsqpQRXo7xKww5FAAAABHNzaDo=" # jaysa hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIK6PlfQq5LYIOHTnPwQvJeiGo3MYDxBRb+KdTqrffxFnAAAABHNzaDo=" # blakeh hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIPs3+fHihwZSBQVtoXffCtSSmBBDb/0NY+BPDIo+FKh9AAAABHNzaDo=" # blakeh backup hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIB1zLZffea+7TdFSQOhNBmT1hftFwPzAEK2c8siFeS/7AAAABHNzaDo=" # ericgu hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKtH02NTIoDXgcD5UJoxWWBu5EhHoYaP6NZQKZSIWmadAAAABHNzaDo=" # ericgu backup hardware token - ]; - }; + users.users.${deploy-user} = { + isNormalUser = true; + group = deploy-user; + createHome = false; + home = "/var/empty"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDMuiOUsjVJSi+0WeMHKquQmwoyz/c3N7HhjJwzz21B3" # github-actions + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGlViRB5HH1bTaS1S7TcqVBSuxKdrbdhL2CmhDqc/t6A" # oliverni + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILOaJJvOUG08qr3yeeQRB71M30cdPMuO69nsf0CodALa" # jaysa + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDLsEX5PgyQwdOtdOo0U+yWdpOu9gOsqpQRXo7xKww5FAAAABHNzaDo=" # jaysa hardware token + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMdAe7sPMxaidnqOah3UVrjt41KFHHOYleS1VWGH+ZUc" # storce + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICW8L5pydSCGwBstSlXWNSQh//wmRB03RmAWaT3u7+8hAAAABHNzaDo=" # sbwilliams primary hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIsQXwbC4lVR8qMbduDWHVNvjfqD1m8yYbjdEOGCNVNPAAAABHNzaDo=" # sbwilliams secondary hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIe3xdiMA4u6OhEEa8gw1w26G8mBvAC6SXbbgR0sSWO7AAAABHNzaDo=" # michaelzls hardware token 1 + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICWs4Daof6LfwMw6376xOfuPgBnZNxnPWpoUvcWdlql5AAAABHNzaDo=" # michaelzls hardware token 2 + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3DDYaYibt/VjeYDR7cO8tZA2iJUhPBh6jFrB1mBxJA" # chamburr + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDLsEX5PgyQwdOtdOo0U+yWdpOu9gOsqpQRXo7xKww5FAAAABHNzaDo=" # jaysa hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIK6PlfQq5LYIOHTnPwQvJeiGo3MYDxBRb+KdTqrffxFnAAAABHNzaDo=" # blakeh hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIPs3+fHihwZSBQVtoXffCtSSmBBDb/0NY+BPDIo+FKh9AAAABHNzaDo=" # blakeh backup hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIB1zLZffea+7TdFSQOhNBmT1hftFwPzAEK2c8siFeS/7AAAABHNzaDo=" # ericgu hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKtH02NTIoDXgcD5UJoxWWBu5EhHoYaP6NZQKZSIWmadAAAABHNzaDo=" # ericgu backup hardware token + ]; + }; - # note: this breaks colmena exec, which runs the given command with sudo, - # but sudo cant ask for a password without a proper terminal - security.sudo.extraRules = [ - { - users = [ deploy-user ]; - commands = [ - # needed for colmena apply - { - command = "/run/current-system/sw/bin/nix-store --no-gc-warning --realise /nix/store/*"; - options = [ "NOPASSWD" ]; - } - { - command = "/run/current-system/sw/bin/nix-env --profile /nix/var/nix/profiles/system --set /nix/store/*"; - options = [ "NOPASSWD" ]; - } - { - command = "/nix/store/*/bin/switch-to-configuration *"; - options = [ "NOPASSWD" ]; - } + # note: this breaks colmena exec, which runs the given command with sudo, + # but sudo cant ask for a password without a proper terminal + security.sudo.extraRules = [ + { + users = [ deploy-user ]; + commands = [ + # needed for colmena apply + { + command = "/run/current-system/sw/bin/nix-store --no-gc-warning --realise /nix/store/*"; + options = [ "NOPASSWD" ]; + } + { + command = "/run/current-system/sw/bin/nix-env --profile /nix/var/nix/profiles/system --set /nix/store/*"; + options = [ "NOPASSWD" ]; + } + { + command = "/nix/store/*/bin/switch-to-configuration *"; + options = [ "NOPASSWD" ]; + } - # extra commands allowed on colmena exec - { - command = "/run/current-system/sw/bin/systemctl *"; - options = [ "NOPASSWD" ]; - } - ]; - } - ]; + # extra commands allowed on colmena exec + { + command = "/run/current-system/sw/bin/systemctl *"; + options = [ "NOPASSWD" ]; + } + ]; + } + ]; - services.openssh.settings.AllowGroups = lib.mkIf cfg.staffOnlySsh [ - "ocfstaff" - "ocfroot" - deploy-user - ]; - }; + services.openssh.settings.AllowGroups = lib.mkIf cfg.staffOnlySsh [ + "ocfstaff" + "ocfroot" + deploy-user + ]; + } + ]); } From d51cb62d668cac7205841036acc335389058c11f Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Thu, 7 May 2026 22:17:28 -0700 Subject: [PATCH 14/52] still fixing deployment --- flake.nix | 4 +++- modules/managed-deployment.nix | 22 ++++++++-------------- modules/motd.nix | 8 +++++++- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/flake.nix b/flake.nix index c6a872d1..92801f25 100644 --- a/flake.nix +++ b/flake.nix @@ -220,7 +220,9 @@ { imports = commonModules ++ modules; deployment.tags = [ group ]; + deployment.allowLocalDeployment = true; # for debugging and deploying when github actions deployment breaks deployment.targetHost = "${host}.ocf.berkeley.edu"; + ocf.motd.group = group; # TODO: Think of a less ugly way of doing this deployment.targetUser = nixpkgs.lib.mkIf self.colmenaHive.nodes.${host}.config.ocf.managed-deployment.enable @@ -321,7 +323,7 @@ system = overrideSystem.${host} or defaultSystem; pkgs = pkgsFor system; modules = colmenaConfig.imports; - specialArgs = { inherit inputs; }; + specialArgs = { inherit self inputs; }; } ) colmenaHosts; }; diff --git a/modules/managed-deployment.nix b/modules/managed-deployment.nix index 153dfa76..f69a23a6 100644 --- a/modules/managed-deployment.nix +++ b/modules/managed-deployment.nix @@ -2,7 +2,6 @@ pkgs, lib, config, - options, ... }: @@ -31,12 +30,8 @@ in default = true; }; - config = lib.mkIf cfg.enable (lib.mkMerge [ - (lib.mkIf (options ? deployment) { - deployment.allowLocalDeployment = true; # for debugging and deploying when github actions deployment breaks - }) - { - nix.settings.trusted-users = [ deploy-user ]; + config = lib.mkIf cfg.enable { + nix.settings.trusted-users = [ deploy-user ]; users.groups.${deploy-user} = { }; @@ -93,11 +88,10 @@ in } ]; - services.openssh.settings.AllowGroups = lib.mkIf cfg.staffOnlySsh [ - "ocfstaff" - "ocfroot" - deploy-user - ]; - } - ]); + services.openssh.settings.AllowGroups = lib.mkIf cfg.staffOnlySsh [ + "ocfstaff" + "ocfroot" + deploy-user + ]; + }; } diff --git a/modules/motd.nix b/modules/motd.nix index 8306bb6c..b09ed20d 100644 --- a/modules/motd.nix +++ b/modules/motd.nix @@ -22,12 +22,18 @@ in description = "Description of this node, to be included in the MOTD."; default = ""; }; + + group = lib.mkOption { + type = lib.types.str; + description = "Host group name (e.g. servers, desktops) shown in the MOTD."; + default = "unknown"; + }; }; # TODO: make this read from LDAP config = lib.mkIf cfg.enable { users.motd = '' - ${ansi-bold}Hi, I am ${ansi-red}${config.networking.hostName}${ansi-resetfg}, a ${ansi-red}${builtins.concatStringsSep ", " config.deployment.tags}${ansi-resetfg} at ${ansi-red}169.229.226.${builtins.toString config.ocf.network.lastOctet}${ansi-reset}. + ${ansi-bold}Hi, I am ${ansi-red}${config.networking.hostName}${ansi-resetfg}, a ${ansi-red}${cfg.group}${ansi-resetfg} at ${ansi-red}169.229.226.${builtins.toString config.ocf.network.lastOctet}${ansi-reset}. ${cfg.description} ''; From e6f69e8ced53fcb0c42a1eb8e809c0cdcbb0be2a Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Thu, 7 May 2026 22:27:00 -0700 Subject: [PATCH 15/52] autoreconfHook --- pkgs/ldap-git-backup.nix | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix index 179f6282..2214e0d5 100644 --- a/pkgs/ldap-git-backup.nix +++ b/pkgs/ldap-git-backup.nix @@ -5,6 +5,7 @@ perlPackages, git, makeWrapper, + autoreconfHook, }: stdenv.mkDerivation { @@ -18,10 +19,13 @@ stdenv.mkDerivation { hash = "sha256-En8MBrSRj2zAs+/3XMRhT96UplkpawdBy3OCLYCWn0s="; }; - nativeBuildInputs = [ makeWrapper ]; + nativeBuildInputs = [ + autoreconfHook + makeWrapper + perl + ]; - installPhase = '' - install -Dm755 ldap-git-backup $out/sbin/ldap-git-backup + postInstall = '' wrapProgram $out/sbin/ldap-git-backup \ --prefix PATH : ${git}/bin \ --prefix PERL5LIB : ${perlPackages.Git}/${perl.libPrefix} From c011087645c1093d18dcc5ca324e21eb2e3e97e3 Mon Sep 17 00:00:00 2001 From: jaysa Date: Thu, 7 May 2026 23:49:48 -0700 Subject: [PATCH 16/52] add eel host key and ldap deploy secret --- secrets/host-keys/eel.pub | 1 + 1 file changed, 1 insertion(+) create mode 100644 secrets/host-keys/eel.pub diff --git a/secrets/host-keys/eel.pub b/secrets/host-keys/eel.pub new file mode 100644 index 00000000..2edc48f6 --- /dev/null +++ b/secrets/host-keys/eel.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJFJC/Uw+PsGtp8b23hxv9q7icTlMqzRk7Se+DFS7Zi3 root@nixos From 20b3ffb0757f41d55adcc7ef625850e96b85c3a1 Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Thu, 7 May 2026 23:57:35 -0700 Subject: [PATCH 17/52] temp acme certs, fix ldap secret path --- hosts/servers/eel.nix | 4 ++-- modules/ldap-server/default.nix | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hosts/servers/eel.nix b/hosts/servers/eel.nix index a101c1e3..61b07e93 100644 --- a/hosts/servers/eel.nix +++ b/hosts/servers/eel.nix @@ -19,8 +19,8 @@ ocf.ldapServer.enable = true; ocf.acme.extraCerts = [ - "ldap.ocf.berkeley.edu" - "kerberos.ocf.berkeley.edu" + "eel-ldap.ocf.berkeley.edu" + "eel-kerberos.ocf.berkeley.edu" ]; system.stateVersion = "25.11"; diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 8eb49de9..832a9ebb 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -178,7 +178,7 @@ in # SSH deploy key for pushing the LDAP backup to github.com:ocf/ldap age.secrets.ldap-github-deploy-key = { - rekeyFile = ../secrets/master-keyed/eel/ldap-github-deploy-key.age; + rekeyFile = ../../secrets/master-keyed/eel/ldap-github-deploy-key.age; path = "/root/.ssh/id_rsa_ldap_backup"; owner = "root"; group = "root"; From cc6cb220b0c93e30881b52eacce1673ea76a1ae3 Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Fri, 8 May 2026 00:22:42 -0700 Subject: [PATCH 18/52] extremely sad fucked up eels octet --- hosts/servers/eel.nix | 2 +- modules/ldap-server/default.nix | 2 +- secrets/master-keyed/keytabs/eel.age | Bin 0 -> 1873 bytes 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 secrets/master-keyed/keytabs/eel.age diff --git a/hosts/servers/eel.nix b/hosts/servers/eel.nix index 61b07e93..64b22bbf 100644 --- a/hosts/servers/eel.nix +++ b/hosts/servers/eel.nix @@ -12,7 +12,7 @@ ocf.network = { enable = true; - lastOctet = 97; + lastOctet = 98; }; ocf.kerberosKdc.enable = true; diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 832a9ebb..e875cf34 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -29,7 +29,7 @@ in # Keytab for the ldap/@OCF.BERKELEY.EDU service principal. # The path is exposed to slapd via the KRB5_KTNAME environment variable. age.secrets.ldap-keytab = { - rekeyFile = ../secrets/master-keyed/ldap-keytab.age; + rekeyFile = ../../secrets/master-keyed/ldap-keytab.age; path = "/etc/openldap/ldap.keytab"; owner = "openldap"; group = "openldap"; diff --git a/secrets/master-keyed/keytabs/eel.age b/secrets/master-keyed/keytabs/eel.age new file mode 100644 index 0000000000000000000000000000000000000000..cca7d366dbded5b4eac9fd0e394110760ed6f67d GIT binary patch literal 1873 zcmYk+?d#kI0S9me_rh~H>)I&{o}jUmiMeu4_w2Iy$5#8CW^wu4uyhlOyCicG}Ro2V>c!Ux6@S5$XA)?wGhbkm}4 zfb}_1vRHdju12+t*S*DPyqaQ^VFhXs;Y7J5STO934S&H+! ibgm4>F5WE-l@+B~ zX-suIj7e~TMrBbrzx(U)N1i-QDL{;z+VltS<=ncbg;qFFp zfIj8(bE8}5O5qnvlOFO@4Ct_A&6hSZD-3db2Ov}1;UbC=riurn+>Qda4-jroWl${v zss-8=@@8PPH4SN`1*}Y+UWw6>udAb&^4yhIRL-~{C7I1hE9I)BnNf8KZDq*)!htgy zB?YeL`t3s;ju0CY&g_erQOo(|{fg0fuDqw0p zkH`Xv>YgOZ>j+hq4Li@24I!6SN%*1dQe?$%2|+WR(i4^e&=?=ivO!yG_cH}`dV^+8 zhz_^(MG#QZMQV&63ba{ z0tj87Y83&L7irr~*_c@XJ+nzdt!g^xOCm-_VM9Xz$nZs66`QSD*j+9dp%SSvTx;`T z)JX*10Rg7l!UoCq(x500_~Br~4;4gQWMzAUSV6g&_?!wr3hT4(G9xXQUr=QO_4%$M z;7vf~*G*%#4lJXncvX`*i%akX);Sv>09(Y@+rolhXQrR{BhDXzY@fBLZb*+=q^C=y zG4f}|d_3qxSu*m-256~3$a`QO>Vb-Lyuy?NE1s!TQA(yI$6QYJ(T%>AZ#Me>=hM0y zBc&L~7X~!hZOR%GYJwT%4vY(N7b{qUo^A|jpqqR{@C=PckSLe@4(5182NM>tlnOVa zn0Scxbd4KQoJOa;Z6PS?tfvlau_VJevFr$ZoOTu|oJ;_7v!1kubjh@3rMMZQVYksJ zBNd9Y;h|!KX|_Syf(g2j&CXY_7jSCO*CnkSmTY5hZ*PZ~b?6~D1G$z_trSJrRP)Tn zhW)nAk{SbX<}eJGAz6tk-gx`kh3Q@Ue-6KeWc4lA{&?y3i@!PehZC>0>leTLx7{~` z+a9^GbA&X%|GmdwGX8n%m7mJoZTpAFPd)je=Zt6NXLhfgrSGS{)V%P-rLSH+|AQHS z-}8IKdiwO|-NSDmDTZITv-Q+{*1ONXaqod2&)>QIn+MUm)60)O)aQTs{?VPY|Ji;2 z)!j3%dXIhW;$5FOj$bv-KY~2nu&*#DUcP+zm3OZ`v45&{{3-S9-|sp8#>cLo=A(1Z zJo?hua|L)2Com(IGerEjQ z8Sgpl)DN?NcOLxQr4Nt3r`dx`$1b9$@-uIpMUTB6-@o_zlShtSJ$|4%HM+JK+@XS_ zPyeg=-Y0Lo^47;cIQkVKy-+{=@ZPx>pD%Zj8{dB6SLeR?^}jy*qmQgZ Date: Fri, 8 May 2026 00:41:26 -0700 Subject: [PATCH 19/52] make ldap-keytab secret optional for now --- modules/ldap-server/default.nix | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index e875cf34..cc00d7d4 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -8,6 +8,8 @@ let cfg = config.ocf.ldapServer; fqdn = "${config.networking.hostName}.ocf.berkeley.edu"; + ldapKeytabPath = ../../secrets/master-keyed/ldap-keytab.age; + hasLdapKeytab = builtins.pathExists ldapKeytabPath; certDir = "/var/lib/acme/${fqdn}"; ldapLint = pkgs.writeShellScriptBin "ldap-lint" '' @@ -28,8 +30,9 @@ in config = lib.mkIf cfg.enable { # Keytab for the ldap/@OCF.BERKELEY.EDU service principal. # The path is exposed to slapd via the KRB5_KTNAME environment variable. - age.secrets.ldap-keytab = { - rekeyFile = ../../secrets/master-keyed/ldap-keytab.age; + # Only configured if the keytab secret exists (not available until KDC is initialized). + age.secrets.ldap-keytab = lib.mkIf hasLdapKeytab { + rekeyFile = ldapKeytabPath; path = "/etc/openldap/ldap.keytab"; owner = "openldap"; group = "openldap"; From 771b9f4189483c6f59755917ede7b527e60d10b2 Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Fri, 8 May 2026 00:45:13 -0700 Subject: [PATCH 20/52] rekey eel secrets --- ...48dd25fba4d5cf416b79ecfe861a1-krb5-keytab.age | Bin 0 -> 640 bytes ...2833e5c6a28b2036dcb883-root-password-hash.age | 9 +++++++++ ...5d0da811fc07eef152b6e25e09af6-tsig-secret.age | Bin 0 -> 447 bytes ...21314899fb95673d82-ldap-github-deploy-key.age | Bin 0 -> 2026 bytes 4 files changed, 9 insertions(+) create mode 100644 secrets/rekeyed/eel/03848dd25fba4d5cf416b79ecfe861a1-krb5-keytab.age create mode 100644 secrets/rekeyed/eel/4cdd508bc62833e5c6a28b2036dcb883-root-password-hash.age create mode 100644 secrets/rekeyed/eel/bbc5d0da811fc07eef152b6e25e09af6-tsig-secret.age create mode 100644 secrets/rekeyed/eel/cb2665f51bd73e21314899fb95673d82-ldap-github-deploy-key.age diff --git a/secrets/rekeyed/eel/03848dd25fba4d5cf416b79ecfe861a1-krb5-keytab.age b/secrets/rekeyed/eel/03848dd25fba4d5cf416b79ecfe861a1-krb5-keytab.age new file mode 100644 index 0000000000000000000000000000000000000000..26db441b36536a9203999f9ad8d71636c1df2fb7 GIT binary patch literal 640 zcmV-`0)PEsXJsvAZewzJaCB*JZZ2&QAS#GMQ>s@R%bR)D_M0;Nia-zF?R|ofa7t28ZDe?EM`uqqc~&-NQZNcFJ|I1Ia(pdka%Ew2WgtT} zSPFJRSa3pjNm)%VS!ORrF=%IYV`fA`L2h$SPFh!GWMx@$FEBPcrjK-Qblw*LR1PcYIHX@Z#F_!N=-ISQ)F;xL@-BDLN`QDGAm?rF>`b^SVJ#R zcx-oiQ3@?BEg)DhLNIhtbx1-lL3ToCY+5-%VOUOSL^fG)d2m5#NLnjnY)NERXfSv( zV+tv?lwf~=7d8L{w!{xsfmvcTOP$jP)YDfGnS^m%I9g(baJoGd>vC|3>ifJN?dw{5VnJi<0VqZI1wkotBi0Nb$3cEvzKg^`y*WDk{Oobx)ZS*G?EPZo zu7UEnU*FThOm6HGpqM@m&2)QrF0q3$5q2>7&1kOhV>D(#PX?NIS@Dw_6t|PozKf_u z;?8P ssh-ed25519 yN2bvA I8PVsR/GfeGMzIM9v/CDZq3yQjEHwKIfABowk4A0MTE +El5fFYtqLWM44DNjGh3x+EQPWWvo+ryRmXSus1aa/7M +-> TH9Y-grease &rVh2|&O H +p0BDLsS4ScmxRgCKU4eQ/UfoBA5di8beEd6qJyUSZsURshj+Z8keK/CWXlFUPucL +JHXZRZcx2OtBMZ3r6sxlUfHZnRRc9HETyEqebLLd +--- hUM6V5ze2qF3F6hjTO91V7QXLta7c4w8kzv39hibMQI +U�8��'[����3���7B�9*�lV������f ��e$�ǂY;LH���U�mM�7�g�����N&S{��f����E�6���> +�*�<��{�b�� \ No newline at end of file diff --git a/secrets/rekeyed/eel/bbc5d0da811fc07eef152b6e25e09af6-tsig-secret.age b/secrets/rekeyed/eel/bbc5d0da811fc07eef152b6e25e09af6-tsig-secret.age new file mode 100644 index 0000000000000000000000000000000000000000..7055e4d8718f1a7baef60ded0ef652e63b049d3b GIT binary patch literal 447 zcmV;w0YLs?XJsvAZewzJaCB*JZZ2-IKWh*OcF;Ze?MPoHKK}j=pF+(rM_R9H1~STkB^O;c}URd_f}P%$eCIcaq`F;s9XcVci@ZAUR!QgC&2Vsk_< zNiT5?xHH&i)fIZab* zMN>w3G&M9ca8OxwWNSHVQciJe3h>cm@;nQ_Z_w(nzL(gCB~@g|j;j>CVseHd@RMCj zjBKpd?7vDefW3M8DxexjN8aZgkn!xv+fD_22MK`~-4YF1KbNNzQ6Nl9fyc1A0DH*i&SdQ}QnXES&ByjZrmN@uy_rLJjp{?RQw%K@}9Q;V26TLx@ zF0fcugf0jGieD#=#gz0fP`w|>rp)9T=kre4%F{yF?RYcc`HVFKD)zzKg}X;Rgi&_T zMV?jYPdWs_`UJNk%+Z*hxCW&yG9eLPHhMu!#eHvLz#tA0RqOWkK^){G3Rr44tmBBL zX63n0>@vPmwYtmk%&85vNu6CHDq}M>mX{#U50mC|LGq&SZnXn{d%xVg6`emIW$wHl zL;82*J;x#PcRpcf7Zk)Q9#B4St_leQy`NW>(S8fam?vnTXB)^q}xOGxrZMMoYQo914Cu2y= z4-B`aIxt*3g>EL-CB18J5V(ef#WvM6v|h$7oLCHCLQ{7shck$M3*mrA&v^p60fWCI zVouD_@cgf;NcUrn3!bzTM=PA0}z7`av=y4~aU zp_#O%Cg4CJFfJ;aiwciFs{~5SsjQ+W(7I|5CJoU%6HdD}EUiI_@weimRtBEbynwQt z#gwnaUeNa0fS0a7d)p5l-$Lg2^EY`U9`^bIFeGw0kPkN+9yXofYTYp%1~?q(MNva; zf5+q9&1|#la%9_4e~6#@G9B8L9b&bJ!pT?i>DB0a|f4-veONS zYUuj@3{rtY64?!yq$10)vi#UV!9){;8~&zIP&&;D7~?u$v2PfE%#(n5q5is|1x?TB@4VdwDH&`gmf)y@SVw2G zZXI9r8#;02sS#vfo(B-EVin}q8nbaRaOw;_$`BWu%(uwRv^&HaIq6*0>dd1U}@2-pJEoCt(+} z{VlXc-TU>m3B0JL14h`MhhJYH4LwK7gX`$z!#rpN@U@cqXRR_yoQRaxl!io)jv@Qt z2>$+HpzL4>Xo)_pC+VYsy3r#ao5UA+8mzcm%TWTEbze2Cj=HUqD!Tse?<$xNPw`a#J501 zjS5nx=+4ulF6tUVJ*X62^xR!$L(!)#Il|f3%HxB*LOsMPeWR^0TgI`prWHAG<*N_# zsR-hT{#%)-0(AQDg2GW8ZA9(>`DWm0;{Q38FYeh@rDt!f#Fiq`b%*;r_fz^)M2bWl zX+HT(qe{ZX*51{?BkPi;yz}23<LBA(`DqC8L`VCh#GAeo(6#Cjuya;j-xLUFM)_F zHzCqfgAbbO^rR=k^{W7fQMJ0SL>1a~FvOH?<&qV;jIYM03o$gTFgO)$=pdtV503rPwMZjn8#7o%Kau{z@$uhuh! zkpZiytlK3c(X_JUj1dtrH1GUxyD+++f=)!>Fvq?6hC`3Gnd)D?sRL-qbu`?_U Date: Fri, 8 May 2026 01:19:47 -0700 Subject: [PATCH 21/52] at last, the keytab secret. after kdc dump --- secrets/master-keyed/ldap-keytab.age | Bin 0 -> 1733 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 secrets/master-keyed/ldap-keytab.age diff --git a/secrets/master-keyed/ldap-keytab.age b/secrets/master-keyed/ldap-keytab.age new file mode 100644 index 0000000000000000000000000000000000000000..5810b2f782c05bf5ea29ef5fe21ceb38cc14eeff GIT binary patch literal 1733 zcmYk5yUQ$h9f#8h$$*Gh2-+MJM9%U$GduT$gv|Z2GqW>0*BuBlyF2%t`)y~iND+dS zO-KZ>v9JpXX+sK|aKJ(k!NN*Z1i?U#O^O)wO}GER@8Nkq-(Q$S4^egQmS)K6>L+!V zfD;Tny!OQ3Vi-(4A?(;c>^VJCJAqrN+-gBn=G`+dQND9LB($I}J4D1~#{^7HrDKKe zWG)^t2bG&%O+iWD=3^VC8tj>repE(tjynF1z$2Kwixq|#Z{wB24;%l22O41?wbk`$ z6|bPVLZGf4`~n!%Sw%z+FXbai8)9f`-Z4Kp`puZ~q1CdZv%|G;BS=PnM+k#tKx67s zE%gnTW!T0JBe7DHLaf+z(`;n2kc3+$l`sT!XN#y1uK^icr{->&a5c%|wJ#=%#|z#a zsVNsZeujDajsTv-sRPZ@+~^?KwAv~c7s6?`;~|rJ7iTt*?VZFP#~m3M5<}hflX**5 zsUw3kR`r7HrYU^h)|*rzmfS!wX0oqUaz}_PlcBKFS=A+>7-2Tj(=Iw*(q@7=niFBa z;4P+Oqy*vtAHp&FmRkyW5l^5N@0G`dI3w= zH))+48|Ai4f_9l2kDM=Zh28Y4c)lZW29<17WJQ@`V+GJi=AeACrE(|g0f%NcUgqG; zQ1DwK1If0@WoN{weeIrtGYieKq%?hvp4PFh*#N~B+xB8dE2vpip;T*|jm_pgqxae3B!wMXw6&o`4y7{_@Q~5$A{4Vt6bV%17%ySY z4cVd`ud@(cV#z}qNVOA>yRWo`u@J$v#cm|$aIDG=qxvq-^)h@hn&2=N0S~&neDF;Z zC@(v{bVOBMs}nVpEFY55$)3UeNgJ}}z-eJoC@9kyx_P&Q-g=g%vfPy?(DS^+Yr$tM z$giYR-K=vM2ajj!kr5jqB+&W75Z7Ec>*tYE;klf*PQ`+$vDVj)?sO#b9HAFV+Pwd9 zQtD<7biFDH3BwH%CITtfyyfKqTS$Ap8fCdDX@Jq=h60lX$CngIkvjS0UHVf*N`~mrA2C4 z*&Qd*!y_~squ!6Vq6Vl}YC!kM3dhz_?xE6v@Wd~4QAt@`Ix?8L%vgs?OOGADcDOxt zACfK#`v}-+MP;c=T;R=$6Yg9_P!nxvhw(erx#cl;HVPRP=F7ez0@o6lQYQy{1|A+B zp4cb>cg;+1#nrR}L{#d<$cB_lJ!&XQX_hAv+*?q4F*V@FFa7 Date: Fri, 8 May 2026 01:20:46 -0700 Subject: [PATCH 22/52] nix fmt --- modules/managed-deployment.nix | 102 ++++++++++++++++----------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/modules/managed-deployment.nix b/modules/managed-deployment.nix index f69a23a6..6c594a22 100644 --- a/modules/managed-deployment.nix +++ b/modules/managed-deployment.nix @@ -33,60 +33,60 @@ in config = lib.mkIf cfg.enable { nix.settings.trusted-users = [ deploy-user ]; - users.groups.${deploy-user} = { }; + users.groups.${deploy-user} = { }; - users.users.${deploy-user} = { - isNormalUser = true; - group = deploy-user; - createHome = false; - home = "/var/empty"; - openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDMuiOUsjVJSi+0WeMHKquQmwoyz/c3N7HhjJwzz21B3" # github-actions - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGlViRB5HH1bTaS1S7TcqVBSuxKdrbdhL2CmhDqc/t6A" # oliverni - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILOaJJvOUG08qr3yeeQRB71M30cdPMuO69nsf0CodALa" # jaysa - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDLsEX5PgyQwdOtdOo0U+yWdpOu9gOsqpQRXo7xKww5FAAAABHNzaDo=" # jaysa hardware token - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMdAe7sPMxaidnqOah3UVrjt41KFHHOYleS1VWGH+ZUc" # storce - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICW8L5pydSCGwBstSlXWNSQh//wmRB03RmAWaT3u7+8hAAAABHNzaDo=" # sbwilliams primary hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIsQXwbC4lVR8qMbduDWHVNvjfqD1m8yYbjdEOGCNVNPAAAABHNzaDo=" # sbwilliams secondary hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIe3xdiMA4u6OhEEa8gw1w26G8mBvAC6SXbbgR0sSWO7AAAABHNzaDo=" # michaelzls hardware token 1 - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICWs4Daof6LfwMw6376xOfuPgBnZNxnPWpoUvcWdlql5AAAABHNzaDo=" # michaelzls hardware token 2 - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3DDYaYibt/VjeYDR7cO8tZA2iJUhPBh6jFrB1mBxJA" # chamburr - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDLsEX5PgyQwdOtdOo0U+yWdpOu9gOsqpQRXo7xKww5FAAAABHNzaDo=" # jaysa hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIK6PlfQq5LYIOHTnPwQvJeiGo3MYDxBRb+KdTqrffxFnAAAABHNzaDo=" # blakeh hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIPs3+fHihwZSBQVtoXffCtSSmBBDb/0NY+BPDIo+FKh9AAAABHNzaDo=" # blakeh backup hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIB1zLZffea+7TdFSQOhNBmT1hftFwPzAEK2c8siFeS/7AAAABHNzaDo=" # ericgu hardware token - "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKtH02NTIoDXgcD5UJoxWWBu5EhHoYaP6NZQKZSIWmadAAAABHNzaDo=" # ericgu backup hardware token - ]; - }; + users.users.${deploy-user} = { + isNormalUser = true; + group = deploy-user; + createHome = false; + home = "/var/empty"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDMuiOUsjVJSi+0WeMHKquQmwoyz/c3N7HhjJwzz21B3" # github-actions + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGlViRB5HH1bTaS1S7TcqVBSuxKdrbdhL2CmhDqc/t6A" # oliverni + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILOaJJvOUG08qr3yeeQRB71M30cdPMuO69nsf0CodALa" # jaysa + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDLsEX5PgyQwdOtdOo0U+yWdpOu9gOsqpQRXo7xKww5FAAAABHNzaDo=" # jaysa hardware token + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMdAe7sPMxaidnqOah3UVrjt41KFHHOYleS1VWGH+ZUc" # storce + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICW8L5pydSCGwBstSlXWNSQh//wmRB03RmAWaT3u7+8hAAAABHNzaDo=" # sbwilliams primary hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIsQXwbC4lVR8qMbduDWHVNvjfqD1m8yYbjdEOGCNVNPAAAABHNzaDo=" # sbwilliams secondary hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIe3xdiMA4u6OhEEa8gw1w26G8mBvAC6SXbbgR0sSWO7AAAABHNzaDo=" # michaelzls hardware token 1 + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICWs4Daof6LfwMw6376xOfuPgBnZNxnPWpoUvcWdlql5AAAABHNzaDo=" # michaelzls hardware token 2 + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3DDYaYibt/VjeYDR7cO8tZA2iJUhPBh6jFrB1mBxJA" # chamburr + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDLsEX5PgyQwdOtdOo0U+yWdpOu9gOsqpQRXo7xKww5FAAAABHNzaDo=" # jaysa hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIK6PlfQq5LYIOHTnPwQvJeiGo3MYDxBRb+KdTqrffxFnAAAABHNzaDo=" # blakeh hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIPs3+fHihwZSBQVtoXffCtSSmBBDb/0NY+BPDIo+FKh9AAAABHNzaDo=" # blakeh backup hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIB1zLZffea+7TdFSQOhNBmT1hftFwPzAEK2c8siFeS/7AAAABHNzaDo=" # ericgu hardware token + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKtH02NTIoDXgcD5UJoxWWBu5EhHoYaP6NZQKZSIWmadAAAABHNzaDo=" # ericgu backup hardware token + ]; + }; - # note: this breaks colmena exec, which runs the given command with sudo, - # but sudo cant ask for a password without a proper terminal - security.sudo.extraRules = [ - { - users = [ deploy-user ]; - commands = [ - # needed for colmena apply - { - command = "/run/current-system/sw/bin/nix-store --no-gc-warning --realise /nix/store/*"; - options = [ "NOPASSWD" ]; - } - { - command = "/run/current-system/sw/bin/nix-env --profile /nix/var/nix/profiles/system --set /nix/store/*"; - options = [ "NOPASSWD" ]; - } - { - command = "/nix/store/*/bin/switch-to-configuration *"; - options = [ "NOPASSWD" ]; - } + # note: this breaks colmena exec, which runs the given command with sudo, + # but sudo cant ask for a password without a proper terminal + security.sudo.extraRules = [ + { + users = [ deploy-user ]; + commands = [ + # needed for colmena apply + { + command = "/run/current-system/sw/bin/nix-store --no-gc-warning --realise /nix/store/*"; + options = [ "NOPASSWD" ]; + } + { + command = "/run/current-system/sw/bin/nix-env --profile /nix/var/nix/profiles/system --set /nix/store/*"; + options = [ "NOPASSWD" ]; + } + { + command = "/nix/store/*/bin/switch-to-configuration *"; + options = [ "NOPASSWD" ]; + } - # extra commands allowed on colmena exec - { - command = "/run/current-system/sw/bin/systemctl *"; - options = [ "NOPASSWD" ]; - } - ]; - } - ]; + # extra commands allowed on colmena exec + { + command = "/run/current-system/sw/bin/systemctl *"; + options = [ "NOPASSWD" ]; + } + ]; + } + ]; services.openssh.settings.AllowGroups = lib.mkIf cfg.staffOnlySsh [ "ocfstaff" From 8389c23b6acfaaabc39be605f2e0fb8090c3bb79 Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Fri, 8 May 2026 01:25:45 -0700 Subject: [PATCH 23/52] i have no mouth and i must rekey --- ...cb7b1813f8ce5ffa3651877a7ef3fc-ldap-keytab.age | Bin 0 -> 457 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 secrets/rekeyed/eel/becb7b1813f8ce5ffa3651877a7ef3fc-ldap-keytab.age diff --git a/secrets/rekeyed/eel/becb7b1813f8ce5ffa3651877a7ef3fc-ldap-keytab.age b/secrets/rekeyed/eel/becb7b1813f8ce5ffa3651877a7ef3fc-ldap-keytab.age new file mode 100644 index 0000000000000000000000000000000000000000..56c3974cfe0b45640e729a60d214d6c82ebe49a1 GIT binary patch literal 457 zcmV;)0XF_&XJsvAZewzJaCB*JZZ2HB> zZfRpsWI1zVNpndtc2{CWcUeS5YIRR$Z*4GbdNW}`3N0-yATxDraB^}>VnK6ZW>+>i zcSmbicTH$EcX%>(Y)?a0F;RAEZc0a2OG9Ze3R$vyigjJdmk?tCE%!jSciK#o(*$^l z{cxU%;O^h=I;Mw@NW|rTvJ!-fOY$H@m^1say7s@#8k+ZrM Date: Fri, 8 May 2026 06:26:54 -0700 Subject: [PATCH 24/52] kerb backup script, firewall rules --- modules/auth/kerberos-kdc/default.nix | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/modules/auth/kerberos-kdc/default.nix b/modules/auth/kerberos-kdc/default.nix index b7da5b2b..2f45e493 100644 --- a/modules/auth/kerberos-kdc/default.nix +++ b/modules/auth/kerberos-kdc/default.nix @@ -69,5 +69,53 @@ in environment.systemPackages = [ pkgs.heimdal ]; + networking.firewall = { + allowedTCPPorts = [ + 88 # kerberos + 749 # kadmin + ]; + allowedUDPPorts = [ + 88 # kerberos + 464 # kpasswd + ]; + }; + + systemd.tmpfiles.rules = [ + "d /var/backups/kerberos 0700 root root -" + ]; + + systemd.services.kerberos-git-backup = { + description = "Kerberos KDC git backup"; + after = [ "krb5kdc.service" ]; + requires = [ "krb5kdc.service" ]; + path = [ + pkgs.heimdal + pkgs.git + ]; + serviceConfig = { + Type = "oneshot"; + User = "root"; + UMask = "0077"; + }; + script = '' + dir=/var/backups/kerberos + [ -d "$dir/.git" ] || git -C "$dir" init -q + kadmin -l dump --decrypt "$dir/kerberos.dump" + git -C "$dir" add kerberos.dump + git -C "$dir" commit -q -m 'kerberos-git-backup' --allow-empty kerberos.dump + git -C "$dir" gc --auto --quiet + ''; + }; + + systemd.timers.kerberos-git-backup = { + description = "Run Kerberos KDC git backup daily"; + wantedBy = [ "timers.target" ]; + timerConfig = { + # Run before rsnapshot so the backup server gets a fresh daily snapshot + OnCalendar = "*-*-* 01:00:00"; + Persistent = true; + }; + }; + }; } From 2ab83199b4d8ba0a175f57579bf2b594ae31ea9e Mon Sep 17 00:00:00 2001 From: jaysa Date: Fri, 8 May 2026 10:54:27 -0700 Subject: [PATCH 25/52] TLS cipher string in OpenSSL compatible format --- modules/ldap-server/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index cc00d7d4..4e22b65f 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -71,7 +71,8 @@ in olcTLSCertificateFile = "${certDir}/cert.pem"; olcTLSCertificateKeyFile = "${certDir}/key.pem"; olcTLSVerifyClient = "never"; - olcTLSCipherSuite = "SECURE256:!AES-128-CBC:!ARCFOUR-128:!CAMELLIA-128-CBC:!3DES-CBC:!CAMELLIA-128-CBC"; + # OpenSSL cipher string (NixOS OpenLDAP uses OpenSSL, not GnuTLS) + olcTLSCipherSuite = "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"; # SASL/GSSAPI realm — map Kerberos principals to LDAP DNs olcSaslRealm = "OCF.BERKELEY.EDU"; From b74efb7ed6b02a7bbd1508204226b42d53f860be Mon Sep 17 00:00:00 2001 From: Jaysa Garcia Date: Fri, 8 May 2026 11:27:29 -0700 Subject: [PATCH 26/52] upload eels real key --- secrets/host-keys/eel.pub | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/secrets/host-keys/eel.pub b/secrets/host-keys/eel.pub index 2edc48f6..98d5cce7 100644 --- a/secrets/host-keys/eel.pub +++ b/secrets/host-keys/eel.pub @@ -1 +1 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJFJC/Uw+PsGtp8b23hxv9q7icTlMqzRk7Se+DFS7Zi3 root@nixos +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINSvB6e06YbGs4+TXaU+8sL+dWbuGB1A20y5A721faMv root@eel From e36852be382485efb794614a481bc39fd581e1b8 Mon Sep 17 00:00:00 2001 From: Jaysa Garcia Date: Fri, 8 May 2026 11:32:29 -0700 Subject: [PATCH 27/52] i forgot to rekey dude --- ...48dd25fba4d5cf416b79ecfe861a1-krb5-keytab.age | Bin 640 -> 0 bytes ...711b906b7eb44a424b5440fdfb85e-tsig-secret.age | 9 +++++++++ ...2833e5c6a28b2036dcb883-root-password-hash.age | 9 --------- ...c6abe7ed5b54c9de09-ldap-github-deploy-key.age | Bin 0 -> 2033 bytes ...0d3d5542761975e3c704d344300d9-ldap-keytab.age | 8 ++++++++ ...5d0da811fc07eef152b6e25e09af6-tsig-secret.age | Bin 447 -> 0 bytes ...b7b1813f8ce5ffa3651877a7ef3fc-ldap-keytab.age | Bin 457 -> 0 bytes ...21314899fb95673d82-ldap-github-deploy-key.age | Bin 2026 -> 0 bytes ...0fcd058de3a304e2b1e11f-root-password-hash.age | 7 +++++++ ...57f0ea904f5a1e1fecbf6e3684337-krb5-keytab.age | Bin 0 -> 619 bytes 10 files changed, 24 insertions(+), 9 deletions(-) delete mode 100644 secrets/rekeyed/eel/03848dd25fba4d5cf416b79ecfe861a1-krb5-keytab.age create mode 100644 secrets/rekeyed/eel/09e711b906b7eb44a424b5440fdfb85e-tsig-secret.age delete mode 100644 secrets/rekeyed/eel/4cdd508bc62833e5c6a28b2036dcb883-root-password-hash.age create mode 100644 secrets/rekeyed/eel/557d256bed8119c6abe7ed5b54c9de09-ldap-github-deploy-key.age create mode 100644 secrets/rekeyed/eel/9fe0d3d5542761975e3c704d344300d9-ldap-keytab.age delete mode 100644 secrets/rekeyed/eel/bbc5d0da811fc07eef152b6e25e09af6-tsig-secret.age delete mode 100644 secrets/rekeyed/eel/becb7b1813f8ce5ffa3651877a7ef3fc-ldap-keytab.age delete mode 100644 secrets/rekeyed/eel/cb2665f51bd73e21314899fb95673d82-ldap-github-deploy-key.age create mode 100644 secrets/rekeyed/eel/cd0ed9dbba0fcd058de3a304e2b1e11f-root-password-hash.age create mode 100644 secrets/rekeyed/eel/e5d57f0ea904f5a1e1fecbf6e3684337-krb5-keytab.age diff --git a/secrets/rekeyed/eel/03848dd25fba4d5cf416b79ecfe861a1-krb5-keytab.age b/secrets/rekeyed/eel/03848dd25fba4d5cf416b79ecfe861a1-krb5-keytab.age deleted file mode 100644 index 26db441b36536a9203999f9ad8d71636c1df2fb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 640 zcmV-`0)PEsXJsvAZewzJaCB*JZZ2&QAS#GMQ>s@R%bR)D_M0;Nia-zF?R|ofa7t28ZDe?EM`uqqc~&-NQZNcFJ|I1Ia(pdka%Ew2WgtT} zSPFJRSa3pjNm)%VS!ORrF=%IYV`fA`L2h$SPFh!GWMx@$FEBPcrjK-Qblw*LR1PcYIHX@Z#F_!N=-ISQ)F;xL@-BDLN`QDGAm?rF>`b^SVJ#R zcx-oiQ3@?BEg)DhLNIhtbx1-lL3ToCY+5-%VOUOSL^fG)d2m5#NLnjnY)NERXfSv( zV+tv?lwf~=7d8L{w!{xsfmvcTOP$jP)YDfGnS^m%I9g(baJoGd>vC|3>ifJN?dw{5VnJi<0VqZI1wkotBi0Nb$3cEvzKg^`y*WDk{Oobx)ZS*G?EPZo zu7UEnU*FThOm6HGpqM@m&2)QrF0q3$5q2>7&1kOhV>D(#PX?NIS@Dw_6t|PozKf_u z;?8P ssh-ed25519 O51D5A wFvpPkDvMC8EtG/BYNf/CDXIrgV9DvKacfF0W7qyhFs +edMrnMTy/gqIHbA2mrxv3oUohV0aInIgpol9s8HV3C4 +-> l'`+lz-grease X\ (H^;x +kpT3WWPkCY5V2JX+GPdU9o+IXgxi8j0GHrBM5wGCg0edIkQacUin31KlqT4nZDQT +Dv+Wugzvi9y/BcACN52GKmvzTCMtmitQqT5J7M1ufsAqt+VEMm5H+5e+yaP807Va + +--- hB3uEJGpta2q+iu0qL7JXDJkWoZDxj+XTfcocYyZ60Q +�8�Lg���S�=��;N�4�%��H�t�f�H���~����q�G��M�F����B0�/VfmH�ĕ�����^Q���B@�x��\͵�0�%��䐵�?��Z v 1m�u�we��{7H \ No newline at end of file diff --git a/secrets/rekeyed/eel/4cdd508bc62833e5c6a28b2036dcb883-root-password-hash.age b/secrets/rekeyed/eel/4cdd508bc62833e5c6a28b2036dcb883-root-password-hash.age deleted file mode 100644 index e9608b28..00000000 --- a/secrets/rekeyed/eel/4cdd508bc62833e5c6a28b2036dcb883-root-password-hash.age +++ /dev/null @@ -1,9 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 yN2bvA I8PVsR/GfeGMzIM9v/CDZq3yQjEHwKIfABowk4A0MTE -El5fFYtqLWM44DNjGh3x+EQPWWvo+ryRmXSus1aa/7M --> TH9Y-grease &rVh2|&O H -p0BDLsS4ScmxRgCKU4eQ/UfoBA5di8beEd6qJyUSZsURshj+Z8keK/CWXlFUPucL -JHXZRZcx2OtBMZ3r6sxlUfHZnRRc9HETyEqebLLd ---- hUM6V5ze2qF3F6hjTO91V7QXLta7c4w8kzv39hibMQI -U�8��'[����3���7B�9*�lV������f ��e$�ǂY;LH���U�mM�7�g�����N&S{��f����E�6���> -�*�<��{�b�� \ No newline at end of file diff --git a/secrets/rekeyed/eel/557d256bed8119c6abe7ed5b54c9de09-ldap-github-deploy-key.age b/secrets/rekeyed/eel/557d256bed8119c6abe7ed5b54c9de09-ldap-github-deploy-key.age new file mode 100644 index 0000000000000000000000000000000000000000..7f84f5ba5960808dbc9d054bde1d8c55b23dd59a GIT binary patch literal 2033 zcmV^;&a8y%fZbw#kSV0OcJ|JOqEoX9NVRL05U?X@j zH)~Ef3Q~1MRd9K5d1X^^Fm^R&SubT&R6#gTFfVj&Gfz!rN>@rnaCTW$G;LBwZ8dOL zY++X`VQg(NF?LOQL^n!GbqYdnSV~W9cxrVrY(aB5VryDsOl(j~YdL3QFi}rQXl^oN zWM?>Iby`C-MlfSAFgIgVK{!TH3N0-yAZ{-=LQPpRN_kLjMo?%~Sw%2fcQ;8mV`5@L zQ+8HwN^wF+czQ-dXe(i73Ovv`QI++0I{Objaf}RshXB6hGc{Y-A-08(dXjL}a3S4d z*Ogzi4NazZyF~nQOu7~*a#;n8O~YkJ2dATd%HO$~29lE87k&GRYQY463*;p{nLn00 zILqNir@f!hP_}fS=y^IPGHd{ysAcc8*HtBj7I{Ad5~b-{!&i4S(Qz+;tyr)lL@eUW zwmb|1M5^xF@yu$i_1h=>9y(%rCi>^gH@Ys1z5bJyWz_mk1+U{-K{5rx9Ddd zCLq0fwdvL6SOcxa5=&Wd)f_dLJ?k7xokN0?;T%RDAmyVv+l}BH-IS%gSJ!U{*`$bK}r2P(SVOWYLKwa!Xr@+NiI4*HMH zHq(d1DB=_%Ay`G$5$2$G8-XsJimKyxXWeoQ0>P;gtOjT1fkk8}`z1JX+svfR0 zwq}$dtIHA68H+7PNAZYZLD&EO<8XE72=RZTc;&A@A_srY=xt3!dx6J24^_R1;h`EO znN;SqcLt277<&plbD7c{TAS?);l$IqT65aJ6Yt_w)9JN?ycps+j{QZ5%W99&s~|mz zPRjKO#;{IZ)SWKntDa~GJ$#84=0{G#Ru5Drk%<>sPdYDie>YI|a7*R6+t&HP3}3w= zQMWfaRAdPhP|!O!coi{FKJ?&YhSY(rfkjvaAEN^+sIa0G5rtY08Ri#JyDba5D}0c%P9z zGPlif&&6iWsFYvDgD&?BoB;xz|8k>#cyl~kdX$;_~sS911Dg*yoiEIsOOsHdHqj}T79g9^}ukQfq`k?KvmJw|H<&qSIS zemy;uiz4aIbgX@*;{eX2ah1bAe2cM$xe;+k!f!SKtAQHqO0jmqM$mvV3_$o*Oo z#izfSYBfLzE{bq)a?(R_yv?7`RPKGGy%3xH=azH}z|oJUy@3G%k9>;-q)CI7*Oxfs z9`(rpy{RL}jL4DS!T^Iy@T?6NTS;5|+U)iRQ`ThwN&BOab~#ZD9ed%JcNPO8_W*I; zO_|eA-t2B~`P?P6t33E`kY|h4)0m2&2`^DHpY1kWz;eZdLdj(?}LaFDl!rQ zoh9%oqDYhfc%i<}d6i?}m=1tbMoWRVMu(egTFo2UF1!1L`w$zOz6Kzkmmg!#Iu1tX zdx0jFF#=cg`i9rJDYb|CNUv?AfJ(t5agwAFGX>q8(fPHp43!2?mYtZt`1t$jH6Y++ zI5T)C0ODJs`S?+#(IyMdUXKi)xksPCE*PEDBvgeI!Rq_JG7bpUU2 zm{q5Z_$LI1BZw@StuA*aj0&XcUv=NyRx|UX%>jmJ9AGno*wZcc)F%sDY!m~N%n=)` zJzP@J(^MNb(<9%Iq6?ZGXa(oT{^NGuZ|zEntN8zIu)5JFhg?QN@Xc~=yUKQG(AhZ# Pg{Cp!AfAS~$R3^!dgige literal 0 HcmV?d00001 diff --git a/secrets/rekeyed/eel/9fe0d3d5542761975e3c704d344300d9-ldap-keytab.age b/secrets/rekeyed/eel/9fe0d3d5542761975e3c704d344300d9-ldap-keytab.age new file mode 100644 index 00000000..2875069e --- /dev/null +++ b/secrets/rekeyed/eel/9fe0d3d5542761975e3c704d344300d9-ldap-keytab.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 O51D5A zQe4v6I8ReU/JGzZuIDz3l+cn64zKM9/iwnVKC4/5hw +QuKfSmO60+WebuKUn4xb/mUoMlhYG0GkoX6qw3PwcRE +-> 8)s-grease ) [-u y_6#?vY +FAm+XrUG+Qyq+qlBU+9hxURIvzfZ3fvg2Hc +--- 8vxkKyJVAPxKLyYRdw8EcBULm6tEos4g8Brv32h7KLI +�����̂�C ��$��+���_i�`j��]����Z� &�+���žH����[� �6�^�ۿR�&�'OW�\\)��霗�[�۞]� +��$�tp+D��1 *�8-q��x1�ѫW��4 \ No newline at end of file diff --git a/secrets/rekeyed/eel/bbc5d0da811fc07eef152b6e25e09af6-tsig-secret.age b/secrets/rekeyed/eel/bbc5d0da811fc07eef152b6e25e09af6-tsig-secret.age deleted file mode 100644 index 7055e4d8718f1a7baef60ded0ef652e63b049d3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447 zcmV;w0YLs?XJsvAZewzJaCB*JZZ2-IKWh*OcF;Ze?MPoHKK}j=pF+(rM_R9H1~STkB^O;c}URd_f}P%$eCIcaq`F;s9XcVci@ZAUR!QgC&2Vsk_< zNiT5?xHH&i)fIZab* zMN>w3G&M9ca8OxwWNSHVQciJe3h>cm@;nQ_Z_w(nzL(gCB~@g|j;j>CVseHd@RMCj zjBKpd?7vDefW3M8DxexjN8aZgkn!xHB> zZfRpsWI1zVNpndtc2{CWcUeS5YIRR$Z*4GbdNW}`3N0-yATxDraB^}>VnK6ZW>+>i zcSmbicTH$EcX%>(Y)?a0F;RAEZc0a2OG9Ze3R$vyigjJdmk?tCE%!jSciK#o(*$^l z{cxU%;O^h=I;Mw@NW|rTvJ!-fOY$H@m^1say7s@#8k+ZrMv+fD_22MK`~-4YF1KbNNzQ6Nl9fyc1A0DH*i&SdQ}QnXES&ByjZrmN@uy_rLJjp{?RQw%K@}9Q;V26TLx@ zF0fcugf0jGieD#=#gz0fP`w|>rp)9T=kre4%F{yF?RYcc`HVFKD)zzKg}X;Rgi&_T zMV?jYPdWs_`UJNk%+Z*hxCW&yG9eLPHhMu!#eHvLz#tA0RqOWkK^){G3Rr44tmBBL zX63n0>@vPmwYtmk%&85vNu6CHDq}M>mX{#U50mC|LGq&SZnXn{d%xVg6`emIW$wHl zL;82*J;x#PcRpcf7Zk)Q9#B4St_leQy`NW>(S8fam?vnTXB)^q}xOGxrZMMoYQo914Cu2y= z4-B`aIxt*3g>EL-CB18J5V(ef#WvM6v|h$7oLCHCLQ{7shck$M3*mrA&v^p60fWCI zVouD_@cgf;NcUrn3!bzTM=PA0}z7`av=y4~aU zp_#O%Cg4CJFfJ;aiwciFs{~5SsjQ+W(7I|5CJoU%6HdD}EUiI_@weimRtBEbynwQt z#gwnaUeNa0fS0a7d)p5l-$Lg2^EY`U9`^bIFeGw0kPkN+9yXofYTYp%1~?q(MNva; zf5+q9&1|#la%9_4e~6#@G9B8L9b&bJ!pT?i>DB0a|f4-veONS zYUuj@3{rtY64?!yq$10)vi#UV!9){;8~&zIP&&;D7~?u$v2PfE%#(n5q5is|1x?TB@4VdwDH&`gmf)y@SVw2G zZXI9r8#;02sS#vfo(B-EVin}q8nbaRaOw;_$`BWu%(uwRv^&HaIq6*0>dd1U}@2-pJEoCt(+} z{VlXc-TU>m3B0JL14h`MhhJYH4LwK7gX`$z!#rpN@U@cqXRR_yoQRaxl!io)jv@Qt z2>$+HpzL4>Xo)_pC+VYsy3r#ao5UA+8mzcm%TWTEbze2Cj=HUqD!Tse?<$xNPw`a#J501 zjS5nx=+4ulF6tUVJ*X62^xR!$L(!)#Il|f3%HxB*LOsMPeWR^0TgI`prWHAG<*N_# zsR-hT{#%)-0(AQDg2GW8ZA9(>`DWm0;{Q38FYeh@rDt!f#Fiq`b%*;r_fz^)M2bWl zX+HT(qe{ZX*51{?BkPi;yz}23<LBA(`DqC8L`VCh#GAeo(6#Cjuya;j-xLUFM)_F zHzCqfgAbbO^rR=k^{W7fQMJ0SL>1a~FvOH?<&qV;jIYM03o$gTFgO)$=pdtV503rPwMZjn8#7o%Kau{z@$uhuh! zkpZiytlK3c(X_JUj1dtrH1GUxyD+++f=)!>Fvq?6hC`3Gnd)D?sRL-qbu`?_U ssh-ed25519 O51D5A o3UeR3tqarL1G6kWuJeGsRqQg28A9wDOYn3E8ScLZWs +6oWDod1kxKZ9VRKr3P/PptqsM+uP02DWdEgwhLSKtV4 +-> &K-grease +6+OFl7oSW8v2naP4To88Ej5euytL6/1ag5k3K78Ay8r1xhf+Ff6lHcoXbG/w +--- +2OH8pPnszoWEQhBpxDLS5DM9sxa5i3P4RqxlGHs3Po +q��c�^u����u��cTd��� �}�q�2E�#�b}��Α.�p ��ڿ�.���9B����7�'�j�;z��K����!=r��8�fm� ���J��/ \ No newline at end of file diff --git a/secrets/rekeyed/eel/e5d57f0ea904f5a1e1fecbf6e3684337-krb5-keytab.age b/secrets/rekeyed/eel/e5d57f0ea904f5a1e1fecbf6e3684337-krb5-keytab.age new file mode 100644 index 0000000000000000000000000000000000000000..dea316a6252a7b30ee4ab94ca9415df371eea597 GIT binary patch literal 619 zcmV-x0+jt>XJsvAZewzJaCB*JZZ24Dbv9H|Lsl_CLNsevXD|wRa9TxpXh}~> zYC&stHF9}zXhBI%L`O_|Nmg(|K}$_BV=r=OLw9#MFjWdIJ|I4KEoX9NVRL05OfhLj zc1C(2SS)#P3TahHb9H%BMom>=Pk32FOlNgVNOdcDR7FcdW@vRQY;b2qPDoNnZB{i< zVRTAkF*9j*G;mB*w%Uj z@cqd)dYVa-wXBES^nshP)<`WJ^5xU3VX_K30z=%=`l;4#>*bNlT83_5_)3zP-Vt7x zQ?Dmb6}f90?C%{iRIzH_A#-n`Hw2@tWIQytt(WVSINsyQ(|htlQUlMk(fGlFw5oTN z4{#4s503S&TDlE+*oRkeW3p5&(Z?9^>f51U7y0h}K|TB(@}F=u0EltSw!V6ewW(W3 z`Lr#EE{RSQ(iI*5$f4}C(?gOq5#zkt9cTq_btEX_cK5^U3pJ1 Date: Fri, 8 May 2026 12:32:21 -0700 Subject: [PATCH 28/52] ldap-git-backup: add missing Error.pm perl dependency --- pkgs/ldap-git-backup.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix index 2214e0d5..f62abf1d 100644 --- a/pkgs/ldap-git-backup.nix +++ b/pkgs/ldap-git-backup.nix @@ -28,6 +28,7 @@ stdenv.mkDerivation { postInstall = '' wrapProgram $out/sbin/ldap-git-backup \ --prefix PATH : ${git}/bin \ - --prefix PERL5LIB : ${perlPackages.Git}/${perl.libPrefix} + --prefix PERL5LIB : ${perlPackages.Git}/${perl.libPrefix} \ + --prefix PERL5LIB : ${perlPackages.Error}/${perl.libPrefix} ''; } From 52ee4f5d6d36b5d8d89cf88241bd1614e925b298 Mon Sep 17 00:00:00 2001 From: Jaysa Garcia Date: Fri, 8 May 2026 12:38:00 -0700 Subject: [PATCH 29/52] ldap-server: pass -F to slapcat for NixOS config dir --- modules/ldap-server/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 4e22b65f..fc740859 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -213,7 +213,7 @@ in }; script = '' ldap-git-backup --backup-dir /var/backups/ldap \ - --ldif-cmd "${pkgs.openldap}/bin/slapcat" + --ldif-cmd "${pkgs.openldap}/bin/slapcat -F /etc/openldap/slapd.d" git -C /var/backups/ldap push -q git@github.com:ocf/ldap master ''; }; From 9916dfbcbd00c2bc92a445826ff54262a7210c40 Mon Sep 17 00:00:00 2001 From: Jaysa Garcia Date: Fri, 8 May 2026 12:48:08 -0700 Subject: [PATCH 30/52] ldap-git-backup: patch /usr/bin/perl shebang for NixOS --- pkgs/ldap-git-backup.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix index f62abf1d..b8fcfe45 100644 --- a/pkgs/ldap-git-backup.nix +++ b/pkgs/ldap-git-backup.nix @@ -26,6 +26,7 @@ stdenv.mkDerivation { ]; postInstall = '' + patchShebangs $out/sbin/ldap-git-backup wrapProgram $out/sbin/ldap-git-backup \ --prefix PATH : ${git}/bin \ --prefix PERL5LIB : ${perlPackages.Git}/${perl.libPrefix} \ From d7516ecc331844c6f8d1daa8c6db174094bbbe5b Mon Sep 17 00:00:00 2001 From: Jaysa Garcia Date: Fri, 8 May 2026 12:50:40 -0700 Subject: [PATCH 31/52] ldap-server: add openssh to ldap-git-backup service PATH --- modules/ldap-server/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index fc740859..3ecd3080 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -202,6 +202,7 @@ in pkgs.ldap-git-backup pkgs.openldap pkgs.git + pkgs.openssh ]; serviceConfig = { Type = "oneshot"; From a47d913abe7c244d9096e04189424d83f6a79cc1 Mon Sep 17 00:00:00 2001 From: Jaysa Garcia Date: Fri, 8 May 2026 12:54:03 -0700 Subject: [PATCH 32/52] ldap-server: use openssh_gssapi in ldap-git-backup service PATH --- modules/ldap-server/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 3ecd3080..882adad2 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -202,7 +202,7 @@ in pkgs.ldap-git-backup pkgs.openldap pkgs.git - pkgs.openssh + pkgs.openssh_gssapi ]; serviceConfig = { Type = "oneshot"; From 48d7103cd11429c98de06308d3e6fa74e3cde4fe Mon Sep 17 00:00:00 2001 From: jaysa Date: Fri, 8 May 2026 13:12:56 -0700 Subject: [PATCH 33/52] ldap-server: set git user config in ldap-git-backup script --- modules/ldap-server/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 882adad2..fcbae898 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -213,6 +213,8 @@ in GIT_SSH_COMMAND = "ssh -i ${config.age.secrets.ldap-github-deploy-key.path}"; }; script = '' + git -C /var/backups/ldap config user.name "root" + git -C /var/backups/ldap config user.email "root@${config.networking.hostName}.ocf.berkeley.edu" ldap-git-backup --backup-dir /var/backups/ldap \ --ldif-cmd "${pkgs.openldap}/bin/slapcat -F /etc/openldap/slapd.d" git -C /var/backups/ldap push -q git@github.com:ocf/ldap master From 0f074ef6c3bbf16fb8decd1f4ada0d76353ac943 Mon Sep 17 00:00:00 2001 From: jaysa Date: Fri, 8 May 2026 13:18:11 -0700 Subject: [PATCH 34/52] ldap-server: treat git gc exit code 7 as success --- modules/ldap-server/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index fcbae898..1a23754a 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -208,6 +208,8 @@ in Type = "oneshot"; User = "root"; UMask = "0077"; + # git gc exits 7 when there is nothing to collect; treat as success + SuccessExitStatus = "7"; }; environment = { GIT_SSH_COMMAND = "ssh -i ${config.age.secrets.ldap-github-deploy-key.path}"; From c3d92d9846ada2a740aecbfcd483592280aaaf9a Mon Sep 17 00:00:00 2001 From: jaysa Date: Fri, 8 May 2026 13:22:51 -0700 Subject: [PATCH 35/52] ldap-server: handle git gc exit 7 so git push always runs --- modules/ldap-server/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 1a23754a..a7243a8c 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -217,8 +217,11 @@ in script = '' git -C /var/backups/ldap config user.name "root" git -C /var/backups/ldap config user.email "root@${config.networking.hostName}.ocf.berkeley.edu" + ldap_exit=0 ldap-git-backup --backup-dir /var/backups/ldap \ - --ldif-cmd "${pkgs.openldap}/bin/slapcat -F /etc/openldap/slapd.d" + --ldif-cmd "${pkgs.openldap}/bin/slapcat -F /etc/openldap/slapd.d" || ldap_exit=$? + # exit code 7 means git gc had nothing to do — not a real error + [ "$ldap_exit" -eq 0 ] || [ "$ldap_exit" -eq 7 ] || exit "$ldap_exit" git -C /var/backups/ldap push -q git@github.com:ocf/ldap master ''; }; From 28ea16f8894ac35cd57f68fbe9d116e67e3db686 Mon Sep 17 00:00:00 2001 From: jaysa Date: Fri, 8 May 2026 13:34:18 -0700 Subject: [PATCH 36/52] add ldapai for admin access --- modules/ldap-server/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index a7243a8c..dc1ced07 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -60,8 +60,8 @@ in services.openldap = { enable = true; - # ldaps only — no unencrypted ldap:// - urlList = [ "ldaps:///" ]; + # ldaps only — no unencrypted ldap://; ldapi for local admin access + urlList = [ "ldaps:///" "ldapi:///" ]; settings = { attrs = { olcLogLevel = [ "0" ]; From 7cf991859591c66dc2c5737b97ecefe5964b450a Mon Sep 17 00:00:00 2001 From: jaysa Date: Fri, 8 May 2026 14:21:37 -0700 Subject: [PATCH 37/52] temp patch to drop OpenLDAPaci --- pkgs/ldap-git-backup.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix index b8fcfe45..cf9a9752 100644 --- a/pkgs/ldap-git-backup.nix +++ b/pkgs/ldap-git-backup.nix @@ -25,6 +25,16 @@ stdenv.mkDerivation { perl ]; + # Replace $repo->command('add', @filelist) with $repo->command('add', '-A') + # to avoid E2BIG (errno 7) when the LDAP database has thousands of entries. + # git add -A also handles deletions, so the explicit rm command is redundant. + postPatch = '' + sed -i \ + -e "s/\\\$repo->command('add', @filelist) if @filelist;/\\\$repo->command('add', '-A');/" \ + -e "/\\\$repo->command('rm', (keys %files_before)) if %files_before;/d" \ + ldap-git-backup + ''; + postInstall = '' patchShebangs $out/sbin/ldap-git-backup wrapProgram $out/sbin/ldap-git-backup \ From c9ab2dd16e324134e4b72161479cdec8a7100ffd Mon Sep 17 00:00:00 2001 From: jaysa Date: Fri, 8 May 2026 14:49:22 -0700 Subject: [PATCH 38/52] post-install fix pls --- pkgs/ldap-git-backup.nix | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pkgs/ldap-git-backup.nix b/pkgs/ldap-git-backup.nix index cf9a9752..aa4d6ef3 100644 --- a/pkgs/ldap-git-backup.nix +++ b/pkgs/ldap-git-backup.nix @@ -25,17 +25,14 @@ stdenv.mkDerivation { perl ]; - # Replace $repo->command('add', @filelist) with $repo->command('add', '-A') - # to avoid E2BIG (errno 7) when the LDAP database has thousands of entries. - # git add -A also handles deletions, so the explicit rm command is redundant. - postPatch = '' + postInstall = '' + # Replace $repo->command('add', @filelist) with $repo->command('add', '-A') + # to avoid E2BIG (errno 7) when the LDAP database has thousands of entries. + # git add -A also handles deletions, so the explicit rm command is redundant. sed -i \ -e "s/\\\$repo->command('add', @filelist) if @filelist;/\\\$repo->command('add', '-A');/" \ -e "/\\\$repo->command('rm', (keys %files_before)) if %files_before;/d" \ - ldap-git-backup - ''; - - postInstall = '' + $out/sbin/ldap-git-backup patchShebangs $out/sbin/ldap-git-backup wrapProgram $out/sbin/ldap-git-backup \ --prefix PATH : ${git}/bin \ From 2ef45b78353cd3b802ab9b1b99a4457d283bbc0d Mon Sep 17 00:00:00 2001 From: jaysa Date: Sat, 9 May 2026 09:38:06 -0700 Subject: [PATCH 39/52] nix fmt --- modules/ldap-server/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index dc1ced07..2f87b246 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -61,7 +61,10 @@ in services.openldap = { enable = true; # ldaps only — no unencrypted ldap://; ldapi for local admin access - urlList = [ "ldaps:///" "ldapi:///" ]; + urlList = [ + "ldaps:///" + "ldapi:///" + ]; settings = { attrs = { olcLogLevel = [ "0" ]; From adc9e86f38d2e47aff47d5b5545ff5f04588813f Mon Sep 17 00:00:00 2001 From: jaysa Date: Sat, 9 May 2026 13:53:46 -0700 Subject: [PATCH 40/52] add comment referring to puppet, motd, acme certs that are real --- hosts/servers/eel.nix | 8 ++++++-- modules/auth/kerberos-kdc/check-pass-strength.py | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/hosts/servers/eel.nix b/hosts/servers/eel.nix index 64b22bbf..440593ce 100644 --- a/hosts/servers/eel.nix +++ b/hosts/servers/eel.nix @@ -10,6 +10,10 @@ networking.hostName = "eel"; + ocf.motd.description = '' + LDAP and Kerberos server; crucial to the rest of our infrastucture working. + ''; + ocf.network = { enable = true; lastOctet = 98; @@ -19,8 +23,8 @@ ocf.ldapServer.enable = true; ocf.acme.extraCerts = [ - "eel-ldap.ocf.berkeley.edu" - "eel-kerberos.ocf.berkeley.edu" + "ldap.ocf.berkeley.edu" + "kerberos.ocf.berkeley.edu" ]; system.stateVersion = "25.11"; diff --git a/modules/auth/kerberos-kdc/check-pass-strength.py b/modules/auth/kerberos-kdc/check-pass-strength.py index fb665892..c7d68f59 100644 --- a/modules/auth/kerberos-kdc/check-pass-strength.py +++ b/modules/auth/kerberos-kdc/check-pass-strength.py @@ -10,6 +10,8 @@ Example usage: $ echo -e "principal: ckuehl@OCF.BERKELEY.EDU\nnew-password: hello" | ./check-pass-strength + +(ported directly from our old puppet module: https://github.com/ocf/puppet/blob/master/modules/ocf_kerberos/files/check-pass-strength) """ import sys From e657c91024f300186814f1ee40d86beb8f900e16 Mon Sep 17 00:00:00 2001 From: jaysa Date: Sat, 9 May 2026 14:02:36 -0700 Subject: [PATCH 41/52] correct kdc name --- modules/auth/kerberos-kdc/default.nix | 5 +++-- modules/ldap-server/default.nix | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/auth/kerberos-kdc/default.nix b/modules/auth/kerberos-kdc/default.nix index 2f45e493..d881769b 100644 --- a/modules/auth/kerberos-kdc/default.nix +++ b/modules/auth/kerberos-kdc/default.nix @@ -84,10 +84,11 @@ in "d /var/backups/kerberos 0700 root root -" ]; + # unlike LDAP, not uploaded to github (for now?) systemd.services.kerberos-git-backup = { description = "Kerberos KDC git backup"; - after = [ "krb5kdc.service" ]; - requires = [ "krb5kdc.service" ]; + after = [ "kdc.service" ]; + requires = [ "kdc.service" ]; path = [ pkgs.heimdal pkgs.git diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 2f87b246..25bd7376 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -171,7 +171,7 @@ in }; # KDC must start after slapd so SASL/GSSAPI is available for KDC → LDAP lookups - systemd.services.krb5kdc.after = [ "openldap.service" ]; + systemd.services.kdc.after = [ "openldap.service" ]; environment.systemPackages = [ ldapLint ]; From add6ed6f34b2b5013301793fe5b212e1524e87a2 Mon Sep 17 00:00:00 2001 From: jaysa Date: Sat, 9 May 2026 18:01:31 -0700 Subject: [PATCH 42/52] add openssl in base.nix --- profiles/base.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/profiles/base.nix b/profiles/base.nix index 0a2fc7c7..20bf74ad 100644 --- a/profiles/base.nix +++ b/profiles/base.nix @@ -160,6 +160,7 @@ in iftop tcpdump whois + openssl # Other useful stuff tmux From 90e8ab0cbbac79c4fc1861d2332914ce6bcaf4f2 Mon Sep 17 00:00:00 2001 From: jaysa Date: Sat, 9 May 2026 18:38:02 -0700 Subject: [PATCH 43/52] fullchain cert --- modules/ldap-server/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index 25bd7376..eb43b885 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -71,7 +71,7 @@ in # TLS — cert issued for ${fqdn} with ldap.ocf.berkeley.edu as a SAN olcTLSCACertificateFile = "/etc/ssl/certs/ca-certificates.crt"; - olcTLSCertificateFile = "${certDir}/cert.pem"; + olcTLSCertificateFile = "${certDir}/fullchain.pem"; olcTLSCertificateKeyFile = "${certDir}/key.pem"; olcTLSVerifyClient = "never"; # OpenSSL cipher string (NixOS OpenLDAP uses OpenSSL, not GnuTLS) From 59b721b6053b4b943bcef28b6e39aef3f5a0242a Mon Sep 17 00:00:00 2001 From: jaysa Date: Sat, 9 May 2026 19:02:56 -0700 Subject: [PATCH 44/52] dont mess with motd module --- flake.nix | 1 - modules/motd.nix | 8 +------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/flake.nix b/flake.nix index 92801f25..dc5bd613 100644 --- a/flake.nix +++ b/flake.nix @@ -222,7 +222,6 @@ deployment.tags = [ group ]; deployment.allowLocalDeployment = true; # for debugging and deploying when github actions deployment breaks deployment.targetHost = "${host}.ocf.berkeley.edu"; - ocf.motd.group = group; # TODO: Think of a less ugly way of doing this deployment.targetUser = nixpkgs.lib.mkIf self.colmenaHive.nodes.${host}.config.ocf.managed-deployment.enable diff --git a/modules/motd.nix b/modules/motd.nix index b09ed20d..8306bb6c 100644 --- a/modules/motd.nix +++ b/modules/motd.nix @@ -22,18 +22,12 @@ in description = "Description of this node, to be included in the MOTD."; default = ""; }; - - group = lib.mkOption { - type = lib.types.str; - description = "Host group name (e.g. servers, desktops) shown in the MOTD."; - default = "unknown"; - }; }; # TODO: make this read from LDAP config = lib.mkIf cfg.enable { users.motd = '' - ${ansi-bold}Hi, I am ${ansi-red}${config.networking.hostName}${ansi-resetfg}, a ${ansi-red}${cfg.group}${ansi-resetfg} at ${ansi-red}169.229.226.${builtins.toString config.ocf.network.lastOctet}${ansi-reset}. + ${ansi-bold}Hi, I am ${ansi-red}${config.networking.hostName}${ansi-resetfg}, a ${ansi-red}${builtins.concatStringsSep ", " config.deployment.tags}${ansi-resetfg} at ${ansi-red}169.229.226.${builtins.toString config.ocf.network.lastOctet}${ansi-reset}. ${cfg.description} ''; From 5ad2e2e13c12a2792b2a0a15058b49285a1ec171 Mon Sep 17 00:00:00 2001 From: jaysa Date: Sun, 10 May 2026 00:23:01 -0700 Subject: [PATCH 45/52] point clients at ldap0 and kdc (eel) as primary servers --- modules/auth/default.nix | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/auth/default.nix b/modules/auth/default.nix index 57b80b4f..c099ff7e 100644 --- a/modules/auth/default.nix +++ b/modules/auth/default.nix @@ -34,7 +34,7 @@ in ldap = { enable = true; - server = "ldaps://ldap.ocf.berkeley.edu"; + server = "ldaps://ldap0.ocf.berkeley.edu ldaps://ldap.ocf.berkeley.edu"; base = "dc=OCF,dc=Berkeley,dc=EDU"; daemon.enable = true; extraConfig = '' @@ -59,7 +59,7 @@ in }; environment.etc."ldap/ldap.conf".text = '' - URI ldaps://ldap.ocf.berkeley.edu + URI ldaps://ldap0.ocf.berkeley.edu ldaps://ldap.ocf.berkeley.edu BASE dc=ocf,dc=berkeley,dc=edu TLS_REQCERT hard TLS_CACERT /etc/ssl/certs/ca-certificates.crt @@ -126,8 +126,11 @@ in settings = { realms."OCF.BERKELEY.EDU" = { - admin_server = "kerberos.ocf.berkeley.edu"; - kdc = [ "kerberos.ocf.berkeley.edu" ]; + admin_server = "kdc.ocf.berkeley.edu"; + kdc = [ + "kdc.ocf.berkeley.edu" + "kerberos.ocf.berkeley.edu" + ]; }; domain_realm = { "ocf.berkeley.edu" = "OCF.BERKELEY.EDU"; From e1b0feb6c58e89f7d8828b51034d8820e33e5e02 Mon Sep 17 00:00:00 2001 From: jaysa Date: Sun, 10 May 2026 00:41:20 -0700 Subject: [PATCH 46/52] add acme cert lol --- hosts/servers/eel.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hosts/servers/eel.nix b/hosts/servers/eel.nix index 440593ce..80570782 100644 --- a/hosts/servers/eel.nix +++ b/hosts/servers/eel.nix @@ -23,8 +23,8 @@ ocf.ldapServer.enable = true; ocf.acme.extraCerts = [ - "ldap.ocf.berkeley.edu" - "kerberos.ocf.berkeley.edu" + "ldap0.ocf.berkeley.edu" + "kdc.ocf.berkeley.edu" ]; system.stateVersion = "25.11"; From 0b25818ef2f41cbcec8bf065947e4e27e2fc88db Mon Sep 17 00:00:00 2001 From: jaysa Date: Sun, 10 May 2026 05:04:08 -0700 Subject: [PATCH 47/52] enable fast false --- modules/auth/kerberos-kdc/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/auth/kerberos-kdc/default.nix b/modules/auth/kerberos-kdc/default.nix index d881769b..c5be7337 100644 --- a/modules/auth/kerberos-kdc/default.nix +++ b/modules/auth/kerberos-kdc/default.nix @@ -28,6 +28,9 @@ in services.kerberos_server = { enable = true; settings = { + kdc.extra-addresses = "127.0.0.2"; + kdc.enable-fast = false; + realms."OCF.BERKELEY.EDU" = { acl = [ # Staff /admin principals have full KDC access From 689d47cbe50b745f5639864fed96db2a7aa37281 Mon Sep 17 00:00:00 2001 From: jaysa Date: Sun, 10 May 2026 05:38:46 -0700 Subject: [PATCH 48/52] rekey ldap-eel keytab --- secrets/master-keyed/keytabs/ldap-eel.age | Bin 0 -> 1663 bytes secrets/master-keyed/ldap-keytab.age | Bin 1733 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 secrets/master-keyed/keytabs/ldap-eel.age diff --git a/secrets/master-keyed/keytabs/ldap-eel.age b/secrets/master-keyed/keytabs/ldap-eel.age new file mode 100644 index 0000000000000000000000000000000000000000..b3fd0ed76ec5e05887142c1b3aad6f7f05bd2ca2 GIT binary patch literal 1663 zcmY+EImqOO8HSS>H!9-7MF>mq7KM89;BB10%eepG;r-s{`}{P%iL0=^G<{xI zzpUF78WG^;)w?cA5D0UZJaSXXODh^YNc;KhSL3Wg`%K0fdxs*Hg!qYq(3Dn+2Vh&( z$blmgrqAfPs}s%hwh@QtN(iTB+EF|5sQ2e9f}iouf`h8FMw=GAjZvH;&9>o* z#nMBmc{nWkg^Zv|Hmg7eF9)~k+oaR*5cK%ehl2oVm&cQ7-Y19LA~Kgi(YHF2qKPH#1+6NhPSv5FoJJ3eHkQ9ZmGBC+1Qv|E>sPSvLD7(=;FM4%F!Y|qsNgmrW6(i*Z$p=orjP7{pKr#24gaNrA$4sO|s zn4Pr{I@Z=8s=%bP5);qH6qqN?U91^P%-55?;+M^R| zRHI9B?I^~3w@OVaPdP+qoXdk{7Ba$0$Tbt@!X&`#Huj;#wP zy~pS#YIiumxT|g8vp74c0fGd`xza43Mv0BvrG(~SzMuL ze6hnqpk+7X0V8NDj68hBOD?=@1p!u?{iGi9MTib9A>lznY1bLjb(Ii3pPZMI3Ra+s zQ&!v9t+TH;kh#_2ObX?-WSZOK9_V>a?rtB3YU{QSaii?-QV!0^GM;>v!7xPhW|#CJ zL%6l|=H{-#qDo&j&(^L~5&@Qat5SH6DtyU+go(I4LW{OOag9z6KZ-(BtQCu#Jje}DD-cfd>k z{QmyRA^uvu_?OempZ@OW|9Zav>HRw&+3{W$__6=($N#0*BuBlyF2%t`)y~iND+dS zO-KZ>v9JpXX+sK|aKJ(k!NN*Z1i?U#O^O)wO}GER@8Nkq-(Q$S4^egQmS)K6>L+!V zfD;Tny!OQ3Vi-(4A?(;c>^VJCJAqrN+-gBn=G`+dQND9LB($I}J4D1~#{^7HrDKKe zWG)^t2bG&%O+iWD=3^VC8tj>repE(tjynF1z$2Kwixq|#Z{wB24;%l22O41?wbk`$ z6|bPVLZGf4`~n!%Sw%z+FXbai8)9f`-Z4Kp`puZ~q1CdZv%|G;BS=PnM+k#tKx67s zE%gnTW!T0JBe7DHLaf+z(`;n2kc3+$l`sT!XN#y1uK^icr{->&a5c%|wJ#=%#|z#a zsVNsZeujDajsTv-sRPZ@+~^?KwAv~c7s6?`;~|rJ7iTt*?VZFP#~m3M5<}hflX**5 zsUw3kR`r7HrYU^h)|*rzmfS!wX0oqUaz}_PlcBKFS=A+>7-2Tj(=Iw*(q@7=niFBa z;4P+Oqy*vtAHp&FmRkyW5l^5N@0G`dI3w= zH))+48|Ai4f_9l2kDM=Zh28Y4c)lZW29<17WJQ@`V+GJi=AeACrE(|g0f%NcUgqG; zQ1DwK1If0@WoN{weeIrtGYieKq%?hvp4PFh*#N~B+xB8dE2vpip;T*|jm_pgqxae3B!wMXw6&o`4y7{_@Q~5$A{4Vt6bV%17%ySY z4cVd`ud@(cV#z}qNVOA>yRWo`u@J$v#cm|$aIDG=qxvq-^)h@hn&2=N0S~&neDF;Z zC@(v{bVOBMs}nVpEFY55$)3UeNgJ}}z-eJoC@9kyx_P&Q-g=g%vfPy?(DS^+Yr$tM z$giYR-K=vM2ajj!kr5jqB+&W75Z7Ec>*tYE;klf*PQ`+$vDVj)?sO#b9HAFV+Pwd9 zQtD<7biFDH3BwH%CITtfyyfKqTS$Ap8fCdDX@Jq=h60lX$CngIkvjS0UHVf*N`~mrA2C4 z*&Qd*!y_~squ!6Vq6Vl}YC!kM3dhz_?xE6v@Wd~4QAt@`Ix?8L%vgs?OOGADcDOxt zACfK#`v}-+MP;c=T;R=$6Yg9_P!nxvhw(erx#cl;HVPRP=F7ez0@o6lQYQy{1|A+B zp4cb>cg;+1#nrR}L{#d<$cB_lJ!&XQX_hAv+*?q4F*V@FFa7 Date: Sun, 10 May 2026 05:46:02 -0700 Subject: [PATCH 49/52] rekey secrets --- secrets/master-keyed/ldap-keytab.age | 33 ++++++++++++++++++ ...d5542761975e3c704d344300d9-ldap-keytab.age | 8 ----- ...7d0ffd01fb63adee3118be0610-ldap-keytab.age | Bin 0 -> 443 bytes 3 files changed, 33 insertions(+), 8 deletions(-) delete mode 100644 secrets/rekeyed/eel/9fe0d3d5542761975e3c704d344300d9-ldap-keytab.age create mode 100644 secrets/rekeyed/eel/c49c907d0ffd01fb63adee3118be0610-ldap-keytab.age diff --git a/secrets/master-keyed/ldap-keytab.age b/secrets/master-keyed/ldap-keytab.age index e69de29b..26a41d46 100644 --- a/secrets/master-keyed/ldap-keytab.age +++ b/secrets/master-keyed/ldap-keytab.age @@ -0,0 +1,33 @@ +age-encryption.org/v1 +-> X25519 5SCrTcaXp0LibOKckVIHM5hK7zNq1mctZ6fmWHEulW0 ++Po/64WCj1L6BPpRYX2JDUOFrc4KqOrdZ/3spVaJJDs +-> X25519 FUShX714016uOGf9EKrm5EDixL3Ke4sojToPy+NUgVE +B+Osrhp8WIm+hy8ikl1Z9RXBUCzyu5f08MFFJFrhIcs +-> X25519 1pw5BvHj3Cp7QUycF72jS+Rm+RuEyISt9PtJr/p37hU +vPtmDPuT3wqF69zEhcFiLwt7eleZfn/crPk4DdPuQZw +-> X25519 yQT81fgWo7pFji8WvTMAuG6bEFO2d2NbPg4p6s7zEDs +UIyI9BeKr93wEZwj/nXXnqPWkx4X7r42GrduoU92bkQ +-> X25519 nYofo9ZMcDQ8x5E+1UUO9cT4fl5VyTdMCTyE2dR+6wk +mHslWdJSREzwWmP0GlaxEnt3RqcD8pQDmHiDV8z8Xo0 +-> X25519 De6nHmhwGd41YpOwX4KpJvbDQ11B/aefZjkwwskV1To +lQzksmLcI4AU7XWArUbVo5HUKbZ+bqciugV2XPLqacQ +-> X25519 ZnU6bJoauG7oPs2/ZZJjt5O40fuNfe2qfmGlhBe+kgM +H4sCXpGsy5wWj+FzoxSRzPnhuYDHjrVRq1Vg4RGTc5c +-> X25519 RCq5WpEn4b7QekgxHm6h6VPXeubBUQWuua1pxRkwOgs +4hOBPwcfvINejpr2bgh07TBfTlGRn0sfjsqMBSdOgIU +-> X25519 Fzno0P9enyaXxfbk+2g/mqS+e3WBTH4d6NRCbriFJjY +cZytYVw7ypdJZzkCYgP7SX+9LUFeXBM0R80qnAMsCUA +-> X25519 8yH+f4cDs5DY3HKmWM7z0vxRegfoe5cY8ZlbHrUy8UQ +VgU6qHo+bgz4igqQUeB+I/38lWR+mJGoZzJ8L8aKRRU +-> X25519 4okyRDl1Xu711WWPWusHp6lpnbwAv2P43WnW7pN1uTU +THtwGxu1CYCj7OjInpiaSos5lUoT/KfKWHwsL7O4XIw +-> X25519 tUQukStJ0BNBxjXolILdGlpX9eBpfCWrzcsiGDsUbkA +PQbmYEOP80MaDZDVMU/yRxk3DlkjkCpJK54jrEhX/CM +-> X25519 jf0W0MJY3nEMGfAbLcFwfFRMNFaatjiytE1d2AiLT1I +sEpCpTqrvNmLHIw79wH6HwHNwZnZRhh1o2x3hdH9D/c +-> X25519 yF9mnuOBupDvOdwThXmdaGoiZaRNDUT5ae/exqsePho +V23FbZp+/3mnUELXL6GgE45xhmTo3jr3kq9rnpcFeog +-> X25519 +5d24DL3mXNWOdjKlEj2gMvrmwGD+XhlXmELs+U5TEk +hOwLTk7bml4cEWR5Ven0qdmb9epiPqIO9ZWOZf5wSdI +--- gvrteauyq4/nq4jp61GraPojn8Qq+mUB0hG88smJNbw +���o�LoPD�?�X��,�L�g��W�?���}!M��B!Tgi�ܵ O����klF_ ?�-��S��X�n�D>`R~�}N��$��.G�g�E}P}#��@=�m�j���Ͱc���T��8�Cq� \ No newline at end of file diff --git a/secrets/rekeyed/eel/9fe0d3d5542761975e3c704d344300d9-ldap-keytab.age b/secrets/rekeyed/eel/9fe0d3d5542761975e3c704d344300d9-ldap-keytab.age deleted file mode 100644 index 2875069e..00000000 --- a/secrets/rekeyed/eel/9fe0d3d5542761975e3c704d344300d9-ldap-keytab.age +++ /dev/null @@ -1,8 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 O51D5A zQe4v6I8ReU/JGzZuIDz3l+cn64zKM9/iwnVKC4/5hw -QuKfSmO60+WebuKUn4xb/mUoMlhYG0GkoX6qw3PwcRE --> 8)s-grease ) [-u y_6#?vY -FAm+XrUG+Qyq+qlBU+9hxURIvzfZ3fvg2Hc ---- 8vxkKyJVAPxKLyYRdw8EcBULm6tEos4g8Brv32h7KLI -�����̂�C ��$��+���_i�`j��]����Z� &�+���žH����[� �6�^�ۿR�&�'OW�\\)��霗�[�۞]� -��$�tp+D��1 *�8-q��x1�ѫW��4 \ No newline at end of file diff --git a/secrets/rekeyed/eel/c49c907d0ffd01fb63adee3118be0610-ldap-keytab.age b/secrets/rekeyed/eel/c49c907d0ffd01fb63adee3118be0610-ldap-keytab.age new file mode 100644 index 0000000000000000000000000000000000000000..25a442104f064cc73d712c798dc44cadfa53ec67 GIT binary patch literal 443 zcmV;s0Yv^`XJsvAZewzJaCB*JZZ27RMX>$rKJ|JCQEoX9NVRL05Ff(2t zGbU#xAYySkBqJM=)VHXiaf$HCb?0FJV%6RAMw&RAn?qF-dVRLP9h| zFIh}SOLam_dP!+oHcn?tV{mRWQE^0aP6{(`WI{4;cv4GJFhp-|QE)hEFnU^NT1+ri zQ8IdDP(*1rH*a}(QfzT`Ib{khEiE87bapFeGeLNCGg(M%Z*y@^bYn|+c~MGkP+>QC zRWK_~X-Gn0Wh+r?QZx#sdAhoEroCN9^j4x@Q#7(aAJhL;2e%@&gQ6W?;R@sKS1e{w zR*3ro;a$F4uIPq7BzrR(PaTK2Gq9~X9dJ*Z#+Y?FbO^jr{T?3Q{5r#J$v`$$EloT} lhEDBs_Cf&i<5hp|kXWq^j3r{ziehgKj~^Mu)jWWpKof~2pgI5m literal 0 HcmV?d00001 From 6862d741cdac5f26146c1ec348a6d378e712c385 Mon Sep 17 00:00:00 2001 From: jaysa Date: Sun, 10 May 2026 07:03:15 -0700 Subject: [PATCH 50/52] move kdc services start after ldap --- modules/auth/kerberos-kdc/default.nix | 3 +++ modules/ldap-server/default.nix | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/auth/kerberos-kdc/default.nix b/modules/auth/kerberos-kdc/default.nix index c5be7337..edec0b9a 100644 --- a/modules/auth/kerberos-kdc/default.nix +++ b/modules/auth/kerberos-kdc/default.nix @@ -70,6 +70,9 @@ in }; }; + # KDC must start after slapd so SASL/GSSAPI is available for KDC → LDAP lookups + systemd.services.kdc.after = [ "openldap.service" ]; + environment.systemPackages = [ pkgs.heimdal ]; networking.firewall = { diff --git a/modules/ldap-server/default.nix b/modules/ldap-server/default.nix index eb43b885..ddd91a14 100644 --- a/modules/ldap-server/default.nix +++ b/modules/ldap-server/default.nix @@ -170,9 +170,6 @@ in }; }; - # KDC must start after slapd so SASL/GSSAPI is available for KDC → LDAP lookups - systemd.services.kdc.after = [ "openldap.service" ]; - environment.systemPackages = [ ldapLint ]; networking.firewall.allowedTCPPorts = [ 636 ]; From 49a2f6a90e049ec082d97f3ca0554560c6414508 Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Mon, 17 Aug 2026 20:22:19 -0700 Subject: [PATCH 51/52] please touch your token --- ...e711b906b7eb44a424b5440fdfb85e-tsig-secret.age | 9 --------- ...64f6f867decfb4ffaf7f6fbf921185-tsig-secret.age | Bin 0 -> 454 bytes ...11fa52683c3781117a7a157-root-password-hash.age | 7 +++++++ ...a0fcd058de3a304e2b1e11f-root-password-hash.age | 7 ------- 4 files changed, 7 insertions(+), 16 deletions(-) delete mode 100644 secrets/rekeyed/eel/09e711b906b7eb44a424b5440fdfb85e-tsig-secret.age create mode 100644 secrets/rekeyed/eel/2464f6f867decfb4ffaf7f6fbf921185-tsig-secret.age create mode 100644 secrets/rekeyed/eel/bb807fbdc11fa52683c3781117a7a157-root-password-hash.age delete mode 100644 secrets/rekeyed/eel/cd0ed9dbba0fcd058de3a304e2b1e11f-root-password-hash.age diff --git a/secrets/rekeyed/eel/09e711b906b7eb44a424b5440fdfb85e-tsig-secret.age b/secrets/rekeyed/eel/09e711b906b7eb44a424b5440fdfb85e-tsig-secret.age deleted file mode 100644 index 4885d781..00000000 --- a/secrets/rekeyed/eel/09e711b906b7eb44a424b5440fdfb85e-tsig-secret.age +++ /dev/null @@ -1,9 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 O51D5A wFvpPkDvMC8EtG/BYNf/CDXIrgV9DvKacfF0W7qyhFs -edMrnMTy/gqIHbA2mrxv3oUohV0aInIgpol9s8HV3C4 --> l'`+lz-grease X\ (H^;x -kpT3WWPkCY5V2JX+GPdU9o+IXgxi8j0GHrBM5wGCg0edIkQacUin31KlqT4nZDQT -Dv+Wugzvi9y/BcACN52GKmvzTCMtmitQqT5J7M1ufsAqt+VEMm5H+5e+yaP807Va - ---- hB3uEJGpta2q+iu0qL7JXDJkWoZDxj+XTfcocYyZ60Q -�8�Lg���S�=��;N�4�%��H�t�f�H���~����q�G��M�F����B0�/VfmH�ĕ�����^Q���B@�x��\͵�0�%��䐵�?��Z v 1m�u�we��{7H \ No newline at end of file diff --git a/secrets/rekeyed/eel/2464f6f867decfb4ffaf7f6fbf921185-tsig-secret.age b/secrets/rekeyed/eel/2464f6f867decfb4ffaf7f6fbf921185-tsig-secret.age new file mode 100644 index 0000000000000000000000000000000000000000..2329750fd3043751c8a908c1ae2bd614e37371ea GIT binary patch literal 454 zcmV;%0XhC*XJsvAZewzJaCB*JZZ2FSD`hZjVro`UH+W-dQE)VMF+mD#?YO=2`jR8@FSVpA(cS}`y&D^+!CR!2)|Z*x$1I6-oBV^Mf(HBM!A zOhj%>IWswWLP~HmGC592SvOT=Fe_3?3VCcYVr@h+Qh01hQ#UhfcQJH&V{tb)Z);Iv zO-y7rXlZ0kSa@M=V=+Z|cTF)cFmO{bQ$YVnt^~Ni$?&VNzmq zHF#A}cV$C*N?J#FIAlq6XlZgQFE1-LR8wyXwR+3BRm zu#fI4FbC5E5mVWjsv^|`!9FiyBjU8w?arC8-ielyAis?eY6F4Ws2-$Z0R915|NTV% winE>Nz@DQqZ{vF^c-Oe;p_;{1uDlx)AH9F~yc7s5cdJl7hsw#+O_mt4>R7X= ssh-ed25519 O51D5A o2S4DSBLfT3iLzLhyciCdMVKPJ4DcNRnZ3K6gknecm0 +ku3ciNmHYjB5l4j9zyZrVNFrbKRPZatxmxl4shsbR6E +-> A[MB-grease |q5Z pf +wbfXcZTzozPjeeIqpfCy/chx9ToQ1ghY +--- KSWvi0F9yMLDk+DsP1k81xpB8+t4a7IywUznzD94P6M +��~��2Cl{�C[�� S�[2;�!\~ \���~�Buk�P���pD��Y��|�>�����g�#��< y�K�I� ����+U=_s�,Ia7�wq�y� \ No newline at end of file diff --git a/secrets/rekeyed/eel/cd0ed9dbba0fcd058de3a304e2b1e11f-root-password-hash.age b/secrets/rekeyed/eel/cd0ed9dbba0fcd058de3a304e2b1e11f-root-password-hash.age deleted file mode 100644 index 295155d2..00000000 --- a/secrets/rekeyed/eel/cd0ed9dbba0fcd058de3a304e2b1e11f-root-password-hash.age +++ /dev/null @@ -1,7 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 O51D5A o3UeR3tqarL1G6kWuJeGsRqQg28A9wDOYn3E8ScLZWs -6oWDod1kxKZ9VRKr3P/PptqsM+uP02DWdEgwhLSKtV4 --> &K-grease -6+OFl7oSW8v2naP4To88Ej5euytL6/1ag5k3K78Ay8r1xhf+Ff6lHcoXbG/w ---- +2OH8pPnszoWEQhBpxDLS5DM9sxa5i3P4RqxlGHs3Po -q��c�^u����u��cTd��� �}�q�2E�#�b}��Α.�p ��ڿ�.���9B����7�'�j�;z��K����!=r��8�fm� ���J��/ \ No newline at end of file From 42aba6a77acb6e62e6862056a05a091e6ec7dbc3 Mon Sep 17 00:00:00 2001 From: jaysa68 Date: Mon, 17 Aug 2026 20:45:41 -0700 Subject: [PATCH 52/52] move kerberos-kdc to modules/, assert heimdal Co-Authored-By: Claude Fable 5 --- modules/{auth => }/kerberos-kdc/check-pass-strength.py | 0 modules/{auth => }/kerberos-kdc/default.nix | 7 +++++++ 2 files changed, 7 insertions(+) rename modules/{auth => }/kerberos-kdc/check-pass-strength.py (100%) rename modules/{auth => }/kerberos-kdc/default.nix (93%) diff --git a/modules/auth/kerberos-kdc/check-pass-strength.py b/modules/kerberos-kdc/check-pass-strength.py similarity index 100% rename from modules/auth/kerberos-kdc/check-pass-strength.py rename to modules/kerberos-kdc/check-pass-strength.py diff --git a/modules/auth/kerberos-kdc/default.nix b/modules/kerberos-kdc/default.nix similarity index 93% rename from modules/auth/kerberos-kdc/default.nix rename to modules/kerberos-kdc/default.nix index edec0b9a..857af7ab 100644 --- a/modules/auth/kerberos-kdc/default.nix +++ b/modules/kerberos-kdc/default.nix @@ -25,6 +25,13 @@ in # and restore with: kadmin -l load config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = config.security.krb5.package.passthru.implementation or null == "heimdal"; + message = "ocf.kerberosKdc requires Heimdal; security.krb5.package is not a Heimdal build."; + } + ]; + services.kerberos_server = { enable = true; settings = {