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