Summary
Two related issues found during lab testing:
-
Config/docs gap: VaultSharp's PatchSecretAsync uses HTTP PATCH for passphrase writes on PFX/JKS/P12 KV stores. Vault/OpenBao requires an explicit patch capability in the policy — it is not implied by create or update. The typical example policy in documentation omits patch, causing all file-format Management-Add jobs to fail with 403.
-
Code quality: When this 403 occurs, the job completion message surfaces only the raw OpenBao response body ({"errors":[]}) with no HTTP status code. This makes it nearly impossible to diagnose from the Command job history without inspecting UO logs.
Environment
- Extension version: latest main
- Command version: v25.5.1
- OpenBao (Vault-compatible) — KV v2 engine
Symptom
Management-Add jobs for HCVKVPFX, HCVKVJKS, HCVKVP12 complete with CompletedWillRetry/Failure:
An error occured while adding lab-hcv-pfx to stores/pfx:
One or more errors occurred. ({"errors":[]}\n) - {"errors":[]}\n.
Certificate thumbprint: 5C125FF80A2B7D1A4D423D688526E1301D659C65.
HCVKVPEM Management-Add succeeds because PEM stores use WriteSecretAutoAsync (HTTP POST) throughout — they never call PatchSecretAutoAsync.
Root Cause
HcvKeyValueClient.CreateNewFileStore writes the passphrase at line ~197:
await PatchSecretAutoAsync(pathToWritePassphrase, passphraseSecretContent, _mountPoint);
PatchSecretAutoAsync calls _vaultClient.V1.Secrets.KeyValue.V2.PatchSecretAsync(...), which VaultSharp implements as PATCH /v1/{mount}/data/{path} with Content-Type: application/merge-patch+json.
Vault/OpenBao requires an explicit patch capability for HTTP PATCH (separate from create/update).
Fix
1. Document the required patch capability
Add to the README/documentation:
path "secret/data/stores/*" {
capabilities = ["create", "read", "update", "patch", "delete", "list"]
}
2. Improve error message to include HTTP status code
In PatchSecretAutoAsync (or the Management job handler), when a VaultApiException is caught, include ex.StatusCode in the propagated exception message so the job completion message visible in Command includes the HTTP status code (403, 404, 405, etc.) rather than just the raw body.
Example improvement:
throw new Exception($"Vault returned HTTP {ex.StatusCode} for {path}: {ex.Message}. API errors: [{string.Join(", ", ex.ApiErrors ?? new List<string>())}]", ex);
Verification
# Without patch capability — returns 403:
curl -X PATCH https://openbao.lab.local/v1/secret/data/stores/test \
-H "X-Vault-Token: $UO_TOKEN" \
-H "Content-Type: application/merge-patch+json" \
-d '{"data":{"passphrase":"x"}}'
# {"errors":["1 error occurred:\n\t* permission denied\n\n"]}
# With patch capability added — returns 200.
Summary
Two related issues found during lab testing:
Config/docs gap: VaultSharp's
PatchSecretAsyncuses HTTPPATCHfor passphrase writes on PFX/JKS/P12 KV stores. Vault/OpenBao requires an explicitpatchcapability in the policy — it is not implied bycreateorupdate. The typical example policy in documentation omitspatch, causing all file-format Management-Add jobs to fail with 403.Code quality: When this 403 occurs, the job completion message surfaces only the raw OpenBao response body (
{"errors":[]}) with no HTTP status code. This makes it nearly impossible to diagnose from the Command job history without inspecting UO logs.Environment
Symptom
Management-Add jobs for
HCVKVPFX,HCVKVJKS,HCVKVP12complete withCompletedWillRetry/Failure:HCVKVPEMManagement-Add succeeds because PEM stores useWriteSecretAutoAsync(HTTP POST) throughout — they never callPatchSecretAutoAsync.Root Cause
HcvKeyValueClient.CreateNewFileStorewrites the passphrase at line ~197:PatchSecretAutoAsynccalls_vaultClient.V1.Secrets.KeyValue.V2.PatchSecretAsync(...), which VaultSharp implements asPATCH /v1/{mount}/data/{path}withContent-Type: application/merge-patch+json.Vault/OpenBao requires an explicit
patchcapability for HTTPPATCH(separate fromcreate/update).Fix
1. Document the required
patchcapabilityAdd to the README/documentation:
2. Improve error message to include HTTP status code
In
PatchSecretAutoAsync(or the Management job handler), when aVaultApiExceptionis caught, includeex.StatusCodein the propagated exception message so the job completion message visible in Command includes the HTTP status code (403, 404, 405, etc.) rather than just the raw body.Example improvement:
Verification