From f8afdfcf186eca7cf66215e8f1bcc1d76c14a1ce Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Apr 2026 21:29:35 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20[nomad-step-2]=20S2-fix-E=20=E2=80=94=20?= =?UTF-8?q?vault-import.sh=20still=20writes=20to=20secret/data/=20not=20kv?= =?UTF-8?q?/data/=20(#926)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The S2 Nomad+Vault migration switched the KV v2 mount from `secret/` to `kv/` in policies, roles, templates, and lib/hvault.sh. tools/vault-import.sh was missed — its curl URL and 4 error messages still hardcoded `secret/data/`, so `disinto init --backend=nomad --with forgejo` hit 404 from vault on the first write (issue body reproduces it with the gardener bot path). Five call sites in _kv_put_secret flipped to `kv/data/`: the POST URL (L154) and the curl-error / 404 / 403 / non-2xx branches (L156, L167, L171, L175). The read helper is hvault_kv_get from lib/hvault.sh, which already resolves through VAULT_KV_MOUNT (default `kv`), so no change needed there. tests/vault-import.bats also updated: dev-mode vault only auto-mounts kv-v2 at secret/, so the test harness now enables a parallel kv-v2 mount at path=kv during setup_file to mirror the production cluster layout. Test-side URLs that assert round-trip reads all follow the same secret/ → kv/ rename. shellcheck clean. Co-Authored-By: Claude Opus 4.6 (1M context) --- tests/vault-import.bats | 27 +++++++++++++++++---------- tools/vault-import.sh | 10 +++++----- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/tests/vault-import.bats b/tests/vault-import.bats index aa7ac7b..890a900 100644 --- a/tests/vault-import.bats +++ b/tests/vault-import.bats @@ -34,6 +34,13 @@ setup_file() { return 1 fi done + + # Enable kv-v2 at path=kv (production mount per S2 migration). Dev-mode + # vault only auto-mounts kv-v2 at secret/; tests must mirror the real + # cluster layout so vault-import.sh writes land where we read them. + curl -sf -H "X-Vault-Token: test-root-token" \ + -X POST -d '{"type":"kv","options":{"version":"2"}}' \ + "${VAULT_ADDR}/v1/sys/mounts/kv" >/dev/null } teardown_file() { @@ -90,7 +97,7 @@ setup() { # Verify nothing was written to Vault run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/bots/review" + "${VAULT_ADDR}/v1/kv/data/disinto/bots/review" [ "$status" -ne 0 ] } @@ -105,21 +112,21 @@ setup() { # Check bots/review run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/bots/review" + "${VAULT_ADDR}/v1/kv/data/disinto/bots/review" [ "$status" -eq 0 ] echo "$output" | grep -q "review-token" echo "$output" | grep -q "review-pass" # Check bots/dev-qwen run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/bots/dev-qwen" + "${VAULT_ADDR}/v1/kv/data/disinto/bots/dev-qwen" [ "$status" -eq 0 ] echo "$output" | grep -q "llama-token" echo "$output" | grep -q "llama-pass" # Check forge run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/shared/forge" + "${VAULT_ADDR}/v1/kv/data/disinto/shared/forge" [ "$status" -eq 0 ] echo "$output" | grep -q "generic-forge-token" echo "$output" | grep -q "generic-forge-pass" @@ -127,7 +134,7 @@ setup() { # Check woodpecker run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/shared/woodpecker" + "${VAULT_ADDR}/v1/kv/data/disinto/shared/woodpecker" [ "$status" -eq 0 ] echo "$output" | grep -q "wp-agent-secret" echo "$output" | grep -q "wp-forgejo-client" @@ -136,7 +143,7 @@ setup() { # Check chat run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/shared/chat" + "${VAULT_ADDR}/v1/kv/data/disinto/shared/chat" [ "$status" -eq 0 ] echo "$output" | grep -q "forward-auth-secret" echo "$output" | grep -q "chat-client-id" @@ -144,7 +151,7 @@ setup() { # Check runner tokens from sops run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/runner/GITHUB_TOKEN" + "${VAULT_ADDR}/v1/kv/data/disinto/runner/GITHUB_TOKEN" [ "$status" -eq 0 ] echo "$output" | jq -e '.data.data.value == "github-test-token-abc123"' } @@ -194,7 +201,7 @@ setup() { # Verify the new value was written (path is disinto/bots/dev-qwen, key is token) run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/bots/dev-qwen" + "${VAULT_ADDR}/v1/kv/data/disinto/bots/dev-qwen" [ "$status" -eq 0 ] echo "$output" | jq -e '.data.data.token == "MODIFIED-LLAMA-TOKEN"' } @@ -228,13 +235,13 @@ setup() { # Verify each value round-trips intact. run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/bots/review" + "${VAULT_ADDR}/v1/kv/data/disinto/bots/review" [ "$status" -eq 0 ] echo "$output" | jq -e '.data.data.token == "abc|xyz"' echo "$output" | jq -e '.data.data.pass == "p1|p2|p3"' run curl -sf -H "X-Vault-Token: ${VAULT_TOKEN}" \ - "${VAULT_ADDR}/v1/secret/data/disinto/shared/forge" + "${VAULT_ADDR}/v1/kv/data/disinto/shared/forge" [ "$status" -eq 0 ] echo "$output" | jq -e '.data.data.admin_token == "admin|with|pipes"' } diff --git a/tools/vault-import.sh b/tools/vault-import.sh index d7a4a01..bea4a07 100755 --- a/tools/vault-import.sh +++ b/tools/vault-import.sh @@ -151,9 +151,9 @@ _kv_put_secret() { -X POST \ -d "$payload" \ -o "$tmpfile" \ - "${VAULT_ADDR}/v1/secret/data/${path}")" || { + "${VAULT_ADDR}/v1/kv/data/${path}")" || { rm -f "$tmpfile" - _err "Failed to write to Vault at secret/data/${path}: curl error" + _err "Failed to write to Vault at kv/data/${path}: curl error" return 1 } rm -f "$tmpfile" @@ -164,15 +164,15 @@ _kv_put_secret() { return 0 ;; 404) - _err "KV path not found: secret/data/${path}" + _err "KV path not found: kv/data/${path}" return 1 ;; 403) - _err "Permission denied writing to secret/data/${path}" + _err "Permission denied writing to kv/data/${path}" return 1 ;; *) - _err "Failed to write to Vault at secret/data/${path}: HTTP $http_code" + _err "Failed to write to Vault at kv/data/${path}: HTTP $http_code" return 1 ;; esac -- 2.49.1