longview service: don't write passwords to nix store

Adds services.longview.{apiKeyFile,mysqlPasswordFile} options as
alternatives to apiKey and mysqlPassword, which still work, but are
deprecated with a warning message.

Related to #24288.

+82 -35
+76 -34
nixos/modules/services/monitoring/longview.nix
··· 5 let 6 cfg = config.services.longview; 7 8 - pidFile = "/run/longview.pid"; 9 - 10 - apacheConf = optionalString (cfg.apacheStatusUrl != "") '' 11 - location ${cfg.apacheStatusUrl}?auto 12 - ''; 13 - mysqlConf = optionalString (cfg.mysqlUser != "") '' 14 - username ${cfg.mysqlUser} 15 - password ${cfg.mysqlPassword} 16 - ''; 17 - nginxConf = optionalString (cfg.nginxStatusUrl != "") '' 18 - location ${cfg.nginxStatusUrl} 19 - ''; 20 - 21 - in 22 23 - { 24 options = { 25 26 services.longview = { ··· 35 36 apiKey = mkOption { 37 type = types.str; 38 example = "01234567-89AB-CDEF-0123456789ABCDEF"; 39 description = '' 40 Longview API key. To get this, look in Longview settings which 41 are found at https://manager.linode.com/longview/. 42 ''; 43 }; 44 ··· 77 78 mysqlPassword = mkOption { 79 type = types.str; 80 description = '' 81 - The password corresponding to mysqlUser. Warning: this is 82 - stored in cleartext in the Nix store! 83 ''; 84 }; 85 }; 86 87 }; ··· 94 serviceConfig.Type = "forking"; 95 serviceConfig.ExecStop = "-${pkgs.coreutils}/bin/kill -TERM $MAINPID"; 96 serviceConfig.ExecReload = "-${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 97 - serviceConfig.PIDFile = pidFile; 98 serviceConfig.ExecStart = "${pkgs.longview}/bin/longview"; 99 }; 100 101 - environment.etc."linode/longview.key" = { 102 - mode = "0400"; 103 - text = cfg.apiKey; 104 - }; 105 - environment.etc."linode/longview.d/Apache.conf" = { 106 - mode = "0400"; 107 - text = apacheConf; 108 - }; 109 - environment.etc."linode/longview.d/MySQL.conf" = { 110 - mode = "0400"; 111 - text = mysqlConf; 112 - }; 113 - environment.etc."linode/longview.d/Nginx.conf" = { 114 - mode = "0400"; 115 - text = nginxConf; 116 - }; 117 }; 118 }
··· 5 let 6 cfg = config.services.longview; 7 8 + runDir = "/run/longview"; 9 + configsDir = "${runDir}/longview.d"; 10 11 + in { 12 options = { 13 14 services.longview = { ··· 23 24 apiKey = mkOption { 25 type = types.str; 26 + default = ""; 27 example = "01234567-89AB-CDEF-0123456789ABCDEF"; 28 description = '' 29 Longview API key. To get this, look in Longview settings which 30 are found at https://manager.linode.com/longview/. 31 + 32 + Warning: this secret is stored in the world-readable Nix store! 33 + Use <option>apiKeyFile</option> instead. 34 + ''; 35 + }; 36 + 37 + apiKeyFile = mkOption { 38 + type = types.nullOr types.path; 39 + default = null; 40 + example = "/run/keys/longview-api-key"; 41 + description = '' 42 + A file containing the Longview API key. 43 + To get this, look in Longview settings which 44 + are found at https://manager.linode.com/longview/. 45 + 46 + <option>apiKeyFile</option> takes precedence over <option>apiKey</option>. 47 ''; 48 }; 49 ··· 82 83 mysqlPassword = mkOption { 84 type = types.str; 85 + default = ""; 86 description = '' 87 + The password corresponding to <option>mysqlUser</option>. 88 + Warning: this is stored in cleartext in the Nix store! 89 + Use <option>mysqlPasswordFile</option> instead. 90 + ''; 91 + }; 92 + 93 + mysqlPasswordFile = mkOption { 94 + type = types.nullOr types.path; 95 + default = null; 96 + example = "/run/keys/dbpassword"; 97 + description = '' 98 + A file containing the password corresponding to <option>mysqlUser</option>. 99 ''; 100 }; 101 + 102 }; 103 104 }; ··· 111 serviceConfig.Type = "forking"; 112 serviceConfig.ExecStop = "-${pkgs.coreutils}/bin/kill -TERM $MAINPID"; 113 serviceConfig.ExecReload = "-${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 114 + serviceConfig.PIDFile = "${runDir}/longview.pid"; 115 serviceConfig.ExecStart = "${pkgs.longview}/bin/longview"; 116 + preStart = '' 117 + umask 077 118 + mkdir -p ${configsDir} 119 + '' + (optionalString (cfg.apiKeyFile != null) '' 120 + cp --no-preserve=all "${cfg.apiKeyFile}" ${runDir}/longview.key 121 + '') + (optionalString (cfg.apacheStatusUrl != "") '' 122 + cat > ${configsDir}/Apache.conf <<EOF 123 + location ${cfg.apacheStatusUrl}?auto 124 + EOF 125 + '') + (optionalString (cfg.mysqlUser != "" && cfg.mysqlPasswordFile != null) '' 126 + cat > ${configsDir}/MySQL.conf <<EOF 127 + username ${cfg.mysqlUser} 128 + password `head -n1 "${cfg.mysqlPasswordFile}"` 129 + EOF 130 + '') + (optionalString (cfg.nginxStatusUrl != "") '' 131 + cat > ${configsDir}/Nginx.conf <<EOF 132 + location ${cfg.nginxStatusUrl} 133 + EOF 134 + ''); 135 }; 136 137 + warnings = let warn = k: optional (cfg.${k} != "") 138 + "config.services.longview.${k} is insecure. Use ${k}File instead."; 139 + in concatMap warn [ "apiKey" "mysqlPassword" ]; 140 + 141 + assertions = [ 142 + { assertion = cfg.apiKeyFile != null; 143 + message = "Longview needs an API key configured"; 144 + } 145 + ]; 146 + 147 + # Create API key file if not configured. 148 + services.longview.apiKeyFile = mkIf (cfg.apiKey != "") 149 + (mkDefault (toString (pkgs.writeTextFile { 150 + name = "longview.key"; 151 + text = cfg.apiKey; 152 + }))); 153 + 154 + # Create MySQL password file if not configured. 155 + services.longview.mysqlPasswordFile = mkDefault (toString (pkgs.writeTextFile { 156 + name = "mysql-password-file"; 157 + text = cfg.mysqlPassword; 158 + })); 159 }; 160 }
+6 -1
pkgs/servers/monitoring/longview/default.nix
··· 16 ./log-stdout.patch 17 ]; 18 19 postPatch = '' 20 - substituteInPlace Linode/Longview/Util.pm --replace /var/run/longview.pid /run/longview.pid 21 ''; 22 23 buildInputs = [ perl makeWrapper glibc ]
··· 16 ./log-stdout.patch 17 ]; 18 19 + # Read all configuration from /run/longview 20 postPatch = '' 21 + substituteInPlace Linode/Longview/Util.pm \ 22 + --replace /var/run/longview.pid /run/longview/longview.pid \ 23 + --replace /etc/linode /run/longview 24 + substituteInPlace Linode/Longview.pl \ 25 + --replace /etc/linode /run/longview 26 ''; 27 28 buildInputs = [ perl makeWrapper glibc ]