nixpkgs/nixos/modules/security/dhparams.nix
pennae 2e751c0772 treewide: automatically md-convert option descriptions
the conversion procedure is simple:

 - find all things that look like options, ie calls to either `mkOption`
   or `lib.mkOption` that take an attrset. remember the attrset as the
   option
 - for all options, find a `description` attribute who's value is not a
   call to `mdDoc` or `lib.mdDoc`
 - textually convert the entire value of the attribute to MD with a few
   simple regexes (the set from mdize-module.sh)
 - if the change produced a change in the manual output, discard
 - if the change kept the manual unchanged, add some text to the
   description to make sure we've actually found an option. if the
   manual changes this time, keep the converted description

this procedure converts 80% of nixos options to markdown. around 2000
options remain to be inspected, but most of those fail the "does not
change the manual output check": currently the MD conversion process
does not faithfully convert docbook tags like <code> and <package>, so
any option using such tags will not be converted at all.
2022-07-30 15:16:34 +02:00

178 lines
6.1 KiB
Nix

{ config, lib, options, pkgs, ... }:
let
inherit (lib) literalExpression mkOption types;
cfg = config.security.dhparams;
opt = options.security.dhparams;
bitType = types.addCheck types.int (b: b >= 16) // {
name = "bits";
description = "integer of at least 16 bits";
};
paramsSubmodule = { name, config, ... }: {
options.bits = mkOption {
type = bitType;
default = cfg.defaultBitSize;
defaultText = literalExpression "config.${opt.defaultBitSize}";
description = lib.mdDoc ''
The bit size for the prime that is used during a Diffie-Hellman
key exchange.
'';
};
options.path = mkOption {
type = types.path;
readOnly = true;
description = lib.mdDoc ''
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`.
'';
};
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;
};
in {
options = {
security.dhparams = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to generate new DH params and clean up old DH params.
'';
};
params = mkOption {
type = with types; let
coerce = bits: { inherit bits; };
in attrsOf (coercedTo int coerce (submodule paramsSubmodule));
default = {};
example = lib.literalExpression "{ 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>
<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>
'';
};
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>
'';
};
defaultBitSize = mkOption {
type = bitType;
default = 2048;
description = lib.mdDoc ''
This allows to override the default bit size for all of the
Diffie-Hellman parameters set in
{option}`security.dhparams.params`.
'';
};
path = mkOption {
type = types.str;
default = "/var/lib/dhparams";
description = lib.mdDoc ''
Path to the directory in which Diffie-Hellman parameters will be
stored. This only is relevant if
{option}`security.dhparams.stateful` is
`true`.
'';
};
};
};
config = lib.mkIf (cfg.enable && cfg.stateful) {
systemd.services = {
dhparams-init = {
description = "Clean Up Old Diffie-Hellman Parameters";
# Clean up even when no DH params is set
wantedBy = [ "multi-user.target" ];
serviceConfig.RemainAfterExit = true;
serviceConfig.Type = "oneshot";
script = ''
if [ ! -d ${cfg.path} ]; then
mkdir -p ${cfg.path}
fi
# Remove old dhparams
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
continue
fi
'') 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}
'';
};
} // 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;
};
meta.maintainers = with lib.maintainers; [ ekleog ];
}