| 
									
										
										
										
											2017-02-10 18:36:36 +01:00
										 |  |  | { config, lib, pkgs, ... }: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | let | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |   inherit (lib) mkOption types; | 
					
						
							| 
									
										
										
										
											2017-02-10 18:36:36 +01:00
										 |  |  |   cfg = config.security.dhparams; | 
					
						
							| 
									
										
										
										
											2018-04-26 06:19:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-07 04:33:56 +02:00
										 |  |  |   bitType = types.addCheck types.int (b: b >= 16) // { | 
					
						
							|  |  |  |     name = "bits"; | 
					
						
							|  |  |  |     description = "integer of at least 16 bits"; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-26 06:19:48 +02:00
										 |  |  |   paramsSubmodule = { name, config, ... }: { | 
					
						
							|  |  |  |     options.bits = mkOption { | 
					
						
							| 
									
										
										
										
											2018-05-07 04:33:56 +02:00
										 |  |  |       type = bitType; | 
					
						
							|  |  |  |       default = cfg.defaultBitSize; | 
					
						
							| 
									
										
										
										
											2018-04-26 06:19:48 +02:00
										 |  |  |       description = ''
 | 
					
						
							|  |  |  |         The bit size for the prime that is used during a Diffie-Hellman | 
					
						
							|  |  |  |         key exchange. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     options.path = mkOption { | 
					
						
							|  |  |  |       type = types.path; | 
					
						
							|  |  |  |       readOnly = true; | 
					
						
							|  |  |  |       description = ''
 | 
					
						
							|  |  |  |         The resulting path of the generated Diffie-Hellman parameters | 
					
						
							|  |  |  |         file for other services to reference. This could be either a | 
					
						
							|  |  |  |         store path or a file inside the directory specified by | 
					
						
							|  |  |  |         <option>security.dhparams.path</option>. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-26 06:38:02 +02:00
										 |  |  |     config.path = let | 
					
						
							|  |  |  |       generated = pkgs.runCommand "dhparams-${name}.pem" { | 
					
						
							|  |  |  |         nativeBuildInputs = [ pkgs.openssl ]; | 
					
						
							|  |  |  |       } "openssl dhparam -out \"$out\" ${toString config.bits}"; | 
					
						
							|  |  |  |     in if cfg.stateful then "${cfg.path}/${name}.pem" else generated; | 
					
						
							| 
									
										
										
										
											2018-04-26 06:19:48 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | in { | 
					
						
							| 
									
										
										
										
											2017-02-10 18:36:36 +01:00
										 |  |  |   options = { | 
					
						
							|  |  |  |     security.dhparams = { | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |       enable = mkOption { | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							|  |  |  |         default = false; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Whether to generate new DH params and clean up old DH params. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-10 18:36:36 +01:00
										 |  |  |       params = mkOption { | 
					
						
							| 
									
										
										
										
											2018-04-26 06:19:48 +02:00
										 |  |  |         type = with types; let | 
					
						
							|  |  |  |           coerce = bits: { inherit bits; }; | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |         in attrsOf (coercedTo int coerce (submodule paramsSubmodule)); | 
					
						
							| 
									
										
										
										
											2017-02-10 18:36:36 +01:00
										 |  |  |         default = {}; | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |         example = lib.literalExample "{ nginx.bits = 3072; }"; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Diffie-Hellman parameters to generate. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           The value is the size (in bits) of the DH params to generate. The | 
					
						
							|  |  |  |           generated DH params path can be found in | 
					
						
							|  |  |  |           <literal>config.security.dhparams.params.<replaceable>name</replaceable>.path</literal>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           <note><para>The name of the DH params is taken as being the name of | 
					
						
							|  |  |  |           the service it serves and the params will be generated before the | 
					
						
							|  |  |  |           said service is started.</para></note> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           <warning><para>If you are removing all dhparams from this list, you | 
					
						
							|  |  |  |           have to leave <option>security.dhparams.enable</option> for at | 
					
						
							|  |  |  |           least one activation in order to have them be cleaned up. This also | 
					
						
							|  |  |  |           means if you rollback to a version without any dhparams the | 
					
						
							|  |  |  |           existing ones won't be cleaned up. Of course this only applies if | 
					
						
							|  |  |  |           <option>security.dhparams.stateful</option> is | 
					
						
							|  |  |  |           <literal>true</literal>.</para></warning> | 
					
						
							| 
									
										
										
										
											2018-05-07 04:33:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |           <note><title>For module implementers:</title><para>It's recommended | 
					
						
							|  |  |  |           to not set a specific bit size here, so that users can easily | 
					
						
							|  |  |  |           override this by setting | 
					
						
							|  |  |  |           <option>security.dhparams.defaultBitSize</option>.</para></note> | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |         '';
 | 
					
						
							| 
									
										
										
										
											2017-02-10 18:36:36 +01:00
										 |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-26 06:38:02 +02:00
										 |  |  |       stateful = mkOption { | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							|  |  |  |         default = true; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Whether generation of Diffie-Hellman parameters should be stateful or | 
					
						
							|  |  |  |           not. If this is enabled, PEM-encoded files for Diffie-Hellman | 
					
						
							|  |  |  |           parameters are placed in the directory specified by | 
					
						
							|  |  |  |           <option>security.dhparams.path</option>. Otherwise the files are | 
					
						
							|  |  |  |           created within the Nix store. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           <note><para>If this is <literal>false</literal> the resulting store | 
					
						
							|  |  |  |           path will be non-deterministic and will be rebuilt every time the | 
					
						
							|  |  |  |           <package>openssl</package> package changes.</para></note> | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-07 04:33:56 +02:00
										 |  |  |       defaultBitSize = mkOption { | 
					
						
							|  |  |  |         type = bitType; | 
					
						
							|  |  |  |         default = 2048; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           This allows to override the default bit size for all of the | 
					
						
							|  |  |  |           Diffie-Hellman parameters set in | 
					
						
							|  |  |  |           <option>security.dhparams.params</option>. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-10 18:36:36 +01:00
										 |  |  |       path = mkOption { | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |         type = types.str; | 
					
						
							|  |  |  |         default = "/var/lib/dhparams"; | 
					
						
							| 
									
										
										
										
											2018-04-26 06:38:02 +02:00
										 |  |  |         description = ''
 | 
					
						
							|  |  |  |           Path to the directory in which Diffie-Hellman parameters will be | 
					
						
							|  |  |  |           stored. This only is relevant if | 
					
						
							|  |  |  |           <option>security.dhparams.stateful</option> is | 
					
						
							|  |  |  |           <literal>true</literal>. | 
					
						
							|  |  |  |         '';
 | 
					
						
							| 
									
										
										
										
											2017-03-17 01:56:13 +01:00
										 |  |  |       }; | 
					
						
							| 
									
										
										
										
											2017-02-10 18:36:36 +01:00
										 |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |   config = lib.mkIf (cfg.enable && cfg.stateful) { | 
					
						
							| 
									
										
										
										
											2017-03-17 01:56:13 +01:00
										 |  |  |     systemd.services = { | 
					
						
							|  |  |  |       dhparams-init = { | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |         description = "Clean Up Old Diffie-Hellman Parameters"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Clean up even when no DH params is set | 
					
						
							|  |  |  |         wantedBy = [ "multi-user.target" ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         serviceConfig.RemainAfterExit = true; | 
					
						
							| 
									
										
										
										
											2017-03-17 01:56:13 +01:00
										 |  |  |         serviceConfig.Type = "oneshot"; | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         script = ''
 | 
					
						
							|  |  |  |           if [ ! -d ${cfg.path} ]; then | 
					
						
							|  |  |  |             mkdir -p ${cfg.path} | 
					
						
							|  |  |  |           fi | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-17 01:56:13 +01:00
										 |  |  |           # Remove old dhparams | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |           for file in ${cfg.path}/*; do
 | 
					
						
							|  |  |  |             if [ ! -f "$file" ]; then | 
					
						
							|  |  |  |               continue | 
					
						
							|  |  |  |             fi | 
					
						
							|  |  |  |             ${lib.concatStrings (lib.mapAttrsToList (name: { bits, path, ... }: ''
 | 
					
						
							|  |  |  |               if [ "$file" = ${lib.escapeShellArg path} ] && \ | 
					
						
							|  |  |  |                  ${pkgs.openssl}/bin/openssl dhparam -in "$file" -text \ | 
					
						
							|  |  |  |                  | head -n 1 | grep "(${toString bits} bit)" > /dev/null; then | 
					
						
							| 
									
										
										
										
											2017-03-17 01:56:13 +01:00
										 |  |  |                 continue | 
					
						
							|  |  |  |               fi | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |             '') cfg.params)}
 | 
					
						
							|  |  |  |             rm $file | 
					
						
							|  |  |  |           done | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           # TODO: Ideally this would be removing the *former* cfg.path, though | 
					
						
							|  |  |  |           # this does not seem really important as changes to it are quite | 
					
						
							|  |  |  |           # unlikely | 
					
						
							|  |  |  |           rmdir --ignore-fail-on-non-empty ${cfg.path} | 
					
						
							|  |  |  |         '';
 | 
					
						
							| 
									
										
										
										
											2017-03-17 01:56:13 +01:00
										 |  |  |       }; | 
					
						
							| 
									
										
										
										
											2018-04-26 07:11:54 +02:00
										 |  |  |     } // lib.mapAttrs' (name: { bits, path, ... }: lib.nameValuePair "dhparams-gen-${name}" { | 
					
						
							|  |  |  |       description = "Generate Diffie-Hellman Parameters for ${name}"; | 
					
						
							|  |  |  |       after = [ "dhparams-init.service" ]; | 
					
						
							|  |  |  |       before = [ "${name}.service" ]; | 
					
						
							|  |  |  |       wantedBy = [ "multi-user.target" ]; | 
					
						
							|  |  |  |       unitConfig.ConditionPathExists = "!${path}"; | 
					
						
							|  |  |  |       serviceConfig.Type = "oneshot"; | 
					
						
							|  |  |  |       script = ''
 | 
					
						
							|  |  |  |         mkdir -p ${lib.escapeShellArg cfg.path} | 
					
						
							|  |  |  |         ${pkgs.openssl}/bin/openssl dhparam -out ${lib.escapeShellArg path} \ | 
					
						
							|  |  |  |           ${toString bits} | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }) cfg.params; | 
					
						
							| 
									
										
										
										
											2017-03-17 01:56:13 +01:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2018-10-31 01:05:35 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   meta.maintainers = with lib.maintainers; [ ekleog ]; | 
					
						
							| 
									
										
										
										
											2017-02-10 18:36:36 +01:00
										 |  |  | } |