diff --git a/google/cloud/storage/tests/CMakeLists.txt b/google/cloud/storage/tests/CMakeLists.txt index b57ffe7e381fe..73fd7e85d00bc 100644 --- a/google/cloud/storage/tests/CMakeLists.txt +++ b/google/cloud/storage/tests/CMakeLists.txt @@ -16,6 +16,7 @@ set(storage_client_integration_tests bucket_integration_test.cc + client_sign_url_integration_test.cc curl_upload_request_integration_test.cc curl_download_request_integration_test.cc curl_request_integration_test.cc diff --git a/google/cloud/storage/tests/UrlSignerV4TestAccount.json b/google/cloud/storage/tests/UrlSignerV4TestAccount.json new file mode 100644 index 0000000000000..a8a93b8aab460 --- /dev/null +++ b/google/cloud/storage/tests/UrlSignerV4TestAccount.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "dummy-project-id", + "private_key_id": "ffffffffffffffffffffffffffffffffffffffff", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCsPzMirIottfQ2\nryjQmPWocSEeGo7f7Q4/tMQXHlXFzo93AGgU2t+clEj9L5loNhLVq+vk+qmnyDz5\nQ04y8jVWyMYzzGNNrGRW/yaYqnqlKZCy1O3bmnNjV7EDbC/jE1ZLBY0U3HaSHfn6\nS9ND8MXdgD0/ulRTWwq6vU8/w6i5tYsU7n2LLlQTl1fQ7/emO9nYcCFJezHZVa0H\nmeWsdHwWsok0skwQYQNIzP3JF9BpR5gJT2gNge6KopDesJeLoLzaX7cUnDn+CAnn\nLuLDwwSsIVKyVxhBFsFXPplgpaQRwmGzwEbf/Xpt9qo26w2UMgn30jsOaKlSeAX8\ncS6ViF+tAgMBAAECggEACKRuJCP8leEOhQziUx8Nmls8wmYqO4WJJLyk5xUMUC22\nSI4CauN1e0V8aQmxnIc0CDkFT7qc9xBmsMoF+yvobbeKrFApvlyzNyM7tEa/exh8\nDGD/IzjbZ8VfWhDcUTwn5QE9DCoon9m1sG+MBNlokB3OVOt8LieAAREdEBG43kJu\nyQTOkY9BGR2AY1FnAl2VZ/jhNDyrme3tp1sW1BJrawzR7Ujo8DzlVcS2geKA9at7\n55ua5GbHz3hfzFgjVXDfnkWzId6aHypUyqHrSn1SqGEbyXTaleKTc6Pgv0PgkJjG\nhZazWWdSuf1T5Xbs0OhAK9qraoAzT6cXXvMEvvPt6QKBgQDXcZKqJAOnGEU4b9+v\nOdoh+nssdrIOBNMu1m8mYbUVYS1aakc1iDGIIWNM3qAwbG+yNEIi2xi80a2RMw2T\n9RyCNB7yqCXXVKLBiwg9FbKMai6Vpk2bWIrzahM9on7AhCax/X2AeOp+UyYhFEy6\nUFG4aHb8THscL7b515ukSuKb5QKBgQDMq+9PuaB0eHsrmL6q4vHNi3MLgijGg/zu\nAXaPygSYAwYW8KglcuLZPvWrL6OG0+CrfmaWTLsyIZO4Uhdj7MLvX6yK7IMnagvk\nL3xjgxSklEHJAwi5wFeJ8ai/1MIuCn8p2re3CbwISKpvf7Sgs/W4196P4vKvTiAz\njcTiSYFIKQKBgCjMpkS4O0TakMlGTmsFnqyOneLmu4NyIHgfPb9cA4n/9DHKLKAT\noaWxBPgatOVWs7RgtyGYsk+XubHkpC6f3X0+15mGhFwJ+CSE6tN+l2iF9zp52vqP\nQwkjzm7+pdhZbmaIpcq9m1K+9lqPWJRz/3XXuqi+5xWIZ7NaxGvRjqaNAoGAdK2b\nutZ2y48XoI3uPFsuP+A8kJX+CtWZrlE1NtmS7tnicdd19AtfmTuUL6fz0FwfW4Su\nlQZfPT/5B339CaEiq/Xd1kDor+J7rvUHM2+5p+1A54gMRGCLRv92FQ4EON0RC1o9\nm2I4SHysdO3XmjmdXmfp4BsgAKJIJzutvtbqlakCgYB+Cb10z37NJJ+WgjDt+yT2\nyUNH17EAYgWXryfRgTyi2POHuJitd64Xzuy6oBVs3wVveYFM6PIKXlj8/DahYX5I\nR2WIzoCNLL3bEZ+nC6Jofpb4kspoAeRporj29SgesK6QBYWHWX2H645RkRGYGpDo\n51gjy9m/hSNqBbH2zmh04A==\n-----END PRIVATE KEY-----\n", + "client_email": "test-iam-credentials@dummy-project-id.iam.gserviceaccount.com", + "client_id": "000000000000000000000", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/test-iam-credentials%40dummy-project-id.iam.gserviceaccount.com" +} diff --git a/google/cloud/storage/tests/UrlSignerV4TestData.json b/google/cloud/storage/tests/UrlSignerV4TestData.json new file mode 100644 index 0000000000000..6e8037040d4f9 --- /dev/null +++ b/google/cloud/storage/tests/UrlSignerV4TestData.json @@ -0,0 +1,122 @@ +[ + { + "description": "Simple GET", + "bucket": "test-bucket", + "object": "test-object", + "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=host&X-Goog-Signature=95e6a13d43a1d1962e667f17397f2b80ac9bdd1669210d5e08e0135df9dff4e56113485dbe429ca2266487b9d1796ebdee2d7cf682a6ef3bb9fbb4c351686fba90d7b621cf1c4eb1fdf126460dd25fa0837dfdde0a9fd98662ce60844c458448fb2b352c203d9969cb74efa4bdb742287744a4f2308afa4af0e0773f55e32e92973619249214b97283b2daa14195244444e33f938138d1e5f561088ce8011f4986dda33a556412594db7c12fc40e1ff3f1bedeb7a42f5bcda0b9567f17f65855f65071fabb88ea12371877f3f77f10e1466fff6ff6973b74a933322ff0949ce357e20abe96c3dd5cfab42c9c83e740a4d32b9e11e146f0eb3404d2e975896f74" + }, + + { + "description": "Simple PUT", + "bucket": "test-bucket", + "object": "test-object", + "method": "PUT", + "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=host&X-Goog-Signature=8adff1d4285739e31aa68e73767a46bc5511fde377497dbe08481bf5ceb34e29cc9a59921748d8ec3dd4085b7e9b7772a952afedfcdaecb3ae8352275b8b7c867f204e3db85076220a3127a8a9589302fc1181eae13b9b7fe41109ec8cdc93c1e8bac2d7a0cc32a109ca02d06957211326563ab3d3e678a0ba296e298b5fc5e14593c99d444c94724cc4be97015dbff1dca377b508fa0cb7169195de98d0e4ac96c42b918d28c8d92d33e1bd125ce0fb3cd7ad2c45dae65c22628378f6584971b8bf3945b26f2611eb651e9b6a8648970c1ecf386bb71327b082e7296c4e1ee2fc0bdd8983da80af375c817fb1ad491d0bc22c0f51dba0d66e2cffbc90803e47" + }, + + { + "description": "POST for resumable uploads", + "bucket": "test-bucket", + "object": "test-object", + "method": "POST", + "expiration": 10, + "headers": { + "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" + }, + + { + "description": "Vary expiration and timestamp", + "bucket": "test-bucket", + "object": "test-object", + "method": "GET", + "expiration": 20, + "timestamp": "20190301T090000Z", + "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%2F20190301%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20190301T090000Z&X-Goog-Expires=20&X-Goog-SignedHeaders=host&X-Goog-Signature=9669ed5b10664dc594c758296580662912cf4bcc5a4ba0b6bf055bcbf6f34eed7bdad664f534962174a924741a0c273a4f67bc1847cef20192a6beab44223bd9d4fbbd749c407b79997598c30f82ddc269ff47ec09fa3afe74e00616d438df0d96a7d8ad0adacfad1dc3286f864d924fe919fb0dce45d3d975c5afe8e13af2db9cc37ba77835f92f7669b61e94c6d562196c1274529e76cfff1564cc2cad7d5387dc8e12f7a5dfd925685fe92c30b43709eee29fa2f66067472cee5423d1a3a4182fe8cea75c9329d181dc6acad7c393cd04f8bf5bc0515127d8ebd65d80c08e19ad03316053ea60033fd1b1fd85a69c576415da3bf0a3718d9ea6d03e0d66f0" + }, + + { + "description": "Vary bucket and object", + "bucket": "test-bucket2", + "object": "test-object2", + "method": "GET", + "expiration": 10, + "timestamp": "20190201T090000Z", + "expectedUrl": "https://storage.googleapis.com/test-bucket2/test-object2?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=36e3d58dfd3ec1d2dd2f24b5ee372a71e811ffaa2162a2b871d26728d0354270bc116face87127532969c4a3967ed05b7309af741e19c7202f3167aa8c2ac420b61417d6451442bb91d7c822cd17be8783f01e05372769c88913561d27e6660dd8259f0081a71f831be6c50283626cbf04494ac10c394b29bb3bce74ab91548f58a37118a452693cf0483d77561fc9cac8f1765d2c724994cca46a83517a10157ee0347a233a2aaeae6e6ab5e204ff8fc5f54f90a3efdb8301d9fff5475d58cd05b181affd657f48203f4fb133c3a3d355b8eefbd10d5a0a5fd70d06e9515460ad74e22334b2cba4b29cae4f6f285cdb92d8f3126d7a1479ca3bdb69c207d860" + }, + + { + "description": "Simple headers", + "bucket": "test-bucket", + "object": "test-object", + "headers": { + "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" + }, + + { + "description": "Headers should be trimmed", + "bucket": "test-bucket", + "object": "test-object", + "headers": { + "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" + }, + + { + "description": "Header value with multiple inline values", + "bucket": "test-bucket", + "object": "test-object", + "headers": { + "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=host%3Bmultiple&X-Goog-Signature=5cc113735625341f59c7203f0c2c9febc95ba6af6b9c38814f8e523214712087dc0996e4960d273ae1889f248ac1e58d4d19cb3a69ad7670e9a8ca1b434e878f59339dc7006cf32dfd715337e9f593e0504371839174962a08294586e0c78160a7aa303397888c8350637c6af3b32ac310886cc4590bfda9ca561ee58fb5b8ec56bc606d2ada6e7df31f4276e9dcb96bcaea39dc2cd096f3fad774f9c4b30e317ad43736c05f76831437f44e8726c1e90d3f6c9827dc273f211f32fc85658dfc5d357eb606743a6b00a29e519eef1bebaf9db3e8f4b1f5f9afb648ad06e60bc42fa8b57025056697c874c9ea76f5a73201c9717ea43e54713ff3502ff3fc626b" + }, + + { + "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" + }, + "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=host%3Bx-goog-encryption-algorithm%3Bx-goog-encryption-key%3Bx-goog-encryption-key-sha256&X-Goog-Signature=278a1c5a3bad248637054a047014760353942433955871031ed08f515b54588654ad033e91f046ab202b68673030e117d1b786c325e870238b035ba75b3feed560a17aff9bab6bddebd4a31a52cb68b214e27d3b0bd886502c6b36b164306fe88b5a07c6063592afe746b2a5d205dbe90dd5386b94f0a78f75d9f53ee884e18f476e8fc2eb1dd910ce0b4ae1f5d7b09876ef9bf983f539c028429e14bad3c75dbd4ed1ae37856f6d6f8a1805eaf8b52a0d6fc993902e4c1ee8de477661f7b67c3663000474cb00e178189789b2a3ed6bd21b4ade684fca8108ac4dd106acb17f5954d045775f7aa5a98ebda5d3075e11a8ea49c64c6ad1481e463e8c9f11f704" + }, + + { + "description": "List Objects", + "bucket": "test-bucket", + "object": "", + "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=6dbe94f8e52b2b8a9a476b1c857efa474e09944e2b52b925800316e094a7169d8dbe0df9c0ac08dabb22ac7e827470ceccd65f5a3eadba2a4fb9beebfe37f0d9bb1e552b851fa31a25045bdf019e507f5feb44f061551ef1aeb18dcec0e38ba2e2f77d560a46eaace9c56ed9aa642281301a9d848b0eb30749e34bc7f73a3d596240533466ff9b5f289cd0d4c845c7d96b82a35a5abd0c3aff83e4440ee6873e796087f43545544dc8c01afe1d79c726696b6f555371e491980e7ec145cca0803cf562c38f3fa1d724242f5dea25aac91d74ec9ddd739ff65523627763eaef25cd1f95ad985aaf0079b7c74eb5bcb2870a9b137a7b2c8e41fbe838c95872f75b" + } +] diff --git a/google/cloud/storage/tests/client_sign_url_integration_test.cc b/google/cloud/storage/tests/client_sign_url_integration_test.cc new file mode 100644 index 0000000000000..d15596ed7f148 --- /dev/null +++ b/google/cloud/storage/tests/client_sign_url_integration_test.cc @@ -0,0 +1,155 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "google/cloud/storage/client.h" +#include "google/cloud/storage/internal/nljson.h" +#include "google/cloud/storage/list_objects_reader.h" +#include "google/cloud/storage/testing/storage_integration_test.h" +#include "google/cloud/testing_util/assert_ok.h" +#include "google/cloud/testing_util/init_google_mock.h" +#include +#include + +namespace nl = google::cloud::storage::internal::nl; +namespace google { +namespace cloud { +namespace storage { +inline namespace STORAGE_CLIENT_NS { +namespace { +using ::testing::HasSubstr; + +// Initialized in main() below. +char const* account_file_name_; +char const* data_file_name_; + +class ObjectIntegrationTest + : public google::cloud::storage::testing::StorageIntegrationTest { + protected: + // Converts ""20190201T090000Z", + // to "2019-02-01T09:00:00Z" + std::string TimestampToRfc3339(std::string ts) { + if (ts.size() != 16) { + return ""; + } + return ts.substr(0, 4) + '-' + ts.substr(4, 2) + '-' + ts.substr(6, 2) + + 'T' + ts.substr(9, 2) + ':' + ts.substr(11, 2) + ':' + + ts.substr(13, 2) + 'Z'; + } + + std::vector> ExtractHeaders( + nl::json j_obj) { + std::vector> headers; + + // Check for the keys of the headers field + for (auto& x : j_obj["headers"].items()) { + // The keys are returned in alphabetical order by nlohmann::json, but + // the order does not matter when creating signed urls. + headers.emplace_back(x.key(), x.value()); + } + return headers; + } +}; + +TEST_F(ObjectIntegrationTest, V4SignJson) { + // This is a dummy service account JSON file that is inactive. It's fine for + // it to be public. + std::string account_file = account_file_name_; + std::string data_file = data_file_name_; + + std::ifstream ifstr(data_file); + ASSERT_TRUE(ifstr.is_open()); + + nl::json json_array = nl::json::parse(ifstr); + auto creds = + oauth2::CreateServiceAccountCredentialsFromJsonFilePath(account_file); + + ASSERT_STATUS_OK(creds); + Client client(*creds); + StatusOr actual; + + for (auto const& j_obj : json_array) { + std::string const method_name = j_obj["method"]; + std::string const bucket_name = j_obj["bucket"]; + std::string const object_name = j_obj["object"]; + std::string const date = TimestampToRfc3339(j_obj["timestamp"]); + auto const valid_for = std::chrono::seconds(j_obj["expiration"]); + std::string const expected = j_obj["expectedUrl"]; + + // Extract the headers for each object + std::vector> headers = + ExtractHeaders(j_obj); + + if (headers.size() == 0) { + actual = client.CreateV4SignedUrl( + method_name, bucket_name, object_name, + SignedUrlTimestamp(internal::ParseRfc3339(date)), + SignedUrlDuration(valid_for), + AddExtensionHeader("host", "storage.googleapis.com")); + } else if (headers.size() == 1) { + actual = client.CreateV4SignedUrl( + method_name, bucket_name, object_name, + SignedUrlTimestamp(internal::ParseRfc3339(date)), + SignedUrlDuration(valid_for), + AddExtensionHeader("host", "storage.googleapis.com"), + AddExtensionHeader(headers.at(0).first, headers.at(0).second)); + } else if (headers.size() == 2) { + actual = client.CreateV4SignedUrl( + method_name, bucket_name, object_name, + SignedUrlTimestamp(internal::ParseRfc3339(date)), + SignedUrlDuration(valid_for), + AddExtensionHeader("host", "storage.googleapis.com"), + AddExtensionHeader(headers.at(0).first, headers.at(0).second), + AddExtensionHeader(headers.at(1).first, headers.at(1).second)); + } else if (headers.size() == 3) { + actual = client.CreateV4SignedUrl( + method_name, bucket_name, object_name, + SignedUrlTimestamp(internal::ParseRfc3339(date)), + SignedUrlDuration(valid_for), + AddExtensionHeader("host", "storage.googleapis.com"), + AddExtensionHeader(headers.at(0).first, headers.at(0).second), + AddExtensionHeader(headers.at(1).first, headers.at(1).second), + AddExtensionHeader(headers.at(2).first, headers.at(2).second)); + } else { + EXPECT_LT(headers.size(), 4); + } + ASSERT_STATUS_OK(actual); + EXPECT_THAT(*actual, HasSubstr(bucket_name)); + EXPECT_THAT(*actual, HasSubstr(object_name)); + EXPECT_EQ(expected, *actual); + } +} + +} // namespace +} // namespace STORAGE_CLIENT_NS +} // namespace storage +} // namespace cloud +} // namespace google + +int main(int argc, char* argv[]) { + google::cloud::testing_util::InitGoogleMock(argc, argv); + + // Make sure the arguments are valid. + if (argc != 3) { + std::string const cmd = argv[0]; + auto last_slash = std::string(argv[0]).find_last_of('/'); + std::cerr << "Usage: " << cmd.substr(last_slash + 1) + << " \n"; + return 1; + } + + google::cloud::storage::account_file_name_ = argv[1]; + google::cloud::storage::data_file_name_ = argv[2]; + + return RUN_ALL_TESTS(); +} diff --git a/google/cloud/storage/tests/run_integration_tests_testbench.sh b/google/cloud/storage/tests/run_integration_tests_testbench.sh index 8074c4ecb5bc4..bc0d7e7bc56ca 100755 --- a/google/cloud/storage/tests/run_integration_tests_testbench.sh +++ b/google/cloud/storage/tests/run_integration_tests_testbench.sh @@ -30,6 +30,10 @@ export TOPIC_NAME="projects/${PROJECT_ID}/topics/fake-topic-${RANDOM}-${RANDOM}" export LOCATION="fake-region1" readonly SERVICE_ACCOUNT="fake-service-account@example.com" + +readonly TEST_ACCOUNT_FILE="${PROJECT_ROOT}/google/cloud/storage/tests/UrlSignerV4TestAccount.json" +readonly TEST_DATA_FILE="${PROJECT_ROOT}/google/cloud/storage/tests/UrlSignerV4TestData.json" + echo echo "Running Storage integration tests against local servers." start_testbench @@ -94,6 +98,10 @@ echo echo "Running GCS Projects.serviceAccount integration tests." ./service_account_integration_test "${PROJECT_ID}" "${SERVICE_ACCOUNT}" +echo +echo "Running storage::internal::ClientSignUrl integration test." +./client_sign_url_integration_test "${TEST_ACCOUNT_FILE}" "${TEST_DATA_FILE}" + # The tests were successful, so disable dumping of test bench log during # shutdown. TESTBENCH_DUMP_LOG=no diff --git a/google/cloud/storage/tests/storage_client_integration_tests.bzl b/google/cloud/storage/tests/storage_client_integration_tests.bzl index 9904aced4b2b6..2848123d5171c 100644 --- a/google/cloud/storage/tests/storage_client_integration_tests.bzl +++ b/google/cloud/storage/tests/storage_client_integration_tests.bzl @@ -18,6 +18,7 @@ storage_client_integration_tests = [ "bucket_integration_test.cc", + "client_sign_url_integration_test.cc", "curl_upload_request_integration_test.cc", "curl_download_request_integration_test.cc", "curl_request_integration_test.cc",