Skip to content

Commit

Permalink
FIX URI path handling to remove double slashes
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
TaopaiC committed Sep 13, 2024
1 parent ad23081 commit 327f828
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
11 changes: 11 additions & 0 deletions lib/vault/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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}.
Expand Down Expand Up @@ -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
Expand Down
41 changes: 41 additions & 0 deletions spec/integration/api/logical_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")
Expand All @@ -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")
Expand Down

0 comments on commit 327f828

Please sign in to comment.