{ config, lib, pkgs, ... }: let cfg = config.ringofstorms.secretsBao; mkJwtMintScript = pkgs.writeShellScript "zitadel-mint-jwt" '' #!/usr/bin/env bash set -euo pipefail key_json="${cfg.zitadelKeyPath}" kid="$(${pkgs.jq}/bin/jq -r .keyId "$key_json")" sub="$(${pkgs.jq}/bin/jq -r .userId "$key_json")" pem_file="$(${pkgs.coreutils}/bin/mktemp)" trap '${pkgs.coreutils}/bin/rm -f "$pem_file"' EXIT ${pkgs.jq}/bin/jq -r .key "$key_json" >"$pem_file" ${pkgs.coreutils}/bin/chmod 600 "$pem_file" now="$(${pkgs.coreutils}/bin/date +%s)" exp="$(( now + ${toString cfg.jwtLifetimeSeconds} ))" jti="$(${pkgs.openssl}/bin/openssl rand -hex 16)" header="$(${pkgs.jq}/bin/jq -cn --arg kid "$kid" '{alg:"RS256",typ:"JWT",kid:$kid}')" payload="$(${pkgs.jq}/bin/jq -cn \ --arg iss "$sub" \ --arg sub "$sub" \ --arg aud "${cfg.zitadelTokenEndpoint}" \ --arg jti "$jti" \ --argjson iat "$now" \ --argjson exp "$exp" \ '{iss:$iss,sub:$sub,aud:$aud,iat:$iat,exp:$exp,jti:$jti}' )" b64url() { ${pkgs.openssl}/bin/openssl base64 -A | ${pkgs.gnused}/bin/sed -e 's/+/-/g' -e 's/\//_/g' -e 's/=*$//' } h64="$(${pkgs.coreutils}/bin/printf '%s' "$header" | b64url)" p64="$(${pkgs.coreutils}/bin/printf '%s' "$payload" | b64url)" sig="$(${pkgs.coreutils}/bin/printf '%s' "$h64.$p64" | ${pkgs.openssl}/bin/openssl dgst -sha256 -sign "$pem_file" | b64url)" assertion="$h64.$p64.$sig" resp="" if ! resp="$(${pkgs.curl}/bin/curl -sS --fail-with-body \ --connect-timeout 5 --max-time 30 \ --retry 20 --retry-delay 2 --retry-all-errors \ -X POST "${cfg.zitadelTokenEndpoint}" \ -H 'content-type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' \ --data-urlencode "assertion=$assertion" \ --data-urlencode "scope=${cfg.zitadelScopes}" \ )"; then echo "Zitadel token endpoint returned error; response:" >&2 echo "$resp" >&2 exit 1 fi token="$(${pkgs.jq}/bin/jq -r '.access_token // empty' <<<"$resp" 2>/dev/null || true)" if [ -z "$token" ] || [ "$token" = "null" ]; then echo "Zitadel token mint did not return access_token; response:" >&2 echo "$resp" >&2 exit 1 fi # Quick sanity check: JWT should have 2 dots. if ! ${pkgs.gnugrep}/bin/grep -q '\\.' <<<"$token"; then echo "Zitadel access_token does not look like a JWT; response:" >&2 echo "$resp" >&2 exit 1 fi ${pkgs.coreutils}/bin/printf '%s' "$token" ''; zitadelHost = let noProto = lib.strings.removePrefix "https://" (lib.strings.removePrefix "http://" cfg.zitadelTokenEndpoint); in builtins.head (lib.strings.splitString "/" noProto); mkAgentConfig = pkgs.writeText "vault-agent.hcl" '' vault { address = "${cfg.openBaoAddr}" } auto_auth { method "jwt" { mount_path = "${cfg.jwtAuthMountPath}" config = { role = "${cfg.openBaoRole}" jwt_file = "${cfg.zitadelJwtPath}" } } sink "file" { config = { path = "${cfg.vaultAgentTokenPath}" mode = 0400 } } } ${lib.concatStringsSep "\n\n" ( lib.mapAttrsToList ( name: secret: let renderedTemplate = if secret.template != null then secret.template else ''{{- with secret "${secret.kvPath}" -}}{{- .Data.data.${secret.field} -}}{{- end -}}''; in '' template { destination = "${secret.path}" perms = "${secret.mode}" contents = <&2 exit 1 ''; }; } ) cfg.secrets) ]; age.secrets = lib.mapAttrs' ( name: secret: lib.nameValuePair name { file = null; path = secret.path; } ) cfg.secrets; }; }