1 //
2 // Copyright (C) 2019 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "credential_source.h"
17 
18 #include <android-base/logging.h>
19 
20 namespace cuttlefish {
21 namespace {
22 
23 std::chrono::steady_clock::duration REFRESH_WINDOW =
24     std::chrono::minutes(2);
25 std::string REFRESH_URL = "http://metadata.google.internal/computeMetadata/"
26     "v1/instance/service-accounts/default/token";
27 
28 } // namespace
29 
GceMetadataCredentialSource()30 GceMetadataCredentialSource::GceMetadataCredentialSource() {
31   latest_credential = "";
32   expiration = std::chrono::steady_clock::now();
33 }
34 
Credential()35 std::string GceMetadataCredentialSource::Credential() {
36   if (expiration - std::chrono::steady_clock::now() < REFRESH_WINDOW) {
37     RefreshCredential();
38   }
39   return latest_credential;
40 }
41 
RefreshCredential()42 void GceMetadataCredentialSource::RefreshCredential() {
43   Json::Value credential_json =
44       curl.DownloadToJson(REFRESH_URL, {"Metadata-Flavor: Google"});
45 
46   CHECK(!credential_json.isMember("error")) << "Error fetching credentials. " <<
47       "Response was " << credential_json;
48   bool has_access_token = credential_json.isMember("access_token");
49   bool has_expires_in = credential_json.isMember("expires_in");
50   if (!has_access_token || !has_expires_in) {
51     LOG(FATAL) << "GCE credential was missing access_token or expires_in. "
52         << "Full response was " << credential_json << "";
53   }
54 
55   expiration = std::chrono::steady_clock::now()
56       + std::chrono::seconds(credential_json["expires_in"].asInt());
57   latest_credential = credential_json["access_token"].asString();
58 }
59 
make()60 std::unique_ptr<CredentialSource> GceMetadataCredentialSource::make() {
61   return std::unique_ptr<CredentialSource>(new GceMetadataCredentialSource());
62 }
63 
FixedCredentialSource(const std::string & credential)64 FixedCredentialSource::FixedCredentialSource(const std::string& credential) {
65   this->credential = credential;
66 }
67 
Credential()68 std::string FixedCredentialSource::Credential() {
69   return credential;
70 }
71 
make(const std::string & credential)72 std::unique_ptr<CredentialSource> FixedCredentialSource::make(
73     const std::string& credential) {
74   return std::unique_ptr<CredentialSource>(new FixedCredentialSource(credential));
75 }
76 
77 } // namespace cuttlefish
78