Add secrets-bao with sec CLI; use in hosts; fix git helpers
This commit is contained in:
parent
c223dedb70
commit
f8f93a97dc
6 changed files with 192 additions and 33 deletions
|
|
@ -1,9 +1,9 @@
|
|||
gcamp() {
|
||||
VISUAL=vi EDITOR=vi gcam "$(gcpropose -a | vipe)"
|
||||
VISUAL=vi EDITOR=vi git commit -a -m "$(gcpropose -a | vipe)"
|
||||
}
|
||||
|
||||
gcmp() {
|
||||
VISUAL=vi EDITOR=vi gcm "$(gcpropose | vipe)"
|
||||
VISUAL=vi EDITOR=vi git commit -m "$(gcpropose | vipe)"
|
||||
}
|
||||
|
||||
gcpropose() {
|
||||
|
|
|
|||
|
|
@ -196,6 +196,76 @@ let
|
|||
in
|
||||
builtins.head (lib.strings.splitString "/" noProto);
|
||||
|
||||
sec = pkgs.writeShellScriptBin "sec" ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$(${pkgs.coreutils}/bin/id -u)" -ne 0 ]; then
|
||||
exec ${pkgs.sudo}/bin/sudo "$0" "$@"
|
||||
fi
|
||||
|
||||
vault_addr=${lib.escapeShellArg cfg.openBaoAddr}
|
||||
jwt_mount_path=${lib.escapeShellArg cfg.jwtAuthMountPath}
|
||||
role=${lib.escapeShellArg cfg.openBaoRole}
|
||||
jwt_path=${lib.escapeShellArg cfg.zitadelJwtPath}
|
||||
token_path=${lib.escapeShellArg cfg.vaultAgentTokenPath}
|
||||
|
||||
usage() {
|
||||
echo "usage: sec <kv-path> [field]" >&2
|
||||
echo " examples:" >&2
|
||||
echo " sec machines/home_roaming/test value" >&2
|
||||
echo " sec kv/data/machines/home_roaming/test value" >&2
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "sec: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
kv_path="''${1-}"
|
||||
field="''${2:-value}"
|
||||
|
||||
if [ -z "$kv_path" ] || [ "$kv_path" = "-h" ] || [ "$kv_path" = "--help" ]; then
|
||||
usage
|
||||
exit 2
|
||||
fi
|
||||
|
||||
export VAULT_ADDR="$vault_addr"
|
||||
|
||||
token=""
|
||||
|
||||
if [ -r "$token_path" ] && [ -s "$token_path" ]; then
|
||||
token="$(cat "$token_path")"
|
||||
else
|
||||
if [ ! -r "$jwt_path" ] || [ ! -s "$jwt_path" ]; then
|
||||
die "Missing JWT at $jwt_path (try: systemctl start zitadel-mint-jwt)"
|
||||
fi
|
||||
|
||||
token="$(${pkgs.openbao}/bin/bao write -field=token "$jwt_mount_path/login" role="$role" jwt="$(cat "$jwt_path")")"
|
||||
fi
|
||||
|
||||
if [ -z "$token" ] || [ "$token" = "null" ]; then
|
||||
die "Failed to get OpenBao token"
|
||||
fi
|
||||
|
||||
export VAULT_TOKEN="$token"
|
||||
|
||||
# Accept either KV v2 logical paths (machines/foo/bar) or raw API paths (kv/data/machines/foo/bar).
|
||||
if [[ "$kv_path" == kv/data/* ]]; then
|
||||
json="$(${pkgs.openbao}/bin/bao read -format=json "$kv_path")"
|
||||
else
|
||||
json="$(${pkgs.openbao}/bin/bao kv get -format=json -mount=kv "$kv_path")"
|
||||
fi
|
||||
|
||||
value="$(${pkgs.jq}/bin/jq -er --arg field "$field" '.data.data[$field]' <<<"$json" 2>/dev/null || true)"
|
||||
|
||||
if [ -z "$value" ] || [ "$value" = "null" ]; then
|
||||
die "Field not found: $field"
|
||||
fi
|
||||
|
||||
printf '%s\n' "$value"
|
||||
'';
|
||||
|
||||
mkAgentConfig = pkgs.writeText "vault-agent.hcl" ''
|
||||
vault {
|
||||
address = "${cfg.openBaoAddr}"
|
||||
|
|
@ -245,12 +315,6 @@ let
|
|||
|
||||
in
|
||||
{
|
||||
options.age.secrets = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.anything;
|
||||
default = { };
|
||||
description = "Compatibility shim for modules that expect config.age.secrets.<name>.path.";
|
||||
};
|
||||
|
||||
options.ringofstorms.secretsBao = {
|
||||
enable = lib.mkEnableOption "Fetch runtime secrets via OpenBao";
|
||||
|
||||
|
|
@ -409,6 +473,7 @@ in
|
|||
pkgs.openssl
|
||||
pkgs.openbao
|
||||
zitadelMintJwt
|
||||
sec
|
||||
];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
|
|
@ -594,16 +659,7 @@ in
|
|||
}
|
||||
) cfg.secrets)
|
||||
];
|
||||
|
||||
age.secrets = lib.mapAttrs' (
|
||||
name: secret:
|
||||
lib.nameValuePair name {
|
||||
file = null;
|
||||
path = secret.path;
|
||||
}
|
||||
) cfg.secrets;
|
||||
}
|
||||
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
|||
15
flakes/secrets-bao/readme.md
Normal file
15
flakes/secrets-bao/readme.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
- Create machine in zitadel and generate a key. Put that at /machine-key.json
|
||||
- sudo chmod
|
||||
|
||||
## CLI
|
||||
|
||||
If `ringofstorms.secretsBao.enable = true`, you also get a `sec` helper.
|
||||
|
||||
It reads `/run/openbao/*` files, so it will `sudo` itself if needed.
|
||||
|
||||
- `sec <kv-path> [field]` reads a field (default: `value`) from KV v2.
|
||||
- It reuses `/run/openbao/vault-agent.token` when available, otherwise it logs in via the same jwt auth mount path using `/run/openbao/zitadel.jwt`.
|
||||
|
||||
Example:
|
||||
|
||||
- `sec machines/home_roaming/test value`
|
||||
|
|
@ -69,7 +69,6 @@
|
|||
})
|
||||
inputs.common.nixosModules.jetbrains_font
|
||||
|
||||
inputs.secrets-bao.nixosModules.default
|
||||
inputs.ros_neovim.nixosModules.default
|
||||
({
|
||||
ringofstorms-nvim.includeAllRuntimeDependencies = true;
|
||||
|
|
@ -115,6 +114,7 @@
|
|||
)
|
||||
inputs.common.nixosModules.remote_lio_builds
|
||||
|
||||
inputs.secrets-bao.nixosModules.default
|
||||
(
|
||||
{ inputs, lib, ... }:
|
||||
let
|
||||
|
|
@ -124,6 +124,12 @@
|
|||
dependencies = [ "tailscaled" ];
|
||||
configChanges.services.tailscale.authKeyFile = "$SECRET_PATH";
|
||||
};
|
||||
"atuin-key-josh" = {
|
||||
owner = "josh";
|
||||
group = "users";
|
||||
mode = "0400";
|
||||
template = ''{{- with secret "kv/data/machines/home_roaming/atuin-key-josh" -}}{{ printf "%s\n%s\n%s" .Data.data.user .Data.data.password .Data.data.value }}{{- end -}}'';
|
||||
};
|
||||
nix2github = {
|
||||
owner = "josh";
|
||||
group = "users";
|
||||
|
|
@ -295,6 +301,50 @@
|
|||
"com.spotify.Client"
|
||||
"com.bitwarden.desktop"
|
||||
];
|
||||
|
||||
systemd.services.atuin-autologin = {
|
||||
description = "Auto-login to Atuin (if logged out)";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" "openbao-secret-atuin-key-josh.service" ];
|
||||
wants = [ "network-online.target" "openbao-secret-atuin-key-josh.service" ];
|
||||
requires = [ "openbao-secret-atuin-key-josh.service" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "josh";
|
||||
Group = "users";
|
||||
Environment = [
|
||||
"HOME=/home/josh"
|
||||
"XDG_CONFIG_HOME=/home/josh/.config"
|
||||
"XDG_DATA_HOME=/home/josh/.local/share"
|
||||
];
|
||||
|
||||
ExecStart = pkgs.writeShellScript "atuin-autologin" ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
secret="/run/secrets/atuin-key-josh"
|
||||
if [ ! -s "$secret" ]; then
|
||||
echo "Missing atuin secret at $secret" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# status exits non-zero when logged out.
|
||||
out="$(${pkgs.atuin}/bin/atuin status 2>&1)" && exit 0
|
||||
|
||||
if [[ "$out" != *"You are not logged in"* ]]; then
|
||||
echo "$out" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
username="$(${pkgs.coreutils}/bin/sed -n '1p' "$secret")"
|
||||
password="$(${pkgs.coreutils}/bin/sed -n '2p' "$secret")"
|
||||
key="$(${pkgs.coreutils}/bin/sed -n '3p' "$secret")"
|
||||
|
||||
exec ${pkgs.atuin}/bin/atuin login --username "$username" --password "$password" --key "$key"
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
|
|
|
|||
32
hosts/lio/flake.lock
generated
32
hosts/lio/flake.lock
generated
|
|
@ -63,20 +63,14 @@
|
|||
},
|
||||
"common": {
|
||||
"locked": {
|
||||
"dir": "flakes/common",
|
||||
"lastModified": 1767740224,
|
||||
"narHash": "sha256-7yUQUw/7IMTBHy2EtuDggE8+NwUN3vDH5fwiTQDIrsI=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "4bc645061b8c3108fdb3ee92a61dbe3e98ecdaea",
|
||||
"revCount": 1082,
|
||||
"type": "git",
|
||||
"url": "https://git.joshuabell.xyz/ringofstorms/dotfiles"
|
||||
"path": "../../flakes/common",
|
||||
"type": "path"
|
||||
},
|
||||
"original": {
|
||||
"dir": "flakes/common",
|
||||
"type": "git",
|
||||
"url": "https://git.joshuabell.xyz/ringofstorms/dotfiles"
|
||||
}
|
||||
"path": "../../flakes/common",
|
||||
"type": "path"
|
||||
},
|
||||
"parent": []
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
|
|
@ -1321,7 +1315,8 @@
|
|||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"opencode": "opencode",
|
||||
"ros_neovim": "ros_neovim",
|
||||
"secrets": "secrets"
|
||||
"secrets": "secrets",
|
||||
"secrets-bao": "secrets-bao"
|
||||
}
|
||||
},
|
||||
"ros_neovim": {
|
||||
|
|
@ -1460,6 +1455,17 @@
|
|||
"url": "https://git.joshuabell.xyz/ringofstorms/dotfiles"
|
||||
}
|
||||
},
|
||||
"secrets-bao": {
|
||||
"locked": {
|
||||
"path": "../../flakes/secrets-bao",
|
||||
"type": "path"
|
||||
},
|
||||
"original": {
|
||||
"path": "../../flakes/secrets-bao",
|
||||
"type": "path"
|
||||
},
|
||||
"parent": []
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@
|
|||
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
|
||||
# Use relative to get current version for testing
|
||||
# common.url = "path:../../flakes/common";
|
||||
common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/common";
|
||||
common.url = "path:../../flakes/common";
|
||||
# common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/common";
|
||||
# secrets.url = "path:../../flakes/secrets";
|
||||
secrets.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/secrets";
|
||||
secrets-bao.url = "path:../../flakes/secrets-bao";
|
||||
# secrets-bao.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/secrets-bao";
|
||||
# flatpaks.url = "path:../../flakes/flatpaks";
|
||||
flatpaks.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/flatpaks";
|
||||
# beszel.url = "path:../../flakes/beszel";
|
||||
|
|
@ -95,6 +97,36 @@
|
|||
common.nixosModules.zsh
|
||||
common.nixosModules.more_filesystems
|
||||
|
||||
inputs.secrets-bao.nixosModules.default
|
||||
(
|
||||
{ inputs, lib, ... }:
|
||||
let
|
||||
secrets = {
|
||||
headscale_auth = {
|
||||
kvPath = "kv/data/machines/home_roaming/headscale_auth";
|
||||
# dependencies = [ "tailscaled" ];
|
||||
# configChanges.services.tailscale.authKeyFile = "$SECRET_PATH"; # TODO remove secrets and enable this
|
||||
};
|
||||
};
|
||||
in
|
||||
lib.mkMerge [
|
||||
{
|
||||
ringofstorms.secretsBao = {
|
||||
enable = true;
|
||||
zitadelKeyPath = "/machine-key.json";
|
||||
openBaoAddr = "https://sec.joshuabell.xyz";
|
||||
jwtAuthMountPath = "auth/zitadel-jwt";
|
||||
openBaoRole = "machines";
|
||||
zitadelIssuer = "https://sso.joshuabell.xyz";
|
||||
zitadelProjectId = "344379162166820867";
|
||||
inherit secrets;
|
||||
};
|
||||
}
|
||||
(inputs.secrets-bao.lib.applyConfigChanges secrets)
|
||||
(inputs.secrets-bao.lib.applyHmChanges secrets)
|
||||
]
|
||||
)
|
||||
|
||||
beszel.nixosModules.agent
|
||||
({
|
||||
beszelAgent = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue