about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/doc/manual/release-notes/rl-1903.xml7
-rw-r--r--nixos/modules/config/ldap.nix65
-rw-r--r--nixos/tests/ldap.nix4
3 files changed, 41 insertions, 35 deletions
diff --git a/nixos/doc/manual/release-notes/rl-1903.xml b/nixos/doc/manual/release-notes/rl-1903.xml
index 7d40637df931..bbd3cf2e9db5 100644
--- a/nixos/doc/manual/release-notes/rl-1903.xml
+++ b/nixos/doc/manual/release-notes/rl-1903.xml
@@ -516,6 +516,13 @@
      Graylog</link> for details.
     </para>
    </listitem>
+   <listitem>
+    <para>
+      The option <literal>users.ldap.bind.password</literal> was renamed to <literal>users.ldap.bind.passwordFile</literal>,
+      and needs to be readable by the <literal>nslcd</literal> user.
+      Same applies to the new <literal>users.ldap.daemon.rootpwmodpwFile</literal> option.
+    </para>
+   </listitem>
   </itemizedlist>
  </section>
 
diff --git a/nixos/modules/config/ldap.nix b/nixos/modules/config/ldap.nix
index b5f6702f1c68..e008497a2a6e 100644
--- a/nixos/modules/config/ldap.nix
+++ b/nixos/modules/config/ldap.nix
@@ -27,25 +27,29 @@ let
     '';
   };
 
-  nslcdConfig = {
-    target = "nslcd.conf";
-    source = writeText "nslcd.conf" ''
-      uid nslcd
-      gid nslcd
-      uri ${cfg.server}
-      base ${cfg.base}
-      timelimit ${toString cfg.timeLimit}
-      bind_timelimit ${toString cfg.bind.timeLimit}
-      ${optionalString (cfg.bind.distinguishedName != "")
-        "binddn ${cfg.bind.distinguishedName}" }
-      ${optionalString (cfg.daemon.rootpwmoddn != "")
-        "rootpwmoddn ${cfg.daemon.rootpwmoddn}" }
-      ${optionalString (cfg.daemon.extraConfig != "") cfg.daemon.extraConfig }
-    '';
-  };
-
-  insertLdapPassword = !config.users.ldap.daemon.enable &&
-    config.users.ldap.bind.distinguishedName != "";
+  nslcdConfig = writeText "nslcd.conf" ''
+    uid nslcd
+    gid nslcd
+    uri ${cfg.server}
+    base ${cfg.base}
+    timelimit ${toString cfg.timeLimit}
+    bind_timelimit ${toString cfg.bind.timeLimit}
+    ${optionalString (cfg.bind.distinguishedName != "")
+      "binddn ${cfg.bind.distinguishedName}" }
+    ${optionalString (cfg.daemon.rootpwmoddn != "")
+      "rootpwmoddn ${cfg.daemon.rootpwmoddn}" }
+    ${optionalString (cfg.daemon.extraConfig != "") cfg.daemon.extraConfig }
+  '';
+
+  # nslcd normally reads configuration from /etc/nslcd.conf.
+  # this file might contain secrets. We append those at runtime,
+  # so redirect its location to something more temporary.
+  nslcdWrapped = runCommandNoCC "nslcd-wrapped" { nativeBuildInputs = [ makeWrapper ]; } ''
+    mkdir -p $out/bin
+    makeWrapper ${nss_pam_ldapd}/sbin/nslcd $out/bin/nslcd \
+      --set LD_PRELOAD    "${pkgs.libredirect}/lib/libredirect.so" \
+      --set NIX_REDIRECTS "/etc/nslcd.conf=/run/nslcd/nslcd.conf"
+  '';
 
 in
 
@@ -220,9 +224,9 @@ in
 
   config = mkIf cfg.enable {
 
-    environment.etc = if cfg.daemon.enable then [nslcdConfig] else [ldapConfig];
+    environment.etc = optional (!cfg.daemon.enable) ldapConfig;
 
-    system.activationScripts = mkIf insertLdapPassword {
+    system.activationScripts = mkIf (!cfg.daemon.enable) {
       ldap = stringAfter [ "etc" "groups" "users" ] ''
         if test -f "${cfg.bind.passwordFile}" ; then
           umask 0077
@@ -251,7 +255,6 @@ in
     };
 
     systemd.services = mkIf cfg.daemon.enable {
-
       nslcd = {
         wantedBy = [ "multi-user.target" ];
 
@@ -259,28 +262,24 @@ in
           umask 0077
           conf="$(mktemp)"
           {
-            cat ${nslcdConfig.source}
+            cat ${nslcdConfig}
             test -z '${cfg.bind.distinguishedName}' -o ! -f '${cfg.bind.passwordFile}' ||
             printf 'bindpw %s\n' "$(cat '${cfg.bind.passwordFile}')"
             test -z '${cfg.daemon.rootpwmoddn}' -o ! -f '${cfg.daemon.rootpwmodpwFile}' ||
             printf 'rootpwmodpw %s\n' "$(cat '${cfg.daemon.rootpwmodpwFile}')"
           } >"$conf"
-          mv -fT "$conf" /etc/nslcd.conf
+          mv -fT "$conf" /run/nslcd/nslcd.conf
         '';
-
-        # NOTE: because one cannot pass a custom config path to `nslcd`
-        # (which is only able to use `/etc/nslcd.conf`)
-        # changes in `nslcdConfig` won't change `serviceConfig`,
-        # and thus won't restart `nslcd`.
-        # Therefore `restartTriggers` is used on `/etc/nslcd.conf`.
-        restartTriggers = [ nslcdConfig.source ];
+        restartTriggers = [ "/run/nslcd/nslcd.conf" ];
 
         serviceConfig = {
-          ExecStart = "${nss_pam_ldapd}/sbin/nslcd";
+          ExecStart = "${nslcdWrapped}/bin/nslcd";
           Type = "forking";
-          PIDFile = "/run/nslcd/nslcd.pid";
           Restart = "always";
+          User = "nslcd";
+          Group = "nslcd";
           RuntimeDirectory = [ "nslcd" ];
+          PIDFile = "/run/nslcd/nslcd.pid";
         };
       };
 
diff --git a/nixos/tests/ldap.nix b/nixos/tests/ldap.nix
index 18a6a2e89feb..fe859876ed25 100644
--- a/nixos/tests/ldap.nix
+++ b/nixos/tests/ldap.nix
@@ -30,7 +30,6 @@ let
         rootpwmoddn = "cn=admin,${dbSuffix}";
         rootpwmodpwFile = "/etc/nslcd.rootpwmodpw";
       };
-      environment.etc."nslcd.rootpwmodpw".source = pkgs.writeText "rootpwmodpw" dbAdminPwd;
       users.ldap.loginPam = true;
       users.ldap.nsswitch = true;
       users.ldap.server = "ldap://server";
@@ -39,8 +38,9 @@ let
         distinguishedName = "cn=admin,${dbSuffix}";
         passwordFile = "/etc/ldap/bind.password";
       };
-      # NOTE: password stored in clear in Nix's store, but this is a test.
+      # NOTE: passwords stored in clear in Nix's store, but this is a test.
       environment.etc."ldap/bind.password".source = pkgs.writeText "password" dbAdminPwd;
+      environment.etc."nslcd.rootpwmodpw".source = pkgs.writeText "rootpwmodpw" dbAdminPwd;
     };
 in