ops/nixos: add some vault-agent setup

This commit is contained in:
Luke Granger-Brown 2022-01-23 23:38:40 +00:00
parent 3ad4c2399a
commit 7c418666fe
4 changed files with 141 additions and 4 deletions

View file

@ -15,7 +15,10 @@ let
mkDefault = lib.mkOverride 900; mkDefault = lib.mkOverride 900;
in in
{ {
imports = [ ../../../third_party/home-manager/nixos ]; imports = [
../../../third_party/home-manager/nixos
./vault-agent.nix
];
options.my.specialisationName = lib.mkOption { options.my.specialisationName = lib.mkOption {
type = lib.types.nullOr lib.types.str; type = lib.types.nullOr lib.types.str;

View file

@ -0,0 +1,88 @@
# SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
#
# SPDX-License-Identifier: Apache-2.0
{ pkgs, config, depot, lib, ... }:
let
inherit (lib) mkEnableOption mkOption types;
mkDefault = lib.mkOverride 900;
format = pkgs.formats.json {};
in
{
options.my.vault = {
enable = mkEnableOption "vault agent";
roleID = mkOption {
type = types.str;
default = config.networking.hostName;
};
secretIDPath = mkOption {
type = types.str;
default = "/var/lib/vault-agent/secret-id";
};
settings = mkOption {
type = format.type;
default = {};
};
bindMountStateTo = mkOption {
type = types.nullOr types.str;
default = null;
};
};
config = {
my.vault.enable = mkDefault true;
my.vault.settings = mkDefault {
pid_file = "/run/vault-agent/pid";
vault.address = "https://vault.int.lukegb.com";
auto_auth.method = [{
type = "approle";
config = {
role_id_file_path = pkgs.writeText "${config.my.vault.roleID}-role-id" config.my.vault.roleID;
secret_id_file_path = config.my.vault.secretIDPath;
remove_secret_id_file_after_reading = false;
};
}];
cache.use_auto_auth_token = true;
listener.tcp = {
address = "127.0.0.1:8200";
tls_disable = true;
};
};
systemd = lib.optionalAttrs config.my.vault.enable {
services.vault-agent = {
description = "Hashicorp Vault Agent";
wants = [ "network.target" ];
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ glibc.bin ];
serviceConfig = {
RuntimeDirectory = "vault-agent";
RuntimeDirectoryMode = "0700";
StateDirectory = "vault-agent";
StateDirectoryMode = "0700";
DynamicUser = true;
User = "vault-agent";
ProtectSystem = "strict";
ProtectHome = "yes";
ExecStart = "${pkgs.vault}/bin/vault agent -config=${format.generate "vault-agent.json" config.my.vault.settings}";
};
};
mounts = lib.optional (config.my.vault.bindMountStateTo != null) {
unitConfig.RequiresMountsFor = "${config.my.vault.bindMountStateTo} /var/lib/private/vault-agent";
options = "bind";
what = config.my.vault.bindMountStateTo;
where = "/var/lib/private/vault-agent";
requiredBy = [ "vault-agent.service" ];
before = [ "vault-agent.service" ];
wantedBy = [ "vault-agent.service" ];
};
};
};
}

View file

@ -4,7 +4,7 @@
{ lib, config, ... }: { lib, config, ... }:
let let
inherit (lib) mkOption types mkAfter mkIf; inherit (lib) mkOption types mkAfter mkIf mkDefault;
robCfg = config.services.zfs.rollbackOnBoot; robCfg = config.services.zfs.rollbackOnBoot;
in in
{ {
@ -31,11 +31,13 @@ in
enable = true; enable = true;
monthly = 1; monthly = 1;
}; };
systemd.tmpfiles.rules = lib.mkAfter (builtins.map (x: "L ${x} - - - - /persist{x}") robCfg.keepPaths); systemd.tmpfiles.rules = mkAfter (builtins.map (x: "L ${x} - - - - /persist{x}") robCfg.keepPaths);
boot.initrd.postDeviceCommands = mkIf robCfg.enable boot.initrd.postDeviceCommands = mkIf robCfg.enable
(mkAfter '' (mkAfter ''
zfs rollback -r ${robCfg.snapshot} zfs rollback -r ${robCfg.snapshot}
''); '');
my.vault.bindMountStateTo = mkIf robCfg.enable (mkDefault "/persist/var/lib/vault-agent");
}; };
} }

44
ops/vault/create-server.sh Executable file
View file

@ -0,0 +1,44 @@
#!/usr/bin/env nix-shell
#!nix-shell -p vault -p jq -i bash
set -euo pipefail
readonly server_name=${1}
export VAULT_ADDR=https://vault.int.lukegb.com/
echo Checking login credentials...
vault token lookup >/dev/null || vault login -method=oidc role=admin
echo Grabbing approle accessor...
APPROLE_ACCESSOR="$(vault auth list -format=json | jq -r '.["approle/"].accessor')"
echo -ne "\t${APPROLE_ACCESSOR}\n"
echo Creating new approle...
vault write auth/approle/role/${server_name} \
secret_id_num_uses=0 \
secret_id_ttl="" \
token_ttl=20m \
token_max_ttl=30m \
token_policies="default,server" \
token_max_uses=0
echo Setting role-id...
vault write auth/approle/role/${server_name}/role-id role_id=${server_name}
echo Creating new secret...
SECRET_ID="$(vault write -f -format=json auth/approle/role/${server_name}/secret-id | jq -r '.data.secret_id')"
echo -ne "\t$SECRET_ID\n"
echo Creating entity...
ENTITY_ID="$(vault write -format=json identity/entity \
name="${server_name}" \
policies="server" \
metadata="server=${server_name}" | jq -r '.data.id')"
echo -ne "\t$ENTITY_ID\n"
echo Creating entity alias...
vault write identity/entity-alias \
name="${server_name}" \
canonical_id="${ENTITY_ID}" \
mount_accessor="${APPROLE_ACCESSOR}"