Skip to content

Commit

Permalink
Update signer_v4_test_data.json from google-cloud-dotnet
Browse files Browse the repository at this point in the history
Remove trailing slash from path if no file.
Update CGI.escape to Addressable::URI.escape.

[refs googleapis#3081]
  • Loading branch information
quartzmo committed Apr 1, 2019
1 parent 45792ce commit 23e8f93
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 45 deletions.
12 changes: 5 additions & 7 deletions google-cloud-storage/lib/google/cloud/storage/file/signer_v4.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


require "base64"
require "cgi"
require "addressable/uri"
require "openssl"
require "google/cloud/storage/errors"

Expand Down Expand Up @@ -78,7 +78,6 @@ def signed_url method: "GET", expires: nil, headers: nil,
canonical_headers_str,
signed_headers_str,
"UNSIGNED-PAYLOAD"].join("\n")

# Construct string to sign
req_sha = Digest::SHA256.hexdigest canonical_request
string_to_sign = [algorithm, goog_date, scope, req_sha].join "\n"
Expand Down Expand Up @@ -128,12 +127,11 @@ def canonical_query query, algorithm, credential, goog_date, expires,
end

##
# The external path to the file.
# The URI-encoded (percent encoded) external path to the file.
def ext_path
escaped_path = String(@file_name).split("/").map do |node|
CGI.escape node
end.join("/")
"/#{CGI.escape @bucket_name}/#{escaped_path}"
path = "/#{@bucket_name}"
path += "/#{String(@file_name)}" if @file_name && !@file_name.empty?
Addressable::URI.escape path
end

##
Expand Down
44 changes: 13 additions & 31 deletions google-cloud-storage/test/data/signer_v4_test_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"method": "POST",
"expiration": 10,
"headers": {
"x-goog-resumable": [ "start" ]
"x-goog-resumable": "start"
},
"timestamp": "20190201T090000Z",
"expectedUrl": "https://storage.googleapis.com/test-bucket/test-object?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=test-iam-credentials%40dummy-project-id.iam.gserviceaccount.com%2F20190201%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190201T090000Z&X-Goog-Expires=10&X-Goog-SignedHeaders=host%3Bx-goog-resumable&X-Goog-Signature=4a6d39b23343cedf4c30782aed4b384001828c79ffa3a080a481ea01a640dea0a0ceb58d67a12cef3b243c3f036bb3799c6ee88e8db3eaf7d0bdd4b70a228d0736e07eaa1ee076aff5c6ce09dff1f1f03a0d8ead0d2893408dd3604fdabff553aa6d7af2da67cdba6790006a70240f96717b98f1a6ccb24f00940749599be7ef72aaa5358db63ddd54b2de9e2d6d6a586eac4fe25f36d86fc6ab150418e9c6fa01b732cded226c6d62fc95b72473a4cc55a8257482583fe66d9ab6ede909eb41516a8690946c3e87b0f2052eb0e97e012a14b2f721c42e6e19b8a1cd5658ea36264f10b9b1ada66b8ed5bf7ed7d1708377ac6e5fe608ae361fb594d2e5b24c54"
Expand Down Expand Up @@ -57,70 +57,52 @@
"bucket": "test-bucket",
"object": "test-object",
"headers": {
"foo": [ "foo-value" ],
"BAR": [ "BAR-value" ]
"foo": "foo-value",
"BAR": "BAR-value"
},
"method": "GET",
"expiration": 10,
"timestamp": "20190201T090000Z",
"expectedUrl": "https://storage.googleapis.com/test-bucket/test-object?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=test-iam-credentials%40dummy-project-id.iam.gserviceaccount.com%2F20190201%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190201T090000Z&X-Goog-Expires=10&X-Goog-SignedHeaders=bar%3Bfoo%3Bhost&X-Goog-Signature=68ecd3b008328ed30d91e2fe37444ed7b9b03f28ed4424555b5161980531ef87db1c3a5bc0265aad5640af30f96014c94fb2dba7479c41bfe1c020eb90c0c6d387d4dd09d4a5df8b60ea50eb6b01cdd786a1e37020f5f95eb8f9b6cd3f65a1f8a8a65c9fcb61ea662959efd9cd73b683f8d8804ef4d6d9b2852419b013368842731359d7f9e6d1139032ceca75d5e67cee5fd0192ea2125e5f2955d38d3d50cf116f3a52e6a62de77f6207f5b95aaa1d7d0f8a46de89ea72e7ea30f21286318d7eba0142232b0deb3a1dc9e1e812a981c66b5ffda3c6b01a8a9d113155792309fd53a3acfd054ca7776e8eec28c26480cd1e3c812f67f91d14217f39a606669d"
},

// Note: some platforms may not expose multi-value headers to clients. They could skip
// this test or perform the concatenation of header values themselves.
{
"description": "Multi-value headers",
"bucket": "test-bucket",
"object": "test-object",
"headers": {
"foo": [ "foo-value1", "foo-value2" ],
"bar": [ "bar-value1", "bar-value2" ]
},
"method": "GET",
"expiration": 10,
"timestamp": "20190201T090000Z",
"expectedUrl": "https://storage.googleapis.com/test-bucket/test-object?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=test-iam-credentials%40dummy-project-id.iam.gserviceaccount.com%2F20190201%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190201T090000Z&X-Goog-Expires=10&X-Goog-SignedHeaders=bar%3Bfoo%3Bhost&X-Goog-Signature=84a14ff388457290bc3ed7bfeb4745a1c2287e58965457d9d9959326fc2cbdfbb9128b6a002e86d617cb1d2187e3e075de223489d4e91418de76e21d4e561c618bc13ac72e1cc3b4e0c9eee880be577c417eb4623347d3d1ffd2a0705ab70bab6786f67107d05dc4652f2b84531dc01a15efa9ee3fbe504f6e76e64658fd1df431bf671a997db8ef7371eae8abbcc2690c085407738e32f396d9b87d0e974740ee0b7a256fc8471db27a6b554527b96dbd972073b89f57d6486182816b0d307875f1753bf16140332c6116899447769dd9f1985a520ca6ab50c614a80b3619e9d9a81ff81a6c14f51f1cf487243c2708aa9064e30acb5694af04c3fe0f5fd5a4"
},

{
"description": "Headers should be trimmed",
"bucket": "test-bucket",
"object": "test-object",
"headers": {
"leading": [ " xyz" ],
"trailing": [ "abc " ],
"collapsed": [ "abc def" ]
"leading": " xyz",
"trailing": "abc ",
"collapsed": "abc def"
},
"method": "GET",
"expiration": 10,
"timestamp": "20190201T090000Z",
"expectedUrl": "https://storage.googleapis.com/test-bucket/test-object?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=test-iam-credentials%40dummy-project-id.iam.gserviceaccount.com%2F20190201%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190201T090000Z&X-Goog-Expires=10&X-Goog-SignedHeaders=collapsed%3Bhost%3Bleading%3Btrailing&X-Goog-Signature=1839511d6238d9ac2bbcbba8b23515b3757db35dfa7b8f9bc4b8b4aa270224df747c812526f1a3bcf294d67ed84cd14e074c36bc090e0a542782934a7c925af4a5ea68123e97533704ce8b08ccdf5fe6b412f89c9fc4de243e29abdb098382c5672188ee3f6fef7131413e252c78e7a35658825ad842a50609e9cc463731e17284ff7a14824c989f87cef22fb99dfec20cfeed69d8b3a08f00b43b8284eecd535e50e982b05cd74c5750cd5f986cfc21a2a05f7f3ab7fc31bd684ed1b823b64d29281e923fc6580c49005552ca19c253de087d9d2df881144e44eda40965cfdb4889bf3a35553c9809f4ed20b8355be481b92b9618952b6a04f3017b36053e15"
},

// Separated from "Headers should be trimmed" test so it can be skipped on single-header-value-only platforms.
{
"description": "Trimming of multiple header values",
"description": "Header value with multiple inline values",
"bucket": "test-bucket",
"object": "test-object",
"headers": {
"foo": [ " abc ", " def ", " ghi jkl " ]
"multiple": " xyz , abc, def , xyz "
},
"method": "GET",
"expiration": 10,
"timestamp": "20190201T090000Z",
"expectedUrl": "https://storage.googleapis.com/test-bucket/test-object?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=test-iam-credentials%40dummy-project-id.iam.gserviceaccount.com%2F20190201%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190201T090000Z&X-Goog-Expires=10&X-Goog-SignedHeaders=foo%3Bhost&X-Goog-Signature=96e36a82dd79e6d37070b5dfaffc616e8c5159c583261dd3858c2241c2a34f270f4fe2bf55ba6877a7c982f34b0b9114683ba37880e3ec378942972882dbcb99c6463573178c6167acc40b2be8db7f3a320de47373c30626a37fe9e6cc719ee6060f573bf1a30ef5e86338e834494c089226bef3722bf8ae2fa3a7599916bec92df30cf25852c3514e3be0f4541063cea2babf4825b8e38876454f1502f5e307d32381aa927113104a75c82a23f7e9597016ca0bc4971d5990515df2a0239a62c711d3aacea50b8e05106ae2a14201bd6dae369334c27fad5c14dac66103c5c1a980b3de263e85fe715010e603a518eaf6286b7beb24ca84b97752485c423f0a"
"expectedUrl": "https://storage.googleapis.com/test-bucket/test-object?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=test-iam-credentials%40dummy-project-id.iam.gserviceaccount.com%2F20190201%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190201T090000Z&X-Goog-Expires=10&X-Goog-SignedHeaders=host%3Bmultiple&X-Goog-Signature=5cc113735625341f59c7203f0c2c9febc95ba6af6b9c38814f8e523214712087dc0996e4960d273ae1889f248ac1e58d4d19cb3a69ad7670e9a8ca1b434e878f59339dc7006cf32dfd715337e9f593e0504371839174962a08294586e0c78160a7aa303397888c8350637c6af3b32ac310886cc4590bfda9ca561ee58fb5b8ec56bc606d2ada6e7df31f4276e9dcb96bcaea39dc2cd096f3fad774f9c4b30e317ad43736c05f76831437f44e8726c1e90d3f6c9827dc273f211f32fc85658dfc5d357eb606743a6b00a29e519eef1bebaf9db3e8f4b1f5f9afb648ad06e60bc42fa8b57025056697c874c9ea76f5a73201c9717ea43e54713ff3502ff3fc626b"
},

// Headers associated with customer-supplied encryption keys should not be included in the signature
{
"description": "Customer-supplied encryption key",
"bucket": "test-bucket",
"object": "test-object",
"headers":
{
"X-Goog-Encryption-Key": [ "key" ],
"X-Goog-Encryption-Key-Sha256": [ "key-hash" ],
"X-Goog-Encryption-Algorithm": [ "AES256" ]
"X-Goog-Encryption-Key": "key",
"X-Goog-Encryption-Key-Sha256": "key-hash",
"X-Goog-Encryption-Algorithm": "AES256"
},
"method": "GET",
"expiration": 10,
Expand All @@ -135,6 +117,6 @@
"method": "GET",
"expiration": 10,
"timestamp": "20190201T090000Z",
"expectedUrl": "https://storage.googleapis.com/test-bucket/?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=test-iam-credentials%40dummy-project-id.iam.gserviceaccount.com%2F20190201%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190201T090000Z&X-Goog-Expires=10&X-Goog-SignedHeaders=host&X-Goog-Signature=2a1d342f11ddf0c90c669b9ba89ab5099f94049a86351cacbc85845fd5a8b31e1f9c8d484926c19fbd6930da6c8d3049ca8ebcfeefb7b02e53137755d36f97baab479414528b2802f10d94541facb888edf886d91ba124e60cb3801464f61aadc575fc921c99cf8c52e281f7bc0d3e740f529201c469c8e52775b6433687e0c0dca1c6b874614c3c3d09599be1e192c40ad6827416e387bf6e88a5f501f1d8225bce498d134599d0dfe30c9c833c244d3f90cf9595b9f8175658b788ee5c4a90b575fde5e83c645772250c7098373ca754b39d0fc1ebca2f50261a015931541c9827920eba67a1c41613853a1bd23299a1f9f5d583c0feb05ea2f792ba390d27"
"expectedUrl": "https://storage.googleapis.com/test-bucket?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=test-iam-credentials%40dummy-project-id.iam.gserviceaccount.com%2F20190201%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190201T090000Z&X-Goog-Expires=10&X-Goog-SignedHeaders=host&X-Goog-Signature=6dbe94f8e52b2b8a9a476b1c857efa474e09944e2b52b925800316e094a7169d8dbe0df9c0ac08dabb22ac7e827470ceccd65f5a3eadba2a4fb9beebfe37f0d9bb1e552b851fa31a25045bdf019e507f5feb44f061551ef1aeb18dcec0e38ba2e2f77d560a46eaace9c56ed9aa642281301a9d848b0eb30749e34bc7f73a3d596240533466ff9b5f289cd0d4c845c7d96b82a35a5abd0c3aff83e4440ee6873e796087f43545544dc8c01afe1d79c726696b6f555371e491980e7ec145cca0803cf562c38f3fa1d724242f5dea25aac91d74ec9ddd739ff65523627763eaef25cd1f95ad985aaf0079b7c74eb5bcb2870a9b137a7b2c8e41fbe838c95872f75b"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ def setup
credentials.signing_key = OpenSSL::PKey::RSA.new account["private_key"]
end

def headers_from_json headers
return nil if headers.nil? || headers.empty?
Hash[headers.map{ |k,v| [k, v.join(",")] } ]
end

def self.load_json rel_path
json_file = File.expand_path rel_path, __dir__
json_contents = File.read json_file
Expand All @@ -43,7 +38,7 @@ def self.build_test_for test, index
# method under test
signed_url = signer.signed_url method: test["method"],
expires: test["expiration"].to_i,
headers: headers_from_json(test["headers"])
headers: test["headers"]

signed_url.must_equal test["expectedUrl"]
end
Expand All @@ -54,6 +49,5 @@ def self.build_test_for test, index

tests = SignerV4Test.load_json "../../../../data/signer_v4_test_data.json"
tests.each_with_index do |test, index|
next if [6,8].include? index # TODO: Support multiple headers
SignerV4Test.build_test_for test, index
end

0 comments on commit 23e8f93

Please sign in to comment.