1 // Copyright 2019 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/examples/storage_examples_common.h"
17 #include "google/cloud/internal/getenv.h"
18 #include <iostream>
19
20 namespace {
21
GetServiceAccount(google::cloud::storage::Client client,std::vector<std::string> const &)22 void GetServiceAccount(google::cloud::storage::Client client,
23 std::vector<std::string> const&) {
24 //! [START storage_get_service_account] [get service account]
25 namespace gcs = google::cloud::storage;
26 using ::google::cloud::StatusOr;
27 [](gcs::Client client) {
28 StatusOr<gcs::ServiceAccount> account = client.GetServiceAccount();
29 if (!account) throw std::runtime_error(account.status().message());
30
31 std::cout << "The service account details are " << *account << "\n";
32 }
33 //! [END storage_get_service_account] [get service account]
34 (std::move(client));
35 }
36
GetServiceAccountForProject(google::cloud::storage::Client client,std::vector<std::string> const & argv)37 void GetServiceAccountForProject(google::cloud::storage::Client client,
38 std::vector<std::string> const& argv) {
39 //! [get service account for project]
40 namespace gcs = google::cloud::storage;
41 using ::google::cloud::StatusOr;
42 [](gcs::Client client, std::string const& project_id) {
43 StatusOr<gcs::ServiceAccount> account =
44 client.GetServiceAccountForProject(project_id);
45 if (!account) throw std::runtime_error(account.status().message());
46
47 std::cout << "The service account details for project " << project_id
48 << " are " << *account << "\n";
49 }
50 //! [get service account for project]
51 (std::move(client), argv.at(0));
52 }
53
ListHmacKeys(google::cloud::storage::Client client,std::vector<std::string> const &)54 void ListHmacKeys(google::cloud::storage::Client client,
55 std::vector<std::string> const&) {
56 //! [list hmac keys] [START storage_list_hmac_keys]
57 namespace gcs = google::cloud::storage;
58 using ::google::cloud::StatusOr;
59 [](gcs::Client client) {
60 int count = 0;
61 gcs::ListHmacKeysReader hmac_keys_list = client.ListHmacKeys();
62 for (auto const& key : hmac_keys_list) {
63 if (!key) throw std::runtime_error(key.status().message());
64
65 std::cout << "service_account_email = " << key->service_account_email()
66 << "\naccess_id = " << key->access_id() << "\n";
67 ++count;
68 }
69 if (count == 0) {
70 std::cout << "No HMAC keys in default project\n";
71 }
72 }
73 //! [list hmac keys] [END storage_list_hmac_keys]
74 (std::move(client));
75 }
76
ListHmacKeysWithServiceAccount(google::cloud::storage::Client client,std::vector<std::string> const & argv)77 void ListHmacKeysWithServiceAccount(google::cloud::storage::Client client,
78 std::vector<std::string> const& argv) {
79 //! [list hmac keys service account]
80 namespace gcs = google::cloud::storage;
81 using ::google::cloud::StatusOr;
82 [](gcs::Client client, std::string const& service_account) {
83 int count = 0;
84 gcs::ListHmacKeysReader hmac_keys_list =
85 client.ListHmacKeys(gcs::ServiceAccountFilter(service_account));
86 for (auto const& key : hmac_keys_list) {
87 if (!key) throw std::runtime_error(key.status().message());
88
89 std::cout << "service_account_email = " << key->service_account_email()
90 << "\naccess_id = " << key->access_id() << "\n";
91 ++count;
92 }
93 if (count == 0) {
94 std::cout << "No HMAC keys for service account " << service_account
95 << " in default project\n";
96 }
97 }
98 //! [list hmac keys service account]
99 (std::move(client), argv.at(0));
100 }
101
CreateHmacKey(google::cloud::storage::Client client,std::vector<std::string> const & argv)102 std::string CreateHmacKey(google::cloud::storage::Client client,
103 std::vector<std::string> const& argv) {
104 //! [create hmac key] [START storage_create_hmac_key]
105 namespace gcs = google::cloud::storage;
106 using ::google::cloud::StatusOr;
107 return [](gcs::Client client, std::string const& service_account_email) {
108 StatusOr<std::pair<gcs::HmacKeyMetadata, std::string>> key_info =
109 client.CreateHmacKey(service_account_email);
110 if (!key_info) throw std::runtime_error(key_info.status().message());
111
112 std::cout << "The base64 encoded secret is: " << key_info->second
113 << "\nDo not miss that secret, there is no API to recover it."
114 << "\nThe HMAC key metadata is: " << key_info->first << "\n";
115 return key_info->first.access_id();
116 }
117 //! [create hmac key] [END storage_create_hmac_key]
118 (std::move(client), argv.at(0));
119 }
120
CreateHmacKeyForProject(google::cloud::storage::Client client,std::vector<std::string> const & argv)121 std::string CreateHmacKeyForProject(google::cloud::storage::Client client,
122 std::vector<std::string> const& argv) {
123 //! [create hmac key project]
124 namespace gcs = google::cloud::storage;
125 using ::google::cloud::StatusOr;
126 return [](gcs::Client client, std::string const& project_id,
127 std::string const& service_account_email) {
128 StatusOr<std::pair<gcs::HmacKeyMetadata, std::string>> hmac_key_details =
129 client.CreateHmacKey(service_account_email,
130 gcs::OverrideDefaultProject(project_id));
131 if (!hmac_key_details) {
132 throw std::runtime_error(hmac_key_details.status().message());
133 }
134
135 std::cout << "The base64 encoded secret is: " << hmac_key_details->second
136 << "\nDo not miss that secret, there is no API to recover it."
137 << "\nThe HMAC key metadata is: " << hmac_key_details->first
138 << "\n";
139 return hmac_key_details->first.access_id();
140 }
141 //! [create hmac key project]
142 (std::move(client), argv.at(0), argv.at(1));
143 }
144
DeleteHmacKey(google::cloud::storage::Client client,std::vector<std::string> const & argv)145 void DeleteHmacKey(google::cloud::storage::Client client,
146 std::vector<std::string> const& argv) {
147 //! [delete hmac key] [START storage_delete_hmac_key]
148 namespace gcs = google::cloud::storage;
149 [](gcs::Client client, std::string const& access_id) {
150 google::cloud::Status status = client.DeleteHmacKey(access_id);
151 if (!status.ok()) throw std::runtime_error(status.message());
152
153 std::cout << "The key is deleted, though it may still appear"
154 << " in ListHmacKeys() results.\n";
155 }
156 //! [delete hmac key] [END storage_delete_hmac_key]
157 (std::move(client), argv.at(0));
158 }
159
GetHmacKey(google::cloud::storage::Client client,std::vector<std::string> const & argv)160 void GetHmacKey(google::cloud::storage::Client client,
161 std::vector<std::string> const& argv) {
162 //! [get hmac key] [START storage_get_hmac_key]
163 namespace gcs = google::cloud::storage;
164 using ::google::cloud::StatusOr;
165 [](gcs::Client client, std::string const& access_id) {
166 StatusOr<gcs::HmacKeyMetadata> hmac_key = client.GetHmacKey(access_id);
167 if (!hmac_key) throw std::runtime_error(hmac_key.status().message());
168
169 std::cout << "The HMAC key metadata is: " << *hmac_key << "\n";
170 }
171 //! [get hmac key] [END storage_get_hmac_key]
172 (std::move(client), argv.at(0));
173 }
174
UpdateHmacKey(google::cloud::storage::Client client,std::vector<std::string> const & argv)175 void UpdateHmacKey(google::cloud::storage::Client client,
176 std::vector<std::string> const& argv) {
177 //! [update hmac key]
178 namespace gcs = google::cloud::storage;
179 using ::google::cloud::StatusOr;
180 [](gcs::Client client, std::string const& access_id,
181 std::string const& state) {
182 StatusOr<gcs::HmacKeyMetadata> updated = client.UpdateHmacKey(
183 access_id, gcs::HmacKeyMetadata().set_state(std::move(state)));
184 if (!updated) throw std::runtime_error(updated.status().message());
185
186 std::cout << "The updated HMAC key metadata is: " << *updated << "\n";
187 }
188 //! [update hmac key]
189 (std::move(client), argv.at(0), argv.at(1));
190 }
191
ActivateHmacKey(google::cloud::storage::Client client,std::vector<std::string> const & argv)192 void ActivateHmacKey(google::cloud::storage::Client client,
193 std::vector<std::string> const& argv) {
194 //! [START storage_activate_hmac_key]
195 namespace gcs = google::cloud::storage;
196 using ::google::cloud::StatusOr;
197 [](gcs::Client client, std::string const& access_id) {
198 StatusOr<gcs::HmacKeyMetadata> updated = client.UpdateHmacKey(
199 access_id,
200 gcs::HmacKeyMetadata().set_state(gcs::HmacKeyMetadata::state_active()));
201 if (!updated) throw std::runtime_error(updated.status().message());
202
203 if (updated->state() != gcs::HmacKeyMetadata::state_active()) {
204 throw std::runtime_error(
205 "The HMAC key is NOT active, this is unexpected");
206 }
207 std::cout << "The HMAC key is now active\nFull metadata: " << *updated
208 << "\n";
209 }
210 //! [END storage_activate_hmac_key]
211 (std::move(client), argv.at(0));
212 }
213
DeactivateHmacKey(google::cloud::storage::Client client,std::vector<std::string> const & argv)214 void DeactivateHmacKey(google::cloud::storage::Client client,
215 std::vector<std::string> const& argv) {
216 //! [START storage_deactivate_hmac_key]
217 namespace gcs = google::cloud::storage;
218 using ::google::cloud::StatusOr;
219 [](gcs::Client client, std::string const& access_id) {
220 StatusOr<gcs::HmacKeyMetadata> updated = client.UpdateHmacKey(
221 access_id, gcs::HmacKeyMetadata().set_state(
222 gcs::HmacKeyMetadata::state_inactive()));
223 if (!updated) throw std::runtime_error(updated.status().message());
224
225 if (updated->state() != gcs::HmacKeyMetadata::state_inactive()) {
226 throw std::runtime_error("The HMAC key is active, this is unexpected");
227 }
228 std::cout << "The HMAC key is now inactive\nFull metadata: " << *updated
229 << "\n";
230 }
231 //! [END storage_deactivate_hmac_key]
232 (std::move(client), argv.at(0));
233 }
234
RunAll(std::vector<std::string> const & argv)235 void RunAll(std::vector<std::string> const& argv) {
236 namespace examples = ::google::cloud::storage::examples;
237 namespace gcs = ::google::cloud::storage;
238
239 if (!argv.empty()) throw examples::Usage{"auto"};
240 examples::CheckEnvironmentVariablesAreSet({
241 "GOOGLE_CLOUD_PROJECT",
242 "GOOGLE_CLOUD_CPP_STORAGE_TEST_HMAC_SERVICE_ACCOUNT",
243 });
244 auto const project_id =
245 google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value();
246 auto const service_account =
247 google::cloud::internal::GetEnv(
248 "GOOGLE_CLOUD_CPP_STORAGE_TEST_HMAC_SERVICE_ACCOUNT")
249 .value();
250 auto client = gcs::Client::CreateDefaultClient().value();
251
252 std::cout << "\nRunning GetServiceAccountForProject() example" << std::endl;
253 GetServiceAccountForProject(client, {project_id});
254
255 std::cout << "\nRunning GetServiceAccount() example" << std::endl;
256 GetServiceAccount(client, {});
257
258 std::cout << "\nRunning ListHmacKeys() example [1]" << std::endl;
259 ListHmacKeys(client, {});
260
261 std::cout << "\nRunning ListHmacKeysWithServiceAccount() example [1]"
262 << std::endl;
263 ListHmacKeysWithServiceAccount(client, {service_account});
264
265 auto const key_info =
266 client
267 .CreateHmacKey(service_account,
268 gcs::OverrideDefaultProject(project_id))
269 .value();
270
271 std::cout << "\nRunning CreateHmacKey() example" << std::endl;
272 auto const hmac_access_id = CreateHmacKey(client, {service_account});
273
274 std::cout << "\nRunning CreateHmacKeyForProject() example" << std::endl;
275 auto const project_hmac_access_id =
276 CreateHmacKeyForProject(client, {project_id, service_account});
277
278 std::cout << "\nRunning ListHmacKeys() example [2]" << std::endl;
279 ListHmacKeys(client, {});
280
281 std::cout << "\nRunning ListHmacKeysWithServiceAccount() example [2]"
282 << std::endl;
283 ListHmacKeysWithServiceAccount(client, {service_account});
284
285 std::cout << "\nRunning GetHmacKey() example" << std::endl;
286 GetHmacKey(client, {key_info.first.access_id()});
287
288 std::cout << "\nRunning UpdateHmacKey() example" << std::endl;
289 UpdateHmacKey(client, {key_info.first.access_id(), "INACTIVE"});
290
291 std::cout << "\nRunning ActivateHmacKey() example" << std::endl;
292 ActivateHmacKey(client, {key_info.first.access_id()});
293
294 std::cout << "\nRunning DeactivateHmacKey() example" << std::endl;
295 DeactivateHmacKey(client, {key_info.first.access_id()});
296
297 std::cout << "\nRunning DeleteHmacKey() example" << std::endl;
298 DeleteHmacKey(client, {key_info.first.access_id()});
299
300 for (auto const& access_id : {project_hmac_access_id, hmac_access_id}) {
301 (void)client.UpdateHmacKey(access_id,
302 gcs::HmacKeyMetadata().set_state(
303 gcs::HmacKeyMetadata::state_inactive()));
304 (void)client.DeleteHmacKey(access_id);
305 }
306 }
307
308 } // anonymous namespace
309
main(int argc,char * argv[])310 int main(int argc, char* argv[]) {
311 namespace examples = ::google::cloud::storage::examples;
312 examples::Example example({
313 examples::CreateCommandEntry("get-service-account", {},
314 GetServiceAccount),
315 examples::CreateCommandEntry("get-service-account-for-project",
316 {"<project-id>"},
317 GetServiceAccountForProject),
318 examples::CreateCommandEntry("list-hmac-keys", {}, ListHmacKeys),
319 examples::CreateCommandEntry("list-hmac-keys-with-service-account",
320 {"<service-account>"},
321 ListHmacKeysWithServiceAccount),
322 examples::CreateCommandEntry("create-hmac-key",
323 {"<service-account-email>"}, CreateHmacKey),
324 examples::CreateCommandEntry("create-hmac-key-for-project",
325 {"<project-id>", "<service-account-email>"},
326 CreateHmacKeyForProject),
327 examples::CreateCommandEntry("delete-hmac-key", {"<access-id>"},
328 DeleteHmacKey),
329 examples::CreateCommandEntry("get-hmac-key", {"<access-id>"}, GetHmacKey),
330 examples::CreateCommandEntry("update-hmac-key",
331 {"<access-id>", "<state>"}, UpdateHmacKey),
332 examples::CreateCommandEntry("activate-hmac-key", {"<access-id>"},
333 ActivateHmacKey),
334 examples::CreateCommandEntry("deactivate-hmac-key", {"<access-id>"},
335 DeactivateHmacKey),
336 {"auto", RunAll},
337 });
338 return example.Run(argc, argv);
339 }
340