change secrets management to its own module and update hetzner-vm with it
This commit is contained in:
parent
c81a933217
commit
0a2aae3a43
|
@ -1,68 +0,0 @@
|
|||
{ }: {
|
||||
mpd_control_password = {
|
||||
user = "mpd";
|
||||
group = "mpd";
|
||||
permissions = "660";
|
||||
path = "/secrets/mpd_control_password";
|
||||
};
|
||||
music_stream_passwd = {
|
||||
user = "nginx";
|
||||
group = "nginx";
|
||||
permissions = "660";
|
||||
path = "/secrets/music_stream_passwd";
|
||||
};
|
||||
chaos_mail_passwd = {
|
||||
user = "dovecot2";
|
||||
group = "dovecot2";
|
||||
permissions = "660";
|
||||
path = "/secrets/chaos_mail_passwd";
|
||||
};
|
||||
gitlab_env = {
|
||||
user = "gitlab_artifacts_sync";
|
||||
group = "gitlab_artifacts_sync";
|
||||
permissions = "660";
|
||||
path = "/secrets/gitlab_env";
|
||||
};
|
||||
restic_password = {
|
||||
user = "root";
|
||||
group = "root";
|
||||
permissions = "660";
|
||||
path = "/secrets/restic_password";
|
||||
};
|
||||
restic_env = {
|
||||
user = "root";
|
||||
group = "root";
|
||||
permissions = "660";
|
||||
path = "/secrets/restic_env";
|
||||
};
|
||||
wg_privkey = {
|
||||
user = "root";
|
||||
group = "root";
|
||||
permissions = "660";
|
||||
path = "/secrets/wg_privkey";
|
||||
};
|
||||
wg_preshared_tablet = {
|
||||
user = "root";
|
||||
group = "root";
|
||||
permissions = "660";
|
||||
path = "/secrets/wg_preshared_tablet";
|
||||
};
|
||||
wg_preshared_vault = {
|
||||
user = "root";
|
||||
group = "root";
|
||||
permissions = "660";
|
||||
path = "/secrets/wg_preshared_vault";
|
||||
};
|
||||
wg_preshared_storage = {
|
||||
user = "root";
|
||||
group = "root";
|
||||
permissions = "660";
|
||||
path = "/secrets/wg_preshared_storage";
|
||||
};
|
||||
wg_preshared_iphone8 = {
|
||||
user = "root";
|
||||
group = "root";
|
||||
permissions = "660";
|
||||
path = "/secrets/wg_preshared_iphone8";
|
||||
};
|
||||
}
|
|
@ -1,97 +1,87 @@
|
|||
{ pkgs, ... }:
|
||||
let secrets-db = (import ./secrets-db.nix { });
|
||||
in {
|
||||
systemd.tmpfiles.rules = [ "d /secrets - root root" ];
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellScriptBin "init-secrets" ''
|
||||
set -e -o pipefail
|
||||
{ pkgs, ... }: {
|
||||
services.secrets = {
|
||||
enable = true;
|
||||
|
||||
VAULT_ADDR_DEFAULT="https://vault.owo.monster"
|
||||
[ -n "$VAULT_ADDR" ] && export VAULT_ADDR="$VAULT_ADDR_DEFAULT"
|
||||
extraPackages = with pkgs;
|
||||
[
|
||||
# for music & mail passwd files
|
||||
apacheHttpd
|
||||
];
|
||||
|
||||
export PATH=$PATH:${pkgs.vault}/bin
|
||||
export PATH=$PATH:${pkgs.jq}/bin
|
||||
export PATH=$PATH:${pkgs.apacheHttpd}/bin
|
||||
|
||||
kv_get() {
|
||||
vault kv get -format json $1
|
||||
}
|
||||
|
||||
simple_get() {
|
||||
kv_get $1 | jq .data.data$2 -r
|
||||
}
|
||||
|
||||
file=${secrets-db.mpd_control_password.path}
|
||||
echo $file
|
||||
simple_get "/api-keys/mpd" .password > $file
|
||||
chown ${secrets-db.mpd_control_password.user}:${secrets-db.mpd_control_password.group} $file
|
||||
chmod ${secrets-db.mpd_control_password.permissions} $file
|
||||
|
||||
file=${secrets-db.music_stream_passwd.path}
|
||||
echo $file
|
||||
secrets = {
|
||||
mpd_control_password = {
|
||||
user = "mpd";
|
||||
group = "mpd";
|
||||
fetchScript = ''
|
||||
simple_get "/api-keys/mpd" .password > $secretFile
|
||||
'';
|
||||
};
|
||||
music_stream_passwd = {
|
||||
user = "nginx";
|
||||
group = "nginx";
|
||||
fetchScript = ''
|
||||
username=$(simple_get "/api-keys/music-stream" .username)
|
||||
password=$(simple_get "/api-keys/music-stream" .password)
|
||||
htpasswd -bc $file "$username" "$password"
|
||||
chown ${secrets-db.music_stream_passwd.user}:${secrets-db.music_stream_passwd.group} $file
|
||||
chmod ${secrets-db.music_stream_passwd.permissions} $file
|
||||
|
||||
file=${secrets-db.chaos_mail_passwd.path}
|
||||
echo $file
|
||||
htpasswd -bc $secretFile "$username" "$password" 2>/dev/null
|
||||
'';
|
||||
};
|
||||
chaos_mail_passwd = {
|
||||
user = "dovecot2";
|
||||
group = "dovecot2";
|
||||
fetchScript = ''
|
||||
password=$(simple_get "/passwords/mail" .password)
|
||||
htpasswd -nbB "" "$password" | cut -d: -f2 > $file
|
||||
chown ${secrets-db.chaos_mail_passwd.user}:${secrets-db.chaos_mail_passwd.group} $file
|
||||
chmod ${secrets-db.chaos_mail_passwd.permissions} $file
|
||||
|
||||
file=${secrets-db.gitlab_env.path}
|
||||
echo $file
|
||||
htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > $secretFile
|
||||
'';
|
||||
};
|
||||
gitlab_env = {
|
||||
user = "gitlab_artifacts_sync";
|
||||
group = "gitlab_artifacts_sync";
|
||||
fetchScript = ''
|
||||
token=$(simple_get "/api-keys/gitlab/gitlab_pages_serve" .token)
|
||||
echo "GITLAB_TOKEN=$token" > $file
|
||||
chown ${secrets-db.gitlab_env.user}:${secrets-db.gitlab_env.group} $file
|
||||
chmod ${secrets-db.gitlab_env.permissions} $file
|
||||
|
||||
file=${secrets-db.restic_password.path}
|
||||
echo $file
|
||||
simple_get "/private-public-keys/restic/HetznerVM" .password > $file
|
||||
chown ${secrets-db.restic_password.user}:${secrets-db.restic_password.group} $file
|
||||
chmod ${secrets-db.restic_password.permissions} $file
|
||||
|
||||
file=${secrets-db.restic_env.path}
|
||||
echo $file
|
||||
echo "GITLAB_TOKEN=$token" > $secretFile
|
||||
'';
|
||||
};
|
||||
restic_password = {
|
||||
fetchScript = ''
|
||||
simple_get "/private-public-keys/restic/HetznerVM" .password > $secretFile
|
||||
'';
|
||||
};
|
||||
restic_env = {
|
||||
fetchScript = ''
|
||||
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/HetznerVM" .username)
|
||||
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/HetznerVM" .password)
|
||||
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/HetznerVM" > $file
|
||||
chown ${secrets-db.restic_env.user}:${secrets-db.restic_env.group} $file
|
||||
chmod ${secrets-db.restic_env.permissions} $file
|
||||
|
||||
file=${secrets-db.wg_privkey.path}
|
||||
echo $file
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .private > $file
|
||||
chown ${secrets-db.wg_privkey.user}:${secrets-db.wg_privkey.group} $file
|
||||
chmod ${secrets-db.wg_privkey.permissions} $file
|
||||
|
||||
file=${secrets-db.wg_preshared_tablet.path}
|
||||
echo $file
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.tablet > $file
|
||||
chown ${secrets-db.wg_preshared_tablet.user}:${secrets-db.wg_preshared_tablet.group} $file
|
||||
chmod ${secrets-db.wg_preshared_tablet.permissions} $file
|
||||
|
||||
file=${secrets-db.wg_preshared_vault.path}
|
||||
echo $file
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.vault > $file
|
||||
chown ${secrets-db.wg_preshared_vault.user}:${secrets-db.wg_preshared_vault.group} $file
|
||||
chmod ${secrets-db.wg_preshared_vault.permissions} $file
|
||||
|
||||
file=${secrets-db.wg_preshared_storage.path}
|
||||
echo $file
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.storage > $file
|
||||
chown ${secrets-db.wg_preshared_storage.user}:${secrets-db.wg_preshared_storage.group} $file
|
||||
chmod ${secrets-db.wg_preshared_storage.permissions} $file
|
||||
|
||||
file=${secrets-db.wg_preshared_iphone8.path}
|
||||
echo $file
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.iphone8 > $file
|
||||
chown ${secrets-db.wg_preshared_iphone8.user}:${secrets-db.wg_preshared_iphone8.group} $file
|
||||
chmod ${secrets-db.wg_preshared_iphone8.permissions} $file
|
||||
'')
|
||||
];
|
||||
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/HetznerVM" > $secretFile
|
||||
'';
|
||||
};
|
||||
wg_privkey = {
|
||||
fetchScript = ''
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .private > $secretFile
|
||||
'';
|
||||
};
|
||||
wg_preshared_tablet = {
|
||||
path = "/secrets/wg_preshared_tablet";
|
||||
fetchScript = ''
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.tablet > $secretFile
|
||||
'';
|
||||
};
|
||||
wg_preshared_vault = {
|
||||
path = "/secrets/wg_preshared_vault";
|
||||
fetchScript = ''
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.vault > $secretFile
|
||||
'';
|
||||
};
|
||||
wg_preshared_storage = {
|
||||
path = "/secrets/wg_preshared_storage";
|
||||
fetchScript = ''
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.storage > $secretFile
|
||||
'';
|
||||
};
|
||||
wg_preshared_iphone8 = {
|
||||
path = "/secrets/wg_preshared_iphone8";
|
||||
fetchScript = ''
|
||||
simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.iphone8 > $secretFile
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{ ... }:
|
||||
let secrets-db = (import ../secrets-db.nix { });
|
||||
{ config, ... }:
|
||||
let secrets = config.services.secrets.secrets;
|
||||
in {
|
||||
services.gitlab_artifacts_sync = {
|
||||
enable = true;
|
||||
credentialsEnvironmentFile = "${secrets-db.gitlab_env.path}";
|
||||
credentialsEnvironmentFile = "${secrets.gitlab_env.path}";
|
||||
repos = [
|
||||
{
|
||||
repoName = "ChaotiCryptidz/VaultUI";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{ }:
|
||||
let secrets-db = (import ../../secrets-db.nix { });
|
||||
{ config }:
|
||||
let secrets = config.services.secrets.secrets;
|
||||
in rec {
|
||||
fqdn = "mail.owo.monster";
|
||||
domains = [
|
||||
|
@ -21,7 +21,7 @@ in rec {
|
|||
accounts = {
|
||||
"chaoticryptidz@owo.monster" = {
|
||||
name = "chaoticryptidz@owo.monster";
|
||||
passwordFile = "${secrets-db.chaos_mail_passwd.path}";
|
||||
passwordFile = "${secrets.chaos_mail_passwd.path}";
|
||||
aliases = [
|
||||
"all@owo.monster"
|
||||
# for sending from
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
mail_config = (import ./config.nix { });
|
||||
|
||||
mail_config = (import ./config.nix { config = config; });
|
||||
passwdDir = "/run/dovecot2";
|
||||
passwdFile = "${passwdDir}/passwd";
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
mail_config = (import ./config.nix { });
|
||||
|
||||
mail_config = (import ./config.nix { config = config; });
|
||||
dkimUser = config.services.opendkim.user;
|
||||
dkimGroup = config.services.opendkim.group;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
mail_config = (import ./config.nix { });
|
||||
mail_config = (import ./config.nix { config = config; });
|
||||
submissionHeaderCleanupRules =
|
||||
pkgs.writeText "submission_header_cleanup_rules" (''
|
||||
/^Received:/ IGNORE
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
mail_config = (import ./config.nix { });
|
||||
mail_config = (import ./config.nix { config = config; });
|
||||
|
||||
ports = (import ../../ports.nix { });
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ pkgs, ... }:
|
||||
{ config, pkgs, ... }:
|
||||
let
|
||||
mail_config = (import ./config.nix { });
|
||||
mail_config = (import ./config.nix { config = config; });
|
||||
acmeRoot = "/var/lib/acme/acme-challenge";
|
||||
|
||||
in {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
mail_config = (import ./config.nix { });
|
||||
mail_config = (import ./config.nix { config = config; });
|
||||
|
||||
v = mail_config.vmail_config;
|
||||
sieve_directory = mail_config.sieve_directory;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{ ... }:
|
||||
let mail_config = (import ./config.nix { });
|
||||
{ config, ... }:
|
||||
let mail_config = (import ./config.nix { config = config; });
|
||||
in {
|
||||
services.roundcube = {
|
||||
enable = true;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ pkgs, lib, tree, ... }:
|
||||
{ config, pkgs, lib, tree, ... }:
|
||||
let
|
||||
ports = (import ../ports.nix { });
|
||||
secrets-db = (import ../secrets-db.nix { });
|
||||
secrets = config.services.secrets.secrets;
|
||||
in {
|
||||
environment.systemPackages = with pkgs; [ mpc_cli ];
|
||||
|
||||
|
@ -10,7 +10,7 @@ in {
|
|||
network.listenAddress = "0.0.0.0";
|
||||
musicDirectory = "https://storage-webdav.owo.monster/music_ro/";
|
||||
credentials = [{
|
||||
passwordFile = "${secrets-db.mpd_control_password.path}";
|
||||
passwordFile = "${secrets.mpd_control_password.path}";
|
||||
permissions = [ "read" "add" "control" "admin" ];
|
||||
}];
|
||||
extraConfig = ''
|
||||
|
@ -53,14 +53,14 @@ in {
|
|||
proxyPass = "http://127.0.0.1:${toString ports.mpd-opus}";
|
||||
extraConfig = ''
|
||||
auth_basic "Music Password";
|
||||
auth_basic_user_file ${secrets-db.music_stream_passwd.path};
|
||||
auth_basic_user_file ${secrets.music_stream_passwd.path};
|
||||
'';
|
||||
};
|
||||
"/flac" = {
|
||||
proxyPass = "http://127.0.0.1:${toString ports.mpd-flac}";
|
||||
extraConfig = ''
|
||||
auth_basic "Music Password";
|
||||
auth_basic_user_file ${secrets-db.music_stream_passwd.path};
|
||||
auth_basic_user_file ${secrets.music_stream_passwd.path};
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
let
|
||||
secrets-db = (import ../secrets-db.nix { });
|
||||
mail_config = (import ./mailserver/config.nix { });
|
||||
secrets = config.services.secrets.secrets;
|
||||
mail_config = (import ./mailserver/config.nix { config = config; });
|
||||
|
||||
backupPrepareCommand = "${
|
||||
(pkgs.writeShellScriptBin "backupPrepareCommand" ''
|
||||
|
@ -12,8 +12,8 @@ in {
|
|||
environment.systemPackages = [
|
||||
(pkgs.writeShellScriptBin "restic-hetzner-vm" ''
|
||||
env \
|
||||
RESTIC_PASSWORD_FILE=${secrets-db.restic_password.path} \
|
||||
$(cat ${secrets-db.restic_env.path}) \
|
||||
RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \
|
||||
$(cat ${secrets.restic_env.path}) \
|
||||
${pkgs.restic}/bin/restic $@
|
||||
'')
|
||||
];
|
||||
|
@ -40,8 +40,8 @@ in {
|
|||
# repository is overrided in environmentFile to contain auth
|
||||
# make sure to keep up to date when changing repository
|
||||
repository = "rest:https://storage-restic.owo.monster/HetznerVM";
|
||||
passwordFile = "${secrets-db.restic_password.path}";
|
||||
environmentFile = "${secrets-db.restic_env.path}";
|
||||
passwordFile = "${secrets.restic_password.path}";
|
||||
environmentFile = "${secrets.restic_env.path}";
|
||||
|
||||
timerConfig = {
|
||||
OnBootSec = "1m";
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
{ ... }:
|
||||
let secrets-db = (import ../secrets-db.nix { });
|
||||
{ config, ... }:
|
||||
let secrets = config.services.secrets.secrets;
|
||||
in {
|
||||
networking.wg-quick.interfaces = {
|
||||
wg0 = {
|
||||
address = [ "10.69.42.1/32" ];
|
||||
listenPort = 51820;
|
||||
privateKeyFile = "${secrets-db.wg_privkey.path}";
|
||||
privateKeyFile = "${secrets.wg_privkey.path}";
|
||||
peers = [
|
||||
# tablet
|
||||
{
|
||||
publicKey = "jXA0DeprEaL/ARQ3K81l8xWuUI5C/90DcY3bIfcIjz8=";
|
||||
presharedKeyFile = "${secrets-db.wg_preshared_tablet.path}";
|
||||
presharedKeyFile = "${secrets.wg_preshared_tablet.path}";
|
||||
allowedIPs = [ "10.69.42.2/32" ];
|
||||
}
|
||||
# vault
|
||||
{
|
||||
publicKey = "IGq+WanFM/bKNUkwjO/0AAtDhJLvtvU+mVxH27QyHTc=";
|
||||
presharedKeyFile = "${secrets-db.wg_preshared_vault.path}";
|
||||
presharedKeyFile = "${secrets.wg_preshared_vault.path}";
|
||||
endpoint = "vault.servers.genderfucked.monster:51820";
|
||||
allowedIPs = [ "10.69.42.3/32" ];
|
||||
}
|
||||
# storage
|
||||
{
|
||||
publicKey = "biNNeCkjAWi2jUVoL5+1pBtXGa3OFZi4DltB2dqGjGg=";
|
||||
presharedKeyFile = "${secrets-db.wg_preshared_storage.path}";
|
||||
presharedKeyFile = "${secrets.wg_preshared_storage.path}";
|
||||
allowedIPs = [ "10.69.42.4/32" ];
|
||||
}
|
||||
# iphone8
|
||||
{
|
||||
publicKey = "2BgT08bDKh8WlFFSeRArI9a1GpFgUyqEApvJy4KgAmw=";
|
||||
presharedKeyFile = "${secrets-db.wg_preshared_iphone8.path}";
|
||||
presharedKeyFile = "${secrets.wg_preshared_iphone8.path}";
|
||||
allowedIPs = [ "10.69.42.5/32" ];
|
||||
}
|
||||
];
|
||||
|
|
|
@ -21,6 +21,7 @@ let
|
|||
|
||||
tree.impure.modules.nixos.rclone-serve
|
||||
tree.impure.modules.nixos.rclone-sync
|
||||
tree.impure.modules.nixos.secrets
|
||||
];
|
||||
|
||||
nixosUnstableSystem = nixpkgs-unstable.lib.nixosSystem;
|
||||
|
|
251
modules/nixos/secrets.nix
Normal file
251
modules/nixos/secrets.nix
Normal file
|
@ -0,0 +1,251 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.secrets;
|
||||
defaultPackages = with pkgs; [ pkgs.vault pkgs.jq ];
|
||||
|
||||
in {
|
||||
options = {
|
||||
services.secrets = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
debug = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
createSecretsDir = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
secretsDirUser = mkOption {
|
||||
type = types.str;
|
||||
default = "root";
|
||||
};
|
||||
|
||||
secretsDirGroup = mkOption {
|
||||
type = types.str;
|
||||
default = "root";
|
||||
};
|
||||
|
||||
secretsDir = mkOption {
|
||||
type = types.str;
|
||||
default = "/secrets";
|
||||
};
|
||||
|
||||
vaultURL = mkOption {
|
||||
type = types.str;
|
||||
default = "https://vault.owo.monster";
|
||||
description = "default Vault URL, can be overrided with env variables";
|
||||
};
|
||||
|
||||
extraFunctions = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = "extra bash functions to add to top of script";
|
||||
};
|
||||
|
||||
extraPackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [ ];
|
||||
description = "extra packages for script";
|
||||
};
|
||||
|
||||
secrets = mkOption {
|
||||
type = types.attrsOf (types.submodule ({ config, name, ... }: {
|
||||
options = {
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "root";
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "root";
|
||||
};
|
||||
permissions = mkOption {
|
||||
type = types.str;
|
||||
default = "660";
|
||||
};
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
default = "${cfg.secretsDir}/${name}";
|
||||
};
|
||||
|
||||
fetchScript = mkOption {
|
||||
type = types.lines;
|
||||
description = ''
|
||||
script used to fetch secrets, $file is secret.path
|
||||
'';
|
||||
};
|
||||
|
||||
checkScript = mkOption {
|
||||
type = types.nullOr types.lines;
|
||||
default = null;
|
||||
description = ''
|
||||
script used to check contents of secret file, set LOCAL_FAIL to true on failure
|
||||
'';
|
||||
};
|
||||
|
||||
manual = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "should the secret be manually deployed";
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf (cfg.enable) (let
|
||||
scriptBase = ''
|
||||
set -e -o pipefail
|
||||
${if cfg.debug then "set -x" else ""}
|
||||
'';
|
||||
|
||||
manualSecrets = filterAttrs (name: secret: secret.manual) cfg.secrets;
|
||||
nonManualSecrets = filterAttrs (name: secret: !secret.manual) cfg.secrets;
|
||||
|
||||
initScript = ''
|
||||
${scriptBase}
|
||||
|
||||
VAULT_ADDR_DEFAULT="${cfg.vaultURL}"
|
||||
[ -n "$VAULT_ADDR" ] && export VAULT_ADDR="$VAULT_ADDR_DEFAULT"
|
||||
|
||||
kv_get() {
|
||||
vault kv get -format json "$1"
|
||||
}
|
||||
|
||||
simple_get() {
|
||||
kv_get "$1" | jq ".data.data$2" -r
|
||||
}
|
||||
|
||||
${cfg.extraFunctions}
|
||||
'' + (lib.concatStringsSep "\n" (lib.mapAttrsToList (name: secret: ''
|
||||
if [[ ! -f "${secret.path}" ]]; then
|
||||
echo "Initializing Secret ${secret.path}"
|
||||
else
|
||||
echo "Updating Secret ${secret.path}"
|
||||
fi
|
||||
|
||||
secretFile="${secret.path}"
|
||||
${secret.fetchScript}
|
||||
|
||||
chown ${secret.user}:${secret.group} "${secret.path}"
|
||||
chmod ${secret.permissions} "${secret.path}"
|
||||
'') nonManualSecrets)) + (lib.concatStringsSep "\n" (lib.mapAttrsToList
|
||||
(name: secret: ''
|
||||
if [[ ! -f "${secret.path}" ]]; then
|
||||
echo "Manual Secret ${secret.path} Doesn't Exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating Permissions on Manual Secret ${secret.path}"
|
||||
|
||||
chown ${secret.user}:${secret.group} "${secret.path}"
|
||||
chmod ${secret.permissions} "${secret.path}"
|
||||
'') manualSecrets)) + ''
|
||||
echo "Secrets Deployed"
|
||||
'';
|
||||
|
||||
checkScript = ''
|
||||
${scriptBase}
|
||||
|
||||
getUser() {
|
||||
stat --format "%U" "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
getGroup() {
|
||||
stat --format "%U" "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
getPermissions() {
|
||||
stat --format "%a" "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
GLOBAL_FAIL=false
|
||||
'' + (lib.concatStringsSep "\n" (lib.mapAttrsToList (name: secret: ''
|
||||
LOCAL_FAIL=false
|
||||
|
||||
echo "Secret: ${name}"
|
||||
echo "Checking ${secret.path}"
|
||||
|
||||
# some variables which can be used by checkScript
|
||||
# shellcheck disable=SC2034
|
||||
secretFile="${secret.path}"
|
||||
|
||||
if [[ -f "${secret.path}" ]]; then
|
||||
echo "✅ File Exists"
|
||||
else
|
||||
echo "❌ File Does Not Exist"
|
||||
LOCAL_FAIL=true
|
||||
fi
|
||||
|
||||
if getUser "${secret.path}" >/dev/null && [[ "$(getUser "${secret.path}")" == "${secret.user}" ]]; then
|
||||
echo "✅ File Is Owned By Correct User"
|
||||
else
|
||||
echo "❌ File Is Not Owned By Correct User (${secret.user})"
|
||||
LOCAL_FAIL=true
|
||||
fi
|
||||
|
||||
if getGroup "${secret.path}" >/dev/null && [[ "$(getGroup "${secret.path}")" == "${secret.group}" ]]; then
|
||||
echo "✅ File Is Owned By Correct Group"
|
||||
else
|
||||
echo "❌ File Is Not Owned By Correct Group (${secret.user})"
|
||||
LOCAL_FAIL=true
|
||||
fi
|
||||
|
||||
if getPermissions "${secret.path}" >/dev/null && [[ "$(getPermissions "${secret.path}")" -eq "${secret.permissions}" ]]; then
|
||||
echo "✅ File Has Correct Permissions"
|
||||
else
|
||||
echo "❌ File Does Not Have Correct Permissions (${secret.permissions})"
|
||||
LOCAL_FAIL=true
|
||||
fi
|
||||
|
||||
${if secret.checkScript != null then secret.checkScript else ""}
|
||||
|
||||
if [[ "$LOCAL_FAIL" == "true" ]]; then
|
||||
echo "❌ File Did Not Pass The Vibe Check"
|
||||
GLOBAL_FAIL=true
|
||||
else
|
||||
echo "✅ File Passed The Vibe Check"
|
||||
fi
|
||||
|
||||
echo
|
||||
'') cfg.secrets)) + ''
|
||||
if [[ "$GLOBAL_FAIL" == "true" ]]; then
|
||||
echo "❌ One Or More Secrets Did Not Pass The Vibe Check"
|
||||
exit 1
|
||||
else
|
||||
echo "✅ All Secrets Passed The Vibe Check"
|
||||
fi
|
||||
'';
|
||||
|
||||
in {
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellApplication {
|
||||
name = "secrets-check";
|
||||
runtimeInputs = defaultPackages ++ cfg.extraPackages;
|
||||
text = checkScript;
|
||||
})
|
||||
(pkgs.writeShellApplication {
|
||||
name = "secrets-init";
|
||||
runtimeInputs = defaultPackages ++ cfg.extraPackages;
|
||||
text = initScript;
|
||||
})
|
||||
];
|
||||
|
||||
}))
|
||||
|
||||
(mkIf (cfg.enable && cfg.createSecretsDir) {
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${cfg.secretsDir} - ${cfg.secretsDirUser} ${cfg.secretsDirGroup}"
|
||||
];
|
||||
})
|
||||
];
|
||||
}
|
|
@ -35,7 +35,8 @@ in {
|
|||
initrd.luks.devices = {
|
||||
"${drive_data.root_mapper_name}" = {
|
||||
device = "${drive_data.encrypted_root_path}";
|
||||
keyFile = "${usb_data.encryption_keys_path}/${config.networking.hostName}.key";
|
||||
keyFile =
|
||||
"${usb_data.encryption_keys_path}/${config.networking.hostName}.key";
|
||||
preLVM = false;
|
||||
allowDiscards = true;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue