1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "google/cloud/storage/client.h"
16 #include "google/cloud/storage/testing/storage_integration_test.h"
17 #include "google/cloud/internal/getenv.h"
18 #include "google/cloud/testing_util/assert_ok.h"
19 #include <gmock/gmock.h>
20
21 namespace google {
22 namespace cloud {
23 namespace storage {
24 inline namespace STORAGE_CLIENT_NS {
25 namespace {
26
27 class ServiceAccountIntegrationTest
28 : public google::cloud::storage::testing::StorageIntegrationTest {
29 protected:
SetUp()30 void SetUp() override {
31 project_id_ =
32 google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value_or("");
33 ASSERT_FALSE(project_id_.empty());
34 service_account_ = google::cloud::internal::GetEnv(
35 "GOOGLE_CLOUD_CPP_STORAGE_TEST_HMAC_SERVICE_ACCOUNT")
36 .value_or("");
37 ASSERT_FALSE(service_account_.empty());
38 }
39
40 std::string project_id_;
41 std::string service_account_;
42 };
43
TEST_F(ServiceAccountIntegrationTest,Get)44 TEST_F(ServiceAccountIntegrationTest, Get) {
45 StatusOr<Client> client = MakeIntegrationTestClient();
46 ASSERT_STATUS_OK(client);
47
48 StatusOr<ServiceAccount> a1 =
49 client->GetServiceAccountForProject(project_id_);
50 ASSERT_STATUS_OK(a1);
51 EXPECT_FALSE(a1->email_address().empty());
52
53 auto client_options = ClientOptions::CreateDefaultClientOptions();
54 ASSERT_STATUS_OK(client_options);
55 Client client_with_default(client_options->set_project_id(project_id_));
56 StatusOr<ServiceAccount> a2 = client_with_default.GetServiceAccount();
57 ASSERT_STATUS_OK(a2);
58 EXPECT_FALSE(a2->email_address().empty());
59
60 EXPECT_EQ(*a1, *a2);
61 }
62
TEST_F(ServiceAccountIntegrationTest,CreateHmacKeyForProject)63 TEST_F(ServiceAccountIntegrationTest, CreateHmacKeyForProject) {
64 auto client_options = ClientOptions::CreateDefaultClientOptions();
65 ASSERT_STATUS_OK(client_options);
66
67 Client client(client_options->set_project_id(project_id_));
68
69 StatusOr<std::pair<HmacKeyMetadata, std::string>> key = client.CreateHmacKey(
70 service_account_, OverrideDefaultProject(project_id_));
71 ASSERT_STATUS_OK(key);
72
73 EXPECT_FALSE(key->second.empty());
74
75 StatusOr<HmacKeyMetadata> update_details = client.UpdateHmacKey(
76 key->first.access_id(), HmacKeyMetadata().set_state("INACTIVE"));
77 ASSERT_STATUS_OK(update_details);
78 EXPECT_EQ("INACTIVE", update_details->state());
79
80 Status deleted_key = client.DeleteHmacKey(key->first.access_id());
81 ASSERT_STATUS_OK(deleted_key);
82 }
83
TEST_F(ServiceAccountIntegrationTest,HmacKeyCRUD)84 TEST_F(ServiceAccountIntegrationTest, HmacKeyCRUD) {
85 auto client_options = ClientOptions::CreateDefaultClientOptions();
86 ASSERT_STATUS_OK(client_options);
87
88 Client client(client_options->set_project_id(project_id_));
89
90 auto get_current_access_ids = [&client, this]() {
91 std::vector<std::string> access_ids;
92 auto range = client.ListHmacKeys(OverrideDefaultProject(project_id_),
93 ServiceAccountFilter(service_account_));
94 std::transform(
95 range.begin(), range.end(), std::back_inserter(access_ids),
96 [](StatusOr<HmacKeyMetadata> x) { return x.value().access_id(); });
97 return access_ids;
98 };
99
100 auto initial_access_ids = get_current_access_ids();
101
102 StatusOr<std::pair<HmacKeyMetadata, std::string>> key =
103 client.CreateHmacKey(service_account_);
104 ASSERT_STATUS_OK(key);
105
106 EXPECT_FALSE(key->second.empty());
107 auto access_id = key->first.access_id();
108
109 using ::testing::Contains;
110 using ::testing::Not;
111 EXPECT_THAT(initial_access_ids, Not(Contains(access_id)));
112
113 auto post_create_access_ids = get_current_access_ids();
114 EXPECT_THAT(post_create_access_ids, Contains(access_id));
115
116 StatusOr<HmacKeyMetadata> get_details = client.GetHmacKey(access_id);
117 ASSERT_STATUS_OK(get_details);
118
119 EXPECT_EQ(access_id, get_details->access_id());
120 HmacKeyMetadata original = key->first;
121 // TODO(#3806) - remove this workaround: the etag may have changed since the
122 // key was created.
123 original.set_etag(get_details->etag());
124 EXPECT_EQ(original, *get_details);
125
126 StatusOr<HmacKeyMetadata> update_details =
127 client.UpdateHmacKey(access_id, HmacKeyMetadata().set_state("INACTIVE"));
128 ASSERT_STATUS_OK(update_details);
129 EXPECT_EQ("INACTIVE", update_details->state());
130
131 Status deleted_key = client.DeleteHmacKey(key->first.access_id());
132 ASSERT_STATUS_OK(deleted_key);
133
134 auto post_delete_access_ids = get_current_access_ids();
135 EXPECT_THAT(post_delete_access_ids, Not(Contains(access_id)));
136 }
137
TEST_F(ServiceAccountIntegrationTest,HmacKeyCRUDFailures)138 TEST_F(ServiceAccountIntegrationTest, HmacKeyCRUDFailures) {
139 auto client_options = ClientOptions::CreateDefaultClientOptions();
140 ASSERT_STATUS_OK(client_options);
141
142 Client client(client_options->set_project_id(project_id_));
143
144 // Test failures in the HmacKey operations by using an invalid project id:
145 auto create_status = client.CreateHmacKey("invalid-service-account",
146 OverrideDefaultProject(""));
147 EXPECT_FALSE(create_status) << "value=" << create_status->first;
148
149 Status deleted_status =
150 client.DeleteHmacKey("invalid-access-id", OverrideDefaultProject(""));
151 EXPECT_FALSE(deleted_status.ok());
152
153 StatusOr<HmacKeyMetadata> get_status =
154 client.GetHmacKey("invalid-access-id", OverrideDefaultProject(""));
155 EXPECT_FALSE(get_status) << "value=" << *get_status;
156
157 StatusOr<HmacKeyMetadata> update_status = client.UpdateHmacKey(
158 "invalid-access-id", HmacKeyMetadata(), OverrideDefaultProject(""));
159 EXPECT_FALSE(update_status) << "value=" << *update_status;
160
161 auto range = client.ListHmacKeys(OverrideDefaultProject(""));
162 auto begin = range.begin();
163 EXPECT_NE(begin, range.end());
164 EXPECT_FALSE(*begin) << "value=" << **begin;
165 }
166
167 } // namespace
168 } // namespace STORAGE_CLIENT_NS
169 } // namespace storage
170 } // namespace cloud
171 } // namespace google
172