add vaultAgent module + test

main
Jörg Thalheim 2 years ago
parent a0199ef2ba
commit fca242ec8d

@ -24,20 +24,18 @@
}: { }: {
packages.default = pkgs.callPackage ./default.nix {}; packages.default = pkgs.callPackage ./default.nix {};
devShells.default = pkgs.callPackage ./shell.nix {}; devShells.default = pkgs.callPackage ./shell.nix {};
checks = { checks = let
treefmt = pkgs.callPackage ./nix/checks/treefmt.nix {}; nixosTests = (pkgs.callPackages ./nix/checks/nixos-test.nix {
inherit
(pkgs.callPackages ./nix/checks/nixos-test.nix {
makeTest = import (pkgs.path + "/nixos/tests/make-test-python.nix"); makeTest = import (pkgs.path + "/nixos/tests/make-test-python.nix");
}) vaultAgentModule = self.nixosModules.vaultAgent;
unittests });
; in {
treefmt = pkgs.callPackage ./nix/checks/treefmt.nix {};
inherit (nixosTests) unittests vault-agent;
}; };
}; };
flake = { flake.nixosModules = {
# The usual flake attributes can be defined here, including system- vaultAgent = ./nix/modules/vault-agent.nix;
# agnostic ones like nixosModule and system-enumerating ones, although
# those are more easily expressed in perSystem.
}; };
}; };
} }

@ -1,6 +1,7 @@
{ {
makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>, makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>,
pkgs ? (import <nixpkgs> {}), pkgs ? (import <nixpkgs> {}),
vaultAgentModule ? ../modules/vault-agent.nix
}: let }: let
makeTest' = args: makeTest' = args:
makeTest args { makeTest args {
@ -8,13 +9,95 @@
inherit (pkgs) system; inherit (pkgs) system;
}; };
in { in {
unittests = makeTest' { vault-agent = makeTest' {
name = "unitests"; name = "vault-agent";
nodes.server = {pkgs, ...}: { nodes.server = {config, pkgs, ...}: {
# Important to get the systemd service running for root imports = [
#environment.variables.XDG_RUNTIME_DIR = "/run/user/0"; vaultAgentModule
];
environment.systemPackages = [ pkgs.vault ];
services.vault = {
enable = true;
dev = true;
devRootTokenID = "phony-secret";
};
systemd.services.setup-vault-agent-approle = {
path = [ pkgs.jq pkgs.vault pkgs.systemd ];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
Environment = [
"VAULT_TOKEN=${config.services.vault.devRootTokenID}"
"VAULT_ADDR=http://127.0.0.1:8200"
];
};
script = ''
set -eux -o pipefail
while ! vault status; do
sleep 1
done
# capabilities of our vault agent
cat > /tmp/policy-file.hcl <<EOF
path "secret/data/my-secret" {
capabilities = ["read"]
}
EOF
vault policy write demo /tmp/policy-file.hcl
vault kv put secret/my-secret foo=bar
# role for our vault agent
vault auth enable approle
vault write auth/approle/role/role1 bind_secret_id=true token_policies=demo
echo -n $(vault read -format json auth/approle/role/role1/role-id | jq -r .data.role_id) > /tmp/roleID
echo -n $(vault write -force -format json auth/approle/role/role1/secret-id | jq -r .data.secret_id) > /tmp/secretID
'';
};
# Make sure our setup service is started before our vault-agent
systemd.services.vault-agent-test = {
wants = [ "setup-vault-agent-approle.service" ];
after = [ "setup-vault-agent-approle.service" ];
};
services.vault.agents.test.settings = {
vault = {
address = "http://localhost:8200";
};
template = {
contents = ''{{ with secret "secret/my-secret" }}{{ .Data.data.foo }}{{ end }}'';
destination = "/run/render.txt";
}; };
auto_auth = {
method = [{
type = "approle";
config = {
role_id_file_path = "/tmp/roleID";
secret_id_file_path = "/tmp/secretID";
};
}];
};
};
};
testScript = ''
start_all()
machine.wait_for_unit("multi-user.target")
machine.wait_for_unit("vault.service")
machine.wait_for_open_port(8200)
machine.wait_for_unit("setup-vault-agent-approle.service")
# It should be able to write our template
out = machine.wait_until_succeeds("cat /run/render.txt")
print(out)
assert out == "bar"
'';
};
unittests = makeTest' {
name = "unittests";
nodes.server = {};
testScript = '' testScript = ''
start_all() start_all()
server.succeed("machinectl shell .host ${pkgs.callPackage ./unittests.nix {}} >&2") server.succeed("machinectl shell .host ${pkgs.callPackage ./unittests.nix {}} >&2")

@ -0,0 +1,83 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.vault;
settingsFormat = pkgs.formats.json {};
autoAuthMethodModule = lib.types.submodule {
freeformType = lib.types.attrsOf lib.types.unspecified;
options = {
type = lib.mkOption {
type = lib.types.str;
};
config = lib.mkOption {
type = lib.types.attrsOf lib.types.unspecified;
};
};
};
autoAuthModule = lib.types.submodule {
freeformType = lib.types.attrsOf lib.types.unspecified;
options = {
method = lib.mkOption {
type = lib.types.listOf autoAuthMethodModule;
default = [ ];
};
};
};
templateConfigModule = lib.types.submodule {
freeformType = lib.types.attrsOf lib.types.unspecified;
options = {
exit_on_retry_failure = lib.mkOption {
type = lib.types.bool;
default = true;
};
};
};
agentConfigType = lib.types.submodule {
freeformType = lib.types.attrsOf lib.types.unspecified;
options = {
auto_auth = lib.mkOption {
type = autoAuthModule;
default = { };
};
template_config = lib.mkOption {
type = templateConfigModule;
default = { };
};
};
};
in
{
options.services.vault.agents = lib.mkOption {
default = {};
description = "Instances of vault agent";
type = lib.types.attrsOf (lib.types.submodule {
options = {
settings = lib.mkOption {
description = "agent configuration";
type = agentConfigType;
};
};
});
};
config = {
systemd.services = lib.mapAttrs' (name: instanceCfg: lib.nameValuePair "vault-agent-${name}" ({
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
# Needs getent in PATH
path = [ pkgs.glibc ];
serviceConfig = {
Restart = "on-failure";
ExecStart = "${pkgs.vault}/bin/vault agent -config=${settingsFormat.generate "agent.json" instanceCfg.settings}";
};
})) cfg.agents;
};
}
Loading…
Cancel
Save