Add zitadel JWT mint service and tmpfiles; adjust juni mounts
This commit is contained in:
parent
127e6d38c1
commit
e5e32593b1
2 changed files with 144 additions and 58 deletions
|
|
@ -253,6 +253,7 @@ in
|
|||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /run/openbao 0700 root root - -"
|
||||
"f /run/openbao/zitadel.jwt 0400 root root - -"
|
||||
"d /run/secrets 0711 root root - -"
|
||||
];
|
||||
|
||||
|
|
@ -267,16 +268,99 @@ in
|
|||
"NetworkManager-wait-online.service"
|
||||
"systemd-resolved.service"
|
||||
];
|
||||
wants = [ "network-online.target" "NetworkManager-wait-online.service" "systemd-resolved.service" ];
|
||||
wants = [
|
||||
"network-online.target"
|
||||
"NetworkManager-wait-online.service"
|
||||
"systemd-resolved.service"
|
||||
];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
Group = "root";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "30s";
|
||||
TimeoutStartSec = "2min";
|
||||
UMask = "0077";
|
||||
|
||||
ExecStart = pkgs.writeShellScript "zitadel-mint-jwt-service" ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ ! -d "/run/openbao" ]; then
|
||||
${pkgs.coreutils}/bin/mkdir -p /run/openbao
|
||||
${pkgs.coreutils}/bin/chmod 0700 /run/openbao
|
||||
fi
|
||||
|
||||
if [ ! -f "${cfg.zitadelKeyPath}" ]; then
|
||||
echo "Missing Zitadel key JSON at ${cfg.zitadelKeyPath}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "zitadel-mint-jwt: starting (host=${zitadelHost})" >&2
|
||||
|
||||
jwt_is_valid() {
|
||||
local token="$1"
|
||||
local payload_b64 payload_json exp now
|
||||
|
||||
payload_b64="$(${pkgs.coreutils}/bin/printf '%s' "$token" | ${pkgs.coreutils}/bin/cut -d. -f2)"
|
||||
payload_b64="$(${pkgs.coreutils}/bin/printf '%s' "$payload_b64" | ${pkgs.gnused}/bin/sed -e 's/-/+/g' -e 's/_/\//g')"
|
||||
|
||||
case $((${pkgs.coreutils}/bin/printf '%s' "$payload_b64" | ${pkgs.coreutils}/bin/wc -c)) in
|
||||
*1) payload_b64="$payload_b64=" ;;
|
||||
*2) payload_b64="$payload_b64==" ;;
|
||||
*3) : ;;
|
||||
*0) : ;;
|
||||
esac
|
||||
|
||||
payload_json="$(${pkgs.coreutils}/bin/printf '%s' "$payload_b64" | ${pkgs.coreutils}/bin/base64 -d 2>/dev/null || true)"
|
||||
exp="$(${pkgs.jq}/bin/jq -r '.exp // empty' <<<"$payload_json" 2>/dev/null || true)"
|
||||
if [ -z "$exp" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
now="$(${pkgs.coreutils}/bin/date +%s)"
|
||||
if [ "$exp" -gt $(( now + 60 )) ]; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ -s "${cfg.zitadelJwtPath}" ] && jwt_is_valid "$(cat "${cfg.zitadelJwtPath}")"; then
|
||||
echo "zitadel-mint-jwt: existing token still valid; skipping" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
jwt="$(${mkJwtMintScript})"
|
||||
|
||||
if [ -z "$jwt" ] || [ "$jwt" = "null" ]; then
|
||||
echo "Failed to mint Zitadel access token" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp="$(${pkgs.coreutils}/bin/mktemp)"
|
||||
trap '${pkgs.coreutils}/bin/rm -f "$tmp"' EXIT
|
||||
${pkgs.coreutils}/bin/printf '%s' "$jwt" > "$tmp"
|
||||
|
||||
# In-place update so the agent's file watcher sees changes.
|
||||
${pkgs.coreutils}/bin/cat "$tmp" > "${cfg.zitadelJwtPath}"
|
||||
${pkgs.coreutils}/bin/chmod 0400 "${cfg.zitadelJwtPath}" || true
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
vault-agent = {
|
||||
description = "OpenBao agent for rendering secrets";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" "zitadel-mint-jwt.service" ];
|
||||
wants = [ "network-online.target" "zitadel-mint-jwt.service" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "root";
|
||||
Group = "root";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
|
||||
|
||||
TimeoutStartSec = "30s";
|
||||
UMask = "0077";
|
||||
ExecStart = "${pkgs.openbao}/bin/bao agent -log-level=debug -config=${mkAgentConfig}";
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ let
|
|||
IMPERMANENCE = true;
|
||||
ENCRYPTED = true;
|
||||
|
||||
USB_KEY = null;
|
||||
|
||||
USB_KEY_PATH = if USB_KEY == null then "" else USB_KEY;
|
||||
USB_KEY = "/dev/disk/by-uuid/ea3e20f6-c7f2-407c-b9a2-00b4ac000178";
|
||||
|
||||
primaryDeviceUnit = "${utils.escapeSystemdPath PRIMARY}.device";
|
||||
in
|
||||
|
|
@ -221,68 +219,72 @@ lib.mkMerge [
|
|||
TTYVTDisallocate = true;
|
||||
};
|
||||
|
||||
script = ''
|
||||
unlock_with_usb_key() {
|
||||
if [[ -z "${USB_KEY_PATH}" ]]; then
|
||||
return 2
|
||||
fi
|
||||
|
||||
echo "Searching for USB unlock key..."
|
||||
KEY_FOUND=0
|
||||
# 4 second search
|
||||
for i in {1..40}; do
|
||||
if [ -e "${USB_KEY_PATH}" ]; then
|
||||
KEY_FOUND=1
|
||||
break
|
||||
script =
|
||||
let
|
||||
USB_KEY_PATH = if USB_KEY == null then "" else USB_KEY;
|
||||
in
|
||||
''
|
||||
unlock_with_usb_key() {
|
||||
if [[ -z "${USB_KEY_PATH}" ]]; then
|
||||
return 2
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
if [ "$KEY_FOUND" -ne 1 ]; then
|
||||
echo "USB key not found within timeout."
|
||||
return 2
|
||||
fi
|
||||
echo "Searching for USB unlock key..."
|
||||
KEY_FOUND=0
|
||||
# 4 second search
|
||||
for i in {1..40}; do
|
||||
if [ -e "${USB_KEY_PATH}" ]; then
|
||||
KEY_FOUND=1
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
echo "USB key found at ${USB_KEY_PATH}. Attempting unlock..."
|
||||
mkdir -p /tmp/usb_key_mount
|
||||
if [ "$KEY_FOUND" -ne 1 ]; then
|
||||
echo "USB key not found within timeout."
|
||||
return 2
|
||||
fi
|
||||
|
||||
# Mount read-only
|
||||
if ! mount -t bcachefs -o ro "${USB_KEY_PATH}" /tmp/usb_key_mount; then
|
||||
echo "Failed to mount USB key device."
|
||||
return 1
|
||||
fi
|
||||
echo "USB key found at ${USB_KEY_PATH}. Attempting unlock..."
|
||||
mkdir -p /tmp/usb_key_mount
|
||||
|
||||
if ${pkgs.bcachefs-tools}/bin/bcachefs unlock -f /tmp/usb_key_mount/key "${PRIMARY}"; then
|
||||
umount /tmp/usb_key_mount || true
|
||||
echo "Bcachefs unlock successful (USB key)!"
|
||||
return 0
|
||||
fi
|
||||
# Mount read-only
|
||||
if ! mount -t bcachefs -o ro "${USB_KEY_PATH}" /tmp/usb_key_mount; then
|
||||
echo "Failed to mount USB key device."
|
||||
return 1
|
||||
fi
|
||||
|
||||
umount /tmp/usb_key_mount || true
|
||||
echo "Failed to unlock with USB key."
|
||||
return 1
|
||||
}
|
||||
|
||||
unlock_with_passphrase_until_success() {
|
||||
echo "Unlocking ${PRIMARY} (will retry on failure)..."
|
||||
while true; do
|
||||
if ${pkgs.bcachefs-tools}/bin/bcachefs unlock "${PRIMARY}"; then
|
||||
echo "Bcachefs unlock successful (passphrase)!"
|
||||
if ${pkgs.bcachefs-tools}/bin/bcachefs unlock -f /tmp/usb_key_mount/key "${PRIMARY}"; then
|
||||
umount /tmp/usb_key_mount || true
|
||||
echo "Bcachefs unlock successful (USB key)!"
|
||||
return 0
|
||||
fi
|
||||
echo "Unlock failed. Try again."
|
||||
sleep 0.2
|
||||
done
|
||||
}
|
||||
|
||||
# 1) Optional USB key unlock attempt (if configured)
|
||||
if unlock_with_usb_key; then
|
||||
exit 0
|
||||
fi
|
||||
umount /tmp/usb_key_mount || true
|
||||
echo "Failed to unlock with USB key."
|
||||
return 1
|
||||
}
|
||||
|
||||
# 2) If USB key not configured or failed, prompt for passphrase and retry
|
||||
unlock_with_passphrase_until_success
|
||||
'';
|
||||
unlock_with_passphrase_until_success() {
|
||||
echo "Unlocking ${PRIMARY} (will retry on failure)..."
|
||||
while true; do
|
||||
if ${pkgs.bcachefs-tools}/bin/bcachefs unlock "${PRIMARY}"; then
|
||||
echo "Bcachefs unlock successful (passphrase)!"
|
||||
return 0
|
||||
fi
|
||||
echo "Unlock failed. Try again."
|
||||
sleep 0.2
|
||||
done
|
||||
}
|
||||
|
||||
# 1) Optional USB key unlock attempt (if configured)
|
||||
if unlock_with_usb_key; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 2) If USB key not configured or failed, prompt for passphrase and retry
|
||||
unlock_with_passphrase_until_success
|
||||
'';
|
||||
};
|
||||
})
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue