From 327f82893289bbf27856515b374842b40e0d71be Mon Sep 17 00:00:00 2001 From: TaopaiC <124380+TaopaiC@users.noreply.github.com> Date: Sat, 14 Sep 2024 00:09:26 +0800 Subject: [PATCH] FIX URI path handling to remove double slashes Fix request URI to remove double slashes. Vault server returns 301 redirect for double slash URIs, requiring resending. Since Vault server v1.17.3, the redirect URL has changed. For example, take key: `/cubbyhole/my-secret`: - Before vault v1.17.2, vault-ruby sends `/v1//cubbyhole/my%2Dsecret`, and the Vault server returns `/v1/cubbyhole/my-secret`. - After vault v1.17.3, vault-ruby sends `/v1//cubbyhole/my%2Dsecret`, and the Vault server returns `/v1/cubbyhole/my%252Dsecret`. Thus, the behavior is not the same. Removing the double slashes prevents the redirect mechanism from being triggered. --- lib/vault/client.rb | 11 ++++++++ spec/integration/api/logical_spec.rb | 41 ++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lib/vault/client.rb b/lib/vault/client.rb index cc82f40..cf03415 100644 --- a/lib/vault/client.rb +++ b/lib/vault/client.rb @@ -305,6 +305,15 @@ def request(verb, path, data = {}, headers = {}) end end + # Removes double slashes from a path. + # + # @param [String] + # + # @return [String] + def remove_double_slash(path) + path.b.gsub(%r{//+}, '/') + end + # Construct a URL from the given verb and path. If the request is a GET or # DELETE request, the params are assumed to be query params are are # converted as such using {Client#to_query_string}. @@ -333,6 +342,8 @@ def build_uri(verb, path, params = {}) # Don't merge absolute URLs uri = URI.parse(File.join(address, path)) unless uri.absolute? + uri.path = remove_double_slash(uri.path) + # Return the URI object uri end diff --git a/spec/integration/api/logical_spec.rb b/spec/integration/api/logical_spec.rb index 1d40592..914314e 100644 --- a/spec/integration/api/logical_spec.rb +++ b/spec/integration/api/logical_spec.rb @@ -58,6 +58,20 @@ module Vault expect(secret).to be expect(secret.data).to eq(foo: "bar") end + + it "allows double slash" do + subject.write("secret/test-read", foo: "bar") + secret = subject.read("secret///test-read") + expect(secret).to be + expect(secret.data).to eq(foo: "bar") + end + + it "allows double slash and special characters" do + subject.write("secret/b:@c%n-read-slash", foo: "bar") + secret = subject.read("secret///b:@c%n-read-slash") + expect(secret).to be + expect(secret.data).to eq(foo: "bar") + end end describe "#write" do @@ -84,6 +98,21 @@ module Vault expect(secret.data).to eq(bacon: true) end + it "allows double slash" do + subject.write("secret///test-write", zip: "zap") + result = subject.read("secret/test-write") + expect(result).to be + expect(result.data).to eq(zip: "zap") + end + + it "allows double slash and special characters" do + subject.write("secret///b:@c%n-write", foo: "bar") + subject.write("secret///b:@c%n-write", bacon: true) + secret = subject.read("secret/b:@c%n-write") + expect(secret).to be + expect(secret.data).to eq(bacon: true) + end + it "respects spaces properly" do key = 'secret/sub/"Test Group"' subject.write(key, foo: "bar") @@ -107,6 +136,18 @@ module Vault expect(subject.read("secret/b:@c%n-delete")).to be(nil) end + it "allows double slash" do + subject.write("secret/delete", foo: "bar") + expect(subject.delete("secret///delete")).to be(true) + expect(subject.read("secret/delete")).to be(nil) + end + + it "allows double slash and special characters" do + subject.write("secret/b:@c%n-delete-slash", foo: "bar") + expect(subject.delete("secret///b:@c%n-delete-slash")).to be(true) + expect(subject.read("secret/b:@c%n-delete-slash")).to be(nil) + end + it "does not error if the secret does not exist" do expect { subject.delete("secret/delete")