nixos/dhparams: Clean up module expression

First of all let's start with a clean up the multiline string
indentation for descriptions, because having two indentation levels
after description is a waste of screen estate.

A quick survey in the form of the following also reveals that the
majority of multiline strings in nixpkgs is starting the two beginning
quotes in the same line:

$ find -name '*.nix' -exec sed -n -e '/=$/ { n; /'\'\''/p }' {} + | wc -l
817
$ find -name '*.nix' -exec grep "= *'' *\$" {} + | wc -l
14818

The next point is to get the type, default and example attributes on top
of the description because that's the way it's rendered in the manual.

Most services have their enable option close to the beginning of the
file, so let's move it to the top.

Also, I found the script attribute for dhparams-init.service a bit hard
to read as it was using string concatenation to split a "for" loop.

Now for the more substantial clean ups rather than just code style:

  * Remove the "with lib;" at the beginning of the module, because it
    makes it easier to do a quick check with "nix-instantiate --parse".
  * Use ConditionPathExists instead of test -e for checking whether we
    need to generate the dhparams file. This avoids spawning a shell if
    the file exists already and it's probably more common that it will
    exist, except for the initial creation of course.
  * When cleaning up old dhparams file, use RemainAfterExit so that the
    unit won't be triggered again whenever we stop and start a service
    depending on it.
  * Capitalize systemd unit descriptions to be more in par with most
    other unit descriptions (also see 0c5e837b66).
  * Use "=" instead of "==" for conditionals using []. It's just a very
    small nitpick though and it will only fail for POSIX shells. Bash on
    the other side accepts it anyway.

Signed-off-by: aszlig <aszlig@nix.build>
Cc: @Ekleog
This commit is contained in:
aszlig 2018-04-26 07:11:54 +02:00
parent 3e11ff6e0d
commit ce87773867
No known key found for this signature in database
GPG Key ID: 684089CE67EBB691

View File

@ -1,8 +1,7 @@
{ config, lib, pkgs, ... }:
with lib;
let
inherit (lib) mkOption types;
cfg = config.security.dhparams;
paramsSubmodule = { name, config, ... }: {
@ -39,32 +38,39 @@ let
in {
options = {
security.dhparams = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to generate new DH params and clean up old DH params.
'';
};
params = mkOption {
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>
'';
type = with types; let
coerce = bits: { inherit bits; };
in attrsOf (coercedTo types.int coerce (submodule paramsSubmodule));
in attrsOf (coercedTo int coerce (submodule paramsSubmodule));
default = {};
example = literalExample "{ nginx.bits = 3072; }";
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>
'';
};
stateful = mkOption {
@ -84,77 +90,67 @@ in {
};
path = mkOption {
type = types.str;
default = "/var/lib/dhparams";
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>.
'';
type = types.str;
default = "/var/lib/dhparams";
};
enable = mkOption {
description =
''
Whether to generate new DH params and clean up old DH params.
'';
default = false;
type = types.bool;
};
};
};
config = mkIf (cfg.enable && cfg.stateful) {
config = lib.mkIf (cfg.enable && cfg.stateful) {
systemd.services = {
dhparams-init = {
description = "Cleanup old Diffie-Hellman parameters";
wantedBy = [ "multi-user.target" ]; # Clean up even when no DH params is set
serviceConfig.Type = "oneshot";
script =
# Create directory
''
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
'' + concatStrings (mapAttrsToList (name: { bits, ... }:
''
if [ "$file" == "${cfg.path}/${name}.pem" ] && \
${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
description = "Clean Up Old Diffie-Hellman Parameters";
# 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}
'';
};
} //
mapAttrs' (name: { bits, ... }: nameValuePair "dhparams-gen-${name}" {
description = "Generate Diffie-Hellman parameters for ${name} if they don't exist yet";
after = [ "dhparams-init.service" ];
before = [ "${name}.service" ];
# Clean up even when no DH params is set
wantedBy = [ "multi-user.target" ];
serviceConfig.RemainAfterExit = true;
serviceConfig.Type = "oneshot";
script =
''
script = ''
if [ ! -d ${cfg.path} ]; then
mkdir -p ${cfg.path}
if [ ! -f ${cfg.path}/${name}.pem ]; then
${pkgs.openssl}/bin/openssl dhparam -out ${cfg.path}/${name}.pem ${toString bits}
fi
# Remove old dhparams
for file in ${cfg.path}/*; do
if [ ! -f "$file" ]; then
continue
fi
'';
}) cfg.params;
${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;
};
}