nixos/vaultwarden: add test for backup script, fix flaky sqlite test

This commit is contained in:
h7x4 2023-07-27 21:13:55 +02:00 committed by Sandro Jäckel
parent ba2ec015bd
commit d952db86c9
No known key found for this signature in database
GPG Key ID: 3AF5A43A3EECC2E5
2 changed files with 134 additions and 123 deletions

View File

@ -1013,7 +1013,7 @@ in {
vault-agent = handleTest ./vault-agent.nix {};
vault-dev = handleTest ./vault-dev.nix {};
vault-postgresql = handleTest ./vault-postgresql.nix {};
vaultwarden = handleTest ./vaultwarden.nix {};
vaultwarden = discoverTests (import ./vaultwarden.nix);
vector = handleTest ./vector {};
vengi-tools = handleTest ./vengi-tools.nix {};
victoriametrics = handleTest ./victoriametrics.nix {};

View File

@ -1,94 +1,26 @@
{ system ? builtins.currentSystem
, config ? { }
, pkgs ? import ../.. { inherit system config; }
}:
# These tests will:
# * Set up a vaultwarden server
# * Have Firefox use the web vault to create an account, log in, and save a password to the valut
# * Have Firefox use the web vault to create an account, log in, and save a password to the vault
# * Have the bw cli log in and read that password from the vault
#
# Note that Firefox must be on the same machine as the server for WebCrypto APIs to be available (or HTTPS must be configured)
#
# The same tests should work without modification on the official bitwarden server, if we ever package that.
with import ../lib/testing-python.nix { inherit system pkgs; };
with pkgs.lib;
let
backends = [ "sqlite" "mysql" "postgresql" ];
makeVaultwardenTest = name: {
backend ? name,
withClient ? true,
testScript ? null,
}: import ./make-test-python.nix ({ lib, pkgs, ...}: let
dbPassword = "please_dont_hack";
userEmail = "meow@example.com";
userPassword = "also_super_secret_ZJWpBKZi668QGt"; # Must be complex to avoid interstitial warning on the signup page
storedPassword = "seeeecret";
makeVaultwardenTest = backend: makeTest {
name = "vaultwarden-${backend}";
meta = {
maintainers = with pkgs.lib.maintainers; [ jjjollyjim ];
};
nodes = {
server = { pkgs, ... }:
let backendConfig = {
mysql = {
services.mysql = {
enable = true;
initialScript = pkgs.writeText "mysql-init.sql" ''
CREATE DATABASE bitwarden;
CREATE USER 'bitwardenuser'@'localhost' IDENTIFIED BY '${dbPassword}';
GRANT ALL ON `bitwarden`.* TO 'bitwardenuser'@'localhost';
FLUSH PRIVILEGES;
'';
package = pkgs.mariadb;
};
services.vaultwarden.config.databaseUrl = "mysql://bitwardenuser:${dbPassword}@localhost/bitwarden";
systemd.services.vaultwarden.after = [ "mysql.service" ];
};
postgresql = {
services.postgresql = {
enable = true;
initialScript = pkgs.writeText "postgresql-init.sql" ''
CREATE USER bitwardenuser WITH PASSWORD '${dbPassword}';
CREATE DATABASE bitwarden WITH OWNER bitwardenuser;
'';
};
services.vaultwarden.config.databaseUrl = "postgresql://bitwardenuser:${dbPassword}@localhost/bitwarden";
systemd.services.vaultwarden.after = [ "postgresql.service" ];
};
sqlite = { };
};
in
mkMerge [
backendConfig.${backend}
{
services.vaultwarden = {
enable = true;
dbBackend = backend;
config = {
rocketAddress = "0.0.0.0";
rocketPort = 80;
};
};
networking.firewall.allowedTCPPorts = [ 80 ];
environment.systemPackages =
let
testRunner = pkgs.writers.writePython3Bin "test-runner"
{
testRunner = pkgs.writers.writePython3Bin "test-runner" {
libraries = [ pkgs.python3Packages.selenium ];
flakeIgnore = [
"E501"
];
flakeIgnore = [ "E501" ];
} ''
from selenium.webdriver.common.by import By
@ -147,19 +79,77 @@ let
driver.find_element(By.XPATH, "//button[contains(., 'Save')]").click()
'';
in
[ pkgs.firefox-unwrapped pkgs.geckodriver testRunner ];
in {
inherit name;
meta = {
maintainers = with pkgs.lib.maintainers; [ dotlambda SuperSandro2000 ];
};
nodes = {
server = { pkgs, ... }: lib.mkMerge [
{
mysql = {
services.mysql = {
enable = true;
initialScript = pkgs.writeText "mysql-init.sql" ''
CREATE DATABASE bitwarden;
CREATE USER 'bitwardenuser'@'localhost' IDENTIFIED BY '${dbPassword}';
GRANT ALL ON `bitwarden`.* TO 'bitwardenuser'@'localhost';
FLUSH PRIVILEGES;
'';
package = pkgs.mariadb;
};
services.vaultwarden.config.databaseUrl = "mysql://bitwardenuser:${dbPassword}@localhost/bitwarden";
systemd.services.vaultwarden.after = [ "mysql.service" ];
};
postgresql = {
services.postgresql = {
enable = true;
ensureDatabases = [ "vaultwarden" ];
ensureUsers = [{
name = "vaultwarden";
ensureDBOwnership = true;
}];
};
services.vaultwarden.config.databaseUrl = "postgresql:///vaultwarden?host=/run/postgresql";
systemd.services.vaultwarden.after = [ "postgresql.service" ];
};
sqlite = {
services.vaultwarden.backupDir = "/var/lib/vaultwarden/backups";
environment.systemPackages = [ pkgs.sqlite ];
};
}.${backend}
{
services.vaultwarden = {
enable = true;
dbBackend = backend;
config = {
rocketAddress = "0.0.0.0";
rocketPort = 80;
};
};
networking.firewall.allowedTCPPorts = [ 80 ];
environment.systemPackages = [ pkgs.firefox-unwrapped pkgs.geckodriver testRunner ];
}
];
client = { pkgs, ... }:
{
} // lib.optionalAttrs withClient {
client = { pkgs, ... }: {
environment.systemPackages = [ pkgs.bitwarden-cli ];
};
};
testScript = ''
testScript = if testScript != null then testScript else ''
start_all()
server.wait_for_unit("vaultwarden.service")
server.wait_for_open_port(80)
@ -184,15 +174,36 @@ let
client.succeed(f"bw --nointeraction --raw --session {key} sync -f")
with subtest("get the password with the cli"):
password = client.succeed(
f"bw --nointeraction --raw --session {key} list items | ${pkgs.jq}/bin/jq -r .[].login.password"
password = client.wait_until_succeeds(
f"bw --nointeraction --raw --session {key} list items | ${pkgs.jq}/bin/jq -r .[].login.password",
timeout=60
)
assert password.strip() == "${storedPassword}"
'';
};
});
in
builtins.listToAttrs (
map
(backend: { name = backend; value = makeVaultwardenTest backend; })
backends
)
builtins.mapAttrs (k: v: makeVaultwardenTest k v) {
mysql = {};
postgresql = {};
sqlite = {};
sqlite-backup = {
backend = "sqlite";
withClient = false;
testScript = ''
start_all()
server.wait_for_unit("vaultwarden.service")
server.wait_for_open_port(80)
with subtest("Set up vaultwarden"):
server.succeed("PYTHONUNBUFFERED=1 test-runner | systemd-cat -t test-runner")
with subtest("Run the backup script"):
server.start_job("backup-vaultwarden.service")
with subtest("Check that backup exists"):
server.succeed('[ -d "/var/lib/vaultwarden/backups" ]')
server.succeed('[ -f "/var/lib/vaultwarden/backups/db.sqlite3" ]')
'';
};
}