From acbeb604ce82cee6aae8226730d32014f4167682 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 5 Oct 2025 23:12:38 +0200 Subject: [PATCH] nixos/sssd: migrate to rfc42-style settings --- nixos/modules/security/ipa.nix | 68 +++++++++++++------------ nixos/modules/services/misc/sssd.nix | 50 +++++++++++++++++- nixos/tests/all-tests.nix | 2 +- nixos/tests/sssd-ldap.nix | 34 +++++++------ nixos/tests/sssd-legacy-config.nix | 37 ++++++++++++++ nixos/tests/sssd.nix | 22 -------- pkgs/os-specific/linux/sssd/default.nix | 2 +- 7 files changed, 140 insertions(+), 75 deletions(-) create mode 100644 nixos/tests/sssd-legacy-config.nix delete mode 100644 nixos/tests/sssd.nix diff --git a/nixos/modules/security/ipa.nix b/nixos/modules/security/ipa.nix index dd01aaf26b21..eded8dd6bcd2 100644 --- a/nixos/modules/security/ipa.nix +++ b/nixos/modules/security/ipa.nix @@ -7,7 +7,6 @@ with lib; let cfg = config.security.ipa; - pyBool = x: if x then "True" else "False"; ldapConf = pkgs.writeText "ldap.conf" '' # Turning this off breaks GSSAPI used with krb5 when rdns = false @@ -236,50 +235,53 @@ in services.sssd = { enable = true; - config = '' - [domain/${cfg.domain}] - id_provider = ipa - auth_provider = ipa - access_provider = ipa - chpass_provider = ipa + settings = { + "domain/${cfg.domain}" = { + id_provider = "ipa"; + auth_provider = "ipa"; + access_provider = "ipa"; + chpass_provider = "ipa"; - ipa_domain = ${cfg.domain} - ipa_server = _srv_, ${cfg.server} - ipa_hostname = ${cfg.ipaHostname} + ipa_domain = cfg.domain; + ipa_server = "_srv_, ${cfg.server}"; + ipa_hostname = cfg.ipaHostname; - cache_credentials = ${pyBool cfg.cacheCredentials} - krb5_store_password_if_offline = ${pyBool cfg.offlinePasswords} - ${optionalString ((toLower cfg.domain) != (toLower cfg.realm)) "krb5_realm = ${cfg.realm}"} + cache_credentials = cfg.cacheCredentials; + krb5_store_password_if_offline = cfg.offlinePasswords; + krb5_realm = lib.mkIf ((toLower cfg.domain) != (toLower cfg.realm)) cfg.realm; - dyndns_update = ${pyBool cfg.dyndns.enable} - dyndns_iface = ${cfg.dyndns.interface} + dyndns_update = cfg.dyndns.enable; + dyndns_iface = cfg.dyndns.interface; - ldap_tls_cacert = /etc/ipa/ca.crt - ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber, lock:nsaccountlock + ldap_tls_cacert = "/etc/ipa/ca.crt"; + ldap_user_extra_attrs = "mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber, lock:nsaccountlock"; + }; - [sssd] - services = nss, sudo, pam, ssh, ifp - domains = ${cfg.domain} + sssd = { + services = "nss, sudo, pam, ssh, ifp"; + domains = cfg.domain; + }; - [nss] - homedir_substring = /home + nss.homedir_substring = "/home"; - [pam] - pam_pwd_expiration_warning = 3 - pam_verbosity = 3 + pam = { + pam_pwd_expiration_warning = 3; + pam_verbosity = 3; + }; - [sudo] + sudo = { }; - [autofs] + autofs = { }; - [ssh] + ssh = { }; - [pac] + pac = { }; - [ifp] - user_attributes = +mail, +telephoneNumber, +givenname, +sn, +lock - allowed_uids = ${concatStringsSep ", " cfg.ifpAllowedUids} - ''; + ifp = { + user_attributes = "+mail, +telephoneNumber, +givenname, +sn, +lock"; + allowed_uids = concatStringsSep ", " cfg.ifpAllowedUids; + }; + }; }; networking.timeServers = singleton cfg.server; diff --git a/nixos/modules/services/misc/sssd.nix b/nixos/modules/services/misc/sssd.nix index 11374f9c014d..05351a040916 100644 --- a/nixos/modules/services/misc/sssd.nix +++ b/nixos/modules/services/misc/sssd.nix @@ -6,20 +6,59 @@ }: let cfg = config.services.sssd; + settingsFormat = pkgs.formats.ini { }; dataDir = "/var/lib/sssd"; settingsFile = "${dataDir}/sssd.conf"; - settingsFileUnsubstituted = pkgs.writeText "${dataDir}/sssd-unsubstituted.conf" cfg.config; + mkSettingsFileUnsubstituted = + settings: + let + pyBool = x: if x then "True" else "False"; + finalSettings = lib.mapAttrs ( + _: lib.mapAttrs (_: v: if lib.isBool v then pyBool v else v) + ) settings; + in + settingsFormat.generate "sssd-unsubstituted.conf" finalSettings; + settingsFileUnsubstituted = + if cfg.settings == { } then + pkgs.writeText "sssd-unsubstituted.conf" cfg.config + else + mkSettingsFileUnsubstituted cfg.settings; in { options = { services.sssd = { enable = lib.mkEnableOption "the System Security Services Daemon"; + settings = lib.mkOption { + inherit (settingsFormat) type; + description = "Contents of {file}`sssd.conf`."; + default = { }; + example = { + sssd = { + services = "nss, pam"; + domains = "shadowutils"; + }; + + nss = { }; + + pam = { }; + + "domain/shadowutils" = { + id_provider = "proxy"; + proxy_lib_name = "files"; + auth_provider = "proxy"; + proxy_pam_target = "sssd-shadowutils"; + proxy_fast_alias = true; + }; + }; + }; + config = lib.mkOption { type = lib.types.lines; description = "Contents of {file}`sssd.conf`."; - default = '' + default = ""; + example = '' [sssd] services = nss, pam domains = shadowutils @@ -80,6 +119,13 @@ in }; config = lib.mkMerge [ (lib.mkIf cfg.enable { + assertions = [ + { + assertion = lib.xor (cfg.settings != { }) (cfg.config != ""); + message = "services.sssd.settings and services.sssd.config are mutually exclusive"; + } + ]; + # For `sssctl` to work. environment.etc."sssd/sssd.conf".source = settingsFile; environment.etc."sssd/conf.d".source = "${dataDir}/conf.d"; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 0d35e82c5fa1..47d731555364 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -1372,8 +1372,8 @@ in ssh-audit = runTest ./ssh-audit.nix; sshwifty = runTest ./web-apps/sshwifty/default.nix; sslh = handleTest ./sslh.nix { }; - sssd = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./sssd.nix { }; sssd-ldap = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./sssd-ldap.nix { }; + sssd-legacy-config = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./sssd-legacy-config.nix { }; stalwart-mail = runTest ./stalwart/stalwart-mail.nix; stargazer = runTest ./web-servers/stargazer.nix; starship = runTest ./starship.nix; diff --git a/nixos/tests/sssd-ldap.nix b/nixos/tests/sssd-ldap.nix index 9d18ef64f39d..f60232945adc 100644 --- a/nixos/tests/sssd-ldap.nix +++ b/nixos/tests/sssd-ldap.nix @@ -112,23 +112,25 @@ import ./make-test-python.nix ( enable = true; # just for testing purposes, don't put this into the Nix store in production! environmentFile = "${pkgs.writeText "ldap-root" "LDAP_BIND_PW=${ldapRootPassword}"}"; - config = '' - [sssd] - config_file_version = 2 - services = nss, pam, sudo - domains = ${dbDomain} + settings = { + sssd = { + config_file_version = 2; + services = "nss, pam, sudo"; + domains = dbDomain; + }; - [domain/${dbDomain}] - auth_provider = ldap - id_provider = ldap - ldap_uri = ldaps://127.0.0.1:636 - ldap_tls_reqcert = allow - ldap_tls_cacert = /etc/cert.pem - ldap_search_base = ${dbSuffix} - ldap_default_bind_dn = cn=${ldapRootUser},${dbSuffix} - ldap_default_authtok_type = password - ldap_default_authtok = $LDAP_BIND_PW - ''; + "domain/${dbDomain}" = { + auth_provider = "ldap"; + id_provider = "ldap"; + ldap_uri = "ldaps://127.0.0.1:636"; + ldap_tls_reqcert = "allow"; + ldap_tls_cacert = "/etc/cert.pem"; + ldap_search_base = dbSuffix; + ldap_default_bind_dn = "cn=${ldapRootUser},${dbSuffix}"; + ldap_default_authtok_type = "password"; + ldap_default_authtok = "$LDAP_BIND_PW"; + }; + }; }; }; diff --git a/nixos/tests/sssd-legacy-config.nix b/nixos/tests/sssd-legacy-config.nix new file mode 100644 index 000000000000..f394c16fdea1 --- /dev/null +++ b/nixos/tests/sssd-legacy-config.nix @@ -0,0 +1,37 @@ +import ./make-test-python.nix ( + { pkgs, ... }: + + { + name = "sssd-legacy-config"; + meta = with pkgs.lib.maintainers; { + maintainers = [ bbigras ]; + }; + nodes.machine.services.sssd = { + enable = true; + config = # ini + '' + [sssd] + services = nss, pam + domains = shadowutils + + [nss] + + [pam] + + [domain/shadowutils] + id_provider = proxy + proxy_lib_name = files + auth_provider = proxy + proxy_pam_target = sssd-shadowutils + proxy_fast_alias = True + ''; + }; + + testScript = '' + start_all() + machine.wait_for_unit("multi-user.target") + machine.wait_for_unit("sssd.service") + machine.succeed("sssctl config-check") + ''; + } +) diff --git a/nixos/tests/sssd.nix b/nixos/tests/sssd.nix deleted file mode 100644 index 5622eadf4e16..000000000000 --- a/nixos/tests/sssd.nix +++ /dev/null @@ -1,22 +0,0 @@ -import ./make-test-python.nix ( - { pkgs, ... }: - - { - name = "sssd"; - meta = with pkgs.lib.maintainers; { - maintainers = [ bbigras ]; - }; - nodes.machine = - { pkgs, ... }: - { - services.sssd.enable = true; - }; - - testScript = '' - start_all() - machine.wait_for_unit("multi-user.target") - machine.wait_for_unit("sssd.service") - machine.succeed("sssctl config-check") - ''; - } -) diff --git a/pkgs/os-specific/linux/sssd/default.nix b/pkgs/os-specific/linux/sssd/default.nix index 1072c9aa148f..af643a8b6a67 100644 --- a/pkgs/os-specific/linux/sssd/default.nix +++ b/pkgs/os-specific/linux/sssd/default.nix @@ -221,7 +221,7 @@ stdenv.mkDerivation (finalAttrs: { passthru = { tests = { - inherit (nixosTests) sssd sssd-ldap; + inherit (nixosTests) sssd-ldap sssd-legacy-config; pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; }; updateScript = nix-update-script { };