From bccaac95357abafe114ee20a39a5d9c91253d5bc Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Thu, 14 Jul 2022 23:42:18 +0200 Subject: [PATCH 1/3] nixos/privacyidea: better secret-handling ldap-proxy & RFC42-style settings for ldap-proxy Instead of hard-coding a single `configFile` for `privacyidea-ldap-proxy.service` which is pretty unmergable with other declarations it now uses a RFC42-like approach. Also to make sure that secrets can be handled properly without ending up in the Nix store, it's possible to inject secrets via envsubst { services.privacyidea.ldap-proxy = { enable = true; environmentFile = "/run/secrets/ldap-pw"; settings = { privacyidea.instance = "privacyidea.example.org"; service-account = { dn = "uid=readonly,ou=serviceaccounts,dc=example,dc=org"; password = "$LDAP_PW"; }; }; }; } and the following secret file (at `/run/secrets`): LDAP_PW= For backwards-compat the old `configFile`-option is kept, but it throws a deprecation warning and is mutually exclusive with the `settings`-attrset. Also, it doesn't support secrets injection with `envsubst` & `environmentFile`. --- .../modules/services/security/privacyidea.nix | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/nixos/modules/services/security/privacyidea.nix b/nixos/modules/services/security/privacyidea.nix index c1617348fb01..190feaf657f3 100644 --- a/nixos/modules/services/security/privacyidea.nix +++ b/nixos/modules/services/security/privacyidea.nix @@ -51,6 +51,16 @@ let ${cfg.extraConfig} ''; + renderValue = x: + if isList x then concatMapStringsSep "," (x: ''"${x}"'') x + else if isString x && hasInfix "," x then ''"${x}"'' + else x; + + ldapProxyConfig = pkgs.writeText "ldap-proxy.ini" + (generators.toINI {} + (flip mapAttrs cfg.ldap-proxy.settings + (const (mapAttrs (const renderValue))))); + in { @@ -172,7 +182,8 @@ in enable = mkEnableOption "PrivacyIDEA LDAP Proxy"; configFile = mkOption { - type = types.path; + type = types.nullOr types.path; + default = null; description = '' Path to PrivacyIDEA LDAP Proxy configuration (proxy.ini). ''; @@ -189,6 +200,26 @@ in default = "pi-ldap-proxy"; description = "Group account under which PrivacyIDEA LDAP proxy runs."; }; + + settings = mkOption { + type = with types; attrsOf (attrsOf (oneOf [ str bool int (listOf str) ])); + default = {}; + description = '' + Attribute-set containing the settings for privacyidea-ldap-proxy. + It's possible to pass secrets using env-vars as substitutes and + use the option + to inject them via envsubst. + ''; + }; + + environmentFile = mkOption { + default = null; + type = types.nullOr types.str; + description = '' + Environment file containing secrets to be substituted into + . + ''; + }; }; }; }; @@ -276,6 +307,18 @@ in (mkIf cfg.ldap-proxy.enable { + assertions = [ + { assertion = let + xor = a: b: a && !b || !a && b; + in xor (cfg.ldap-proxy.settings == {}) (cfg.ldap-proxy.configFile == null); + message = "configFile & settings are mutually exclusive for services.privacyidea.ldap-proxy!"; + } + ]; + + warnings = mkIf (cfg.ldap-proxy.configFile != null) [ + "Using services.privacyidea.ldap-proxy.configFile is deprecated! Use the RFC42-style settings option instead!" + ]; + systemd.services.privacyidea-ldap-proxy = let ldap-proxy-env = pkgs.python3.withPackages (ps: [ ps.privacyidea-ldap-proxy ]); in { @@ -284,14 +327,28 @@ in serviceConfig = { User = cfg.ldap-proxy.user; Group = cfg.ldap-proxy.group; - ExecStart = '' + StateDirectory = "privacyidea-ldap-proxy"; + EnvironmentFile = mkIf (cfg.ldap-proxy.environmentFile != null) + cfg.ldap-proxy.environmentFile; + ExecStartPre = mkIf (cfg.ldap-proxy.settings != {}) + "${pkgs.writeShellScript "substitute-secrets-ldap-proxy" '' + set -x + ${pkgs.envsubst}/bin/envsubst \ + -i ${ldapProxyConfig} \ + -o $STATE_DIRECTORY/ldap-proxy.ini + ''}"; + ExecStart = let + configPath = if cfg.ldap-proxy.settings != {} + then "%S/privacyidea-ldap-proxy/ldap-proxy.ini" + else cfg.ldap-proxy.configFile; + in '' ${ldap-proxy-env}/bin/twistd \ --nodaemon \ --pidfile= \ -u ${cfg.ldap-proxy.user} \ -g ${cfg.ldap-proxy.group} \ ldap-proxy \ - -c ${cfg.ldap-proxy.configFile} + -c ${configPath} ''; Restart = "always"; }; From 4adf26f01893ed98f9ebbc55cbf87cb1be57a54a Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Sat, 16 Jul 2022 14:00:46 +0200 Subject: [PATCH 2/3] nixos/privacyidea-ldap-proxy: always run envsubst Otherwise the file doesn't exist at the expected location. --- nixos/modules/services/security/privacyidea.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nixos/modules/services/security/privacyidea.nix b/nixos/modules/services/security/privacyidea.nix index 190feaf657f3..d48266e4a759 100644 --- a/nixos/modules/services/security/privacyidea.nix +++ b/nixos/modules/services/security/privacyidea.nix @@ -330,9 +330,8 @@ in StateDirectory = "privacyidea-ldap-proxy"; EnvironmentFile = mkIf (cfg.ldap-proxy.environmentFile != null) cfg.ldap-proxy.environmentFile; - ExecStartPre = mkIf (cfg.ldap-proxy.settings != {}) + ExecStartPre = "${pkgs.writeShellScript "substitute-secrets-ldap-proxy" '' - set -x ${pkgs.envsubst}/bin/envsubst \ -i ${ldapProxyConfig} \ -o $STATE_DIRECTORY/ldap-proxy.ini From 949c334ea9b9a506cb8644a356f64c30a92ef307 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Mon, 18 Jul 2022 13:58:08 +0200 Subject: [PATCH 3/3] nixos/privacyidea-ldap-proxy: use list for EnvironmentFile for mergeability --- nixos/modules/services/security/privacyidea.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/services/security/privacyidea.nix b/nixos/modules/services/security/privacyidea.nix index d48266e4a759..13e27f255068 100644 --- a/nixos/modules/services/security/privacyidea.nix +++ b/nixos/modules/services/security/privacyidea.nix @@ -329,7 +329,7 @@ in Group = cfg.ldap-proxy.group; StateDirectory = "privacyidea-ldap-proxy"; EnvironmentFile = mkIf (cfg.ldap-proxy.environmentFile != null) - cfg.ldap-proxy.environmentFile; + [ cfg.ldap-proxy.environmentFile ]; ExecStartPre = "${pkgs.writeShellScript "substitute-secrets-ldap-proxy" '' ${pkgs.envsubst}/bin/envsubst \