Merge branch 'unhashed-password' into 'master'
Add support for plaintext password files See merge request simple-nixos-mailserver/nixos-mailserver!474
This commit is contained in:
+13
@@ -178,6 +178,19 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
type =
|
||||
with types;
|
||||
nullOr (pathWith {
|
||||
inStore = false;
|
||||
});
|
||||
default = null;
|
||||
example = "/run/keys/user1-password";
|
||||
description = ''
|
||||
A file containing the user's plain text password. The value will be hashed at runtime.
|
||||
'';
|
||||
};
|
||||
|
||||
aliases = mkOption {
|
||||
type = with types; listOf types.str;
|
||||
example = [
|
||||
|
||||
@@ -45,12 +45,19 @@ rec {
|
||||
in
|
||||
lib.mapAttrs (
|
||||
name: value:
|
||||
if value.hashedPasswordFile == null then
|
||||
if value.hashedPasswordFile != null then
|
||||
value.hashedPasswordFile
|
||||
else if value.hashedPassword != null then
|
||||
builtins.toString (mkHashFile name value.hashedPassword)
|
||||
else
|
||||
value.hashedPasswordFile
|
||||
value.passwordFile
|
||||
) cfg.loginAccounts;
|
||||
|
||||
# Collect accounts with plain text passwords that require hashing
|
||||
accountsWithPlaintextPasswordFiles = lib.filter (
|
||||
name: cfg.loginAccounts.${name}.passwordFile != null
|
||||
) (builtins.attrNames cfg.loginAccounts);
|
||||
|
||||
# Appends the LDAP bind password to files to avoid writing this
|
||||
# password into the Nix store.
|
||||
appendLdapBindPwd =
|
||||
|
||||
@@ -121,7 +121,11 @@ let
|
||||
cat <<EOF > ${passwdFile}
|
||||
${lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (
|
||||
name: _: "${name}:${"$(head -n 1 ${passwordFiles."${name}"})"}::::::"
|
||||
name: _:
|
||||
if lib.elem name accountsWithPlaintextPasswordFiles then
|
||||
"${name}:${"$(sed -n '1{p;p;q}' ${passwordFiles."${name}"} | ${lib.getExe' pkgs.dovecot "doveadm"} pw)"}::::::"
|
||||
else
|
||||
"${name}:${"$(head -n 1 ${passwordFiles."${name}"})"}::::::"
|
||||
) cfg.loginAccounts
|
||||
)}
|
||||
EOF
|
||||
|
||||
@@ -90,8 +90,15 @@ in
|
||||
config = lib.mkIf enable {
|
||||
# assert that all accounts provide a password
|
||||
assertions = map (acct: {
|
||||
assertion = acct.hashedPassword != null || acct.hashedPasswordFile != null;
|
||||
message = "${acct.name} must provide either a hashed password or a password hash file";
|
||||
assertion =
|
||||
lib.length (
|
||||
lib.filter (value: value != null) [
|
||||
acct.hashedPassword
|
||||
acct.hashedPasswordFile
|
||||
acct.passwordFile
|
||||
]
|
||||
) == 1;
|
||||
message = "Login account ${acct.name} must provide exactly one of password file, hashed password, or hashed password file";
|
||||
}) (lib.attrValues loginAccounts);
|
||||
|
||||
# warn for accounts that specify both password and file
|
||||
|
||||
@@ -69,6 +69,15 @@ in
|
||||
netcat
|
||||
]);
|
||||
|
||||
systemd.tmpfiles.settings."mailserver-test-passwords" = {
|
||||
"/run/passwords/user3" = {
|
||||
f = {
|
||||
argument = "my-password";
|
||||
mode = "0600";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mailserver = {
|
||||
enable = true;
|
||||
fqdn = "mail.example.com";
|
||||
@@ -86,6 +95,9 @@ in
|
||||
hashedPasswordFile = hashedPasswordFile;
|
||||
aliasesRegexp = [ ''/^user2.*@domain\.com$/'' ];
|
||||
};
|
||||
"user3@example.com" = {
|
||||
passwordFile = "/run/passwords/user3";
|
||||
};
|
||||
"send-only@example.com" = {
|
||||
hashedPasswordFile = hashPassword "send-only";
|
||||
sendOnly = true;
|
||||
@@ -223,6 +235,25 @@ in
|
||||
"set +o pipefail; curl --unix-socket /run/rspamd/worker-controller.sock http://localhost/ | grep -q '<body>'"
|
||||
)
|
||||
|
||||
with subtest("user with plaintext password file can send and receive"):
|
||||
machine.succeed(
|
||||
" ".join(
|
||||
[
|
||||
"mail-check send-and-read",
|
||||
"--smtp-port 587",
|
||||
"--smtp-starttls",
|
||||
"--smtp-host localhost",
|
||||
"--imap-host localhost",
|
||||
"--imap-username user3@example.com",
|
||||
"--from-addr user3@example.com",
|
||||
"--to-addr user3@example.com",
|
||||
"--src-password-file ${passwordFile}",
|
||||
"--dst-password-file ${passwordFile}",
|
||||
"--ignore-dkim-spf",
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
with subtest("imap port 143 is closed and imaps is serving SSL"):
|
||||
machine.wait_for_closed_port(143)
|
||||
machine.wait_for_open_port(993)
|
||||
|
||||
Reference in New Issue
Block a user