diff --git a/CHANGELOG.md b/CHANGELOG.md index b742be7..7c6b22a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +BUG FIXES + +- `Client#with_token` now sends the given token from API objects (`#logical`, `#auth`, ...) that the original client had already used. Before, the copy reused them, and their requests went out with the original client's token. + ## v0.20.1 (March 31, 2026) BUG FIXES diff --git a/lib/vault/client.rb b/lib/vault/client.rb index 836aca3..58015ed 100644 --- a/lib/vault/client.rb +++ b/lib/vault/client.rb @@ -96,6 +96,14 @@ def initialize(options = {}) @nhp = nil end + # The API objects (#logical, #auth, ...) are memoized with a reference to + # the client that built them. A copy must build its own, or a request + # through the copy would use the original client's token. + def initialize_copy(other) + super + @logical = @auth = @auth_token = @auth_tls = @approle = @sys = @transform = nil + end + def pool @lock.synchronize do return @nhp if @nhp diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb index 614f1d9..539153b 100644 --- a/spec/unit/client_spec.rb +++ b/spec/unit/client_spec.rb @@ -38,6 +38,18 @@ module Vault end expect(client.token).to eq("abcd-1234") end + + it "sends the new token from an API the original client already used" do + client = described_class.new(address: "http://vault.test", token: "abcd-1234") + stub_request(:get, "http://vault.test/v1/secret/foo") + .to_return(body: '{"data":{}}', headers: { "Content-Type" => "application/json" }) + client.logical.read("secret/foo") + + client.with_token("defg-5678") { |c| c.logical.read("secret/foo") } + + expect(a_request(:get, "http://vault.test/v1/secret/foo") + .with(headers: { "X-Vault-Token" => "defg-5678" })).to have_been_made.once + end end describe "#get" do