1
0
Fork 0

add vm test for vaultwarden

This commit is contained in:
ibizaman 2024-05-24 15:02:38 -07:00 committed by Pierre Penninckx
parent 8ebb3af1f0
commit 97285e1833
3 changed files with 218 additions and 13 deletions

View file

@ -118,6 +118,7 @@
// (vm_test "nextcloud" ./test/vm/nextcloud.nix) // (vm_test "nextcloud" ./test/vm/nextcloud.nix)
// (vm_test "postgresql" ./test/vm/postgresql.nix) // (vm_test "postgresql" ./test/vm/postgresql.nix)
// (vm_test "ssl" ./test/vm/ssl.nix) // (vm_test "ssl" ./test/vm/ssl.nix)
// (vm_test "vaultwarden" ./test/vm/vaultwarden.nix)
); );
} }
); );

View file

@ -36,26 +36,22 @@ in
default = 8222; default = 8222;
}; };
ldapEndpoint = lib.mkOption {
type = lib.types.str;
description = "Endpoint for LDAP authentication backend.";
example = "ldap.example.com";
};
authEndpoint = lib.mkOption { authEndpoint = lib.mkOption {
type = lib.types.str; type = lib.types.nullOr lib.types.str;
description = "OIDC endpoint for SSO"; description = "OIDC endpoint for SSO";
default = null;
example = "https://authelia.example.com"; example = "https://authelia.example.com";
}; };
databasePasswordFile = lib.mkOption { databasePasswordFile = lib.mkOption {
type = lib.types.str; type = lib.types.path;
description = "File containing the password to connect to the postgresql database."; description = "File containing the password to connect to the postgresql database.";
}; };
smtp = lib.mkOption { smtp = lib.mkOption {
description = "SMTP options."; description = "SMTP options.";
type = lib.types.submodule { default = null;
type = lib.types.nullOr (lib.types.submodule {
options = { options = {
from_address = lib.mkOption { from_address = lib.mkOption {
type = lib.types.str; type = lib.types.str;
@ -95,7 +91,7 @@ in
description = "File containing the password to connect to the SMTP host."; description = "File containing the password to connect to the SMTP host.";
}; };
}; };
}; });
}; };
backupConfig = lib.mkOption { backupConfig = lib.mkOption {
@ -130,7 +126,7 @@ in
ROCKET_LOG = if cfg.debug then "trace" else "info"; ROCKET_LOG = if cfg.debug then "trace" else "info";
ROCKET_ADDRESS = "127.0.0.1"; ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = cfg.port; ROCKET_PORT = cfg.port;
} // lib.optionalAttrs (cfg.smtp != null) {
SMTP_FROM = cfg.smtp.from_address; SMTP_FROM = cfg.smtp.from_address;
SMTP_FROM_NAME = cfg.smtp.from_name; SMTP_FROM_NAME = cfg.smtp.from_name;
SMTP_HOST = cfg.smtp.host; SMTP_HOST = cfg.smtp.host;
@ -152,10 +148,11 @@ in
userConfig = { userConfig = {
DATABASE_URL.source = cfg.databasePasswordFile; DATABASE_URL.source = cfg.databasePasswordFile;
DATABASE_URL.transform = v: "postgresql://vaultwarden:${v}@127.0.0.1:5432/vaultwarden"; DATABASE_URL.transform = v: "postgresql://vaultwarden:${v}@127.0.0.1:5432/vaultwarden";
} // lib.optionalAttrs (cfg.smtp != null) {
SMTP_PASSWORD.source = cfg.smtp.passwordFile; SMTP_PASSWORD.source = cfg.smtp.passwordFile;
}; };
resultPath = "/var/lib/bitwarden_rs/vaultwarden.env"; resultPath = "/var/lib/bitwarden_rs/vaultwarden.env";
generator = name: v: lib.generators.toINIWithGlobalSection {} { globalSection = v; }; generator = name: v: pkgs.writeText "template" (lib.generators.toINIWithGlobalSection {} { globalSection = v; });
}; };
shb.nginx.vhosts = [ shb.nginx.vhosts = [
@ -186,7 +183,7 @@ in
{ {
username = "vaultwarden"; username = "vaultwarden";
database = "vaultwarden"; database = "vaultwarden";
passwordFile = cfg.databasePasswordFile; passwordFile = builtins.toString cfg.databasePasswordFile;
} }
]; ];

207
test/vm/vaultwarden.nix Normal file
View file

@ -0,0 +1,207 @@
{ pkgs, lib, ... }:
let
pkgs' = pkgs;
subdomain = "v";
domain = "example.com";
fqdn = "${subdomain}.${domain}";
# TODO: Test login
commonTestScript = { nodes, ... }:
let
hasSSL = !(isNull nodes.server.shb.vaultwarden.ssl);
proto_fqdn = if hasSSL then "https://${fqdn}" else "http://${fqdn}";
in
''
import json
import os
import pathlib
start_all()
server.wait_for_unit("vaultwarden.service")
server.wait_for_unit("nginx.service")
server.wait_for_open_port(8222)
server.wait_for_open_port(5432)
if ${if hasSSL then "True" else "False"}:
server.copy_from_vm("/etc/ssl/certs/ca-certificates.crt")
client.succeed("rm -r /etc/ssl/certs")
client.copy_from_host(str(pathlib.Path(os.environ.get("out", os.getcwd())) / "ca-certificates.crt"), "/etc/ssl/certs/ca-certificates.crt")
def curl(target, format, endpoint, succeed=True):
return json.loads(target.succeed(
"curl --fail-with-body --silent --show-error --output /dev/null --location"
+ " --connect-to ${fqdn}:443:server:443"
+ " --connect-to ${fqdn}:80:server:80"
+ f" --write-out '{format}'"
+ " " + endpoint
))
with subtest("access"):
response = curl(client, """{"code":%{response_code}}""", "${proto_fqdn}")
if response['code'] != 200:
raise Exception(f"Code is {response['code']}")
'';
base = { config, ... }: {
imports = [
(pkgs'.path + "/nixos/modules/profiles/headless.nix")
(pkgs'.path + "/nixos/modules/profiles/qemu-guest.nix")
{
options = {
shb.backup = lib.mkOption { type = lib.types.anything; };
};
}
../../modules/blocks/nginx.nix
../../modules/blocks/postgresql.nix
../../modules/blocks/ssl.nix
../../modules/services/vaultwarden.nix
];
# Nginx port.
networking.firewall.allowedTCPPorts = [ 80 443 ];
shb.certs = {
cas.selfsigned.myca = {
name = "My CA";
};
certs.selfsigned = {
n = {
ca = config.shb.certs.cas.selfsigned.myca;
domain = "*.${domain}";
group = "nginx";
};
};
};
systemd.services.nginx.after = [ config.shb.certs.certs.selfsigned.n.systemdService ];
systemd.services.nginx.requires = [ config.shb.certs.certs.selfsigned.n.systemdService ];
};
basic = { config, ... }: {
shb.vaultwarden = {
enable = true;
inherit subdomain domain;
ssl = config.shb.certs.certs.selfsigned.n;
port = 8222;
databasePasswordFile = pkgs.writeText "pwfile" "DBPASSWORDFILE";
};
networking.hosts = {
"127.0.0.1" = [ fqdn ];
};
};
ldap = { config, ... }: {
imports = [
../../modules/blocks/ldap.nix
];
shb.ldap = {
enable = true;
inherit domain;
subdomain = "ldap";
ldapPort = 3890;
webUIListenPort = 17170;
dcdomain = "dc=example,dc=com";
ldapUserPasswordFile = pkgs.writeText "ldapUserPassword" "ldapUserPassword";
jwtSecretFile = pkgs.writeText "jwtSecret" "jwtSecret";
};
networking.hosts = {
"127.0.0.1" = [ "${config.shb.ldap.subdomain}.${domain}" ];
};
# Not yet supported
# shb.vaultwarden = {
# ldapEndpoint = "http://127.0.0.1:${builtins.toString config.shb.ldap.webUIListenPort}";
# };
};
sso = { config, ... }: {
imports = [
../../modules/blocks/authelia.nix
];
shb.authelia = {
enable = true;
inherit domain;
subdomain = "auth";
ssl = config.shb.certs.certs.selfsigned.n;
ldapEndpoint = "ldap://127.0.0.1:${builtins.toString config.shb.ldap.ldapPort}";
dcdomain = config.shb.ldap.dcdomain;
secrets = {
jwtSecretFile = pkgs.writeText "jwtSecret" "jwtSecret";
ldapAdminPasswordFile = pkgs.writeText "ldapUserPassword" "ldapUserPassword";
sessionSecretFile = pkgs.writeText "sessionSecret" "sessionSecret";
storageEncryptionKeyFile = pkgs.writeText "storageEncryptionKey" "storageEncryptionKey";
identityProvidersOIDCHMACSecretFile = pkgs.writeText "identityProvidersOIDCHMACSecret" "identityProvidersOIDCHMACSecret";
identityProvidersOIDCIssuerPrivateKeyFile = (pkgs.runCommand "gen-private-key" {} ''
mkdir $out
${pkgs.openssl}/bin/openssl genrsa -out $out/private.pem 4096
'') + "/private.pem";
};
};
networking.hosts = {
"127.0.0.1" = [ "${config.shb.authelia.subdomain}.${domain}" ];
};
shb.vaultwarden = {
authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
};
};
in
{
basic = pkgs.testers.runNixOSTest {
name = "vaultwarden_basic";
nodes.server = lib.mkMerge [
base
basic
{
options = {
shb.authelia = lib.mkOption { type = lib.types.anything; };
};
}
];
nodes.client = {};
testScript = commonTestScript;
};
# Not yet supported
#
# ldap = pkgs.testers.runNixOSTest {
# name = "vaultwarden_ldap";
#
# nodes.server = lib.mkMerge [
# base
# basic
# ldap
# ];
#
# nodes.client = {};
#
# testScript = commonTestScript;
# };
sso = pkgs.testers.runNixOSTest {
name = "vaultwarden_sso";
nodes.server = lib.mkMerge [
base
basic
ldap
sso
];
nodes.client = {};
testScript = commonTestScript;
};
}