Skip to content
6 changes: 6 additions & 0 deletions google/cloud/credentials.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ std::shared_ptr<Credentials> MakeServiceAccountCredentials(
std::move(json_object), std::move(opts));
}

std::shared_ptr<Credentials> MakeServiceAccountCredentialsFromFile(
std::string const& file_path, Options opts) {
return std::make_shared<internal::ServiceAccountConfig>("", file_path,
std::move(opts));
}

std::shared_ptr<Credentials> MakeExternalAccountCredentials(
std::string json_object, Options opts) {
return std::make_shared<internal::ExternalAccountConfig>(
Expand Down
49 changes: 49 additions & 0 deletions google/cloud/credentials.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,55 @@ std::shared_ptr<Credentials> MakeImpersonateServiceAccountCredentials(
std::shared_ptr<Credentials> MakeServiceAccountCredentials(
std::string json_object, Options opts = {});

/**
* Creates service account credentials from a service account key contained in
* a file.
*
* A [service account] is an account for an application or compute workload
* instead of an individual end user. The recommended practice is to use
* Google Default Credentials, which relies on the configuration of the Google
* Cloud system hosting your application (GCE, GKE, Cloud Run) to authenticate
* your workload or application. But sometimes you may need to create and
* download a [service account key], for example, to use a service account
* when running your application on a system that is not part of Google Cloud.
*
* Service account credentials are used in this latter case.
*
* You can create multiple service account keys for a single service account.
* When you create a service account key, the key is returned as string, in the
* format described by [aip/4112]. This string contains an id for the service
* account, as well as the cryptographical materials (a RSA private key)
* required to authenticate the caller.
*
* Therefore, services account keys should be treated as any other secret
* with security implications. Think of them as unencrypted passwords. Do not
* store them where unauthorized persons or programs may read them.
*
* As stated above, most applications should probably use default credentials,
* maybe pointing them to a file with these contents. Using this function may be
* useful when the service account key is obtained from Cloud Secret Manager or
* a similar service.
*
* [aip/4112]: https://google.aip.dev/auth/4112
* [service account]: https://cloud.google.com/iam/docs/overview#service_account
* [service account key]:
* https://cloud.google.com/iam/docs/creating-managing-service-account-keys#iam-service-account-keys-create-cpp
*
* @ingroup guac
*
* @note While JSON file formats are supported for both REST and gRPC transport,
* PKCS#12 is only supported for REST transport.
*
* @param file_path path to file containing the service account key
* Typically applications read this from a file, or download the contents from
* something like Google's secret manager service.
* @param opts optional configuration values. Note that the effect of these
* parameters depends on the underlying transport. For example,
* `LoggingComponentsOption` is ignored by gRPC-based services.
*/
std::shared_ptr<Credentials> MakeServiceAccountCredentialsFromFile(
std::string const& file_path, Options opts = {});

/**
* Creates credentials based on external accounts.
*
Expand Down
6 changes: 6 additions & 0 deletions google/cloud/internal/credentials_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ ServiceAccountConfig::ServiceAccountConfig(std::string json_object,
: json_object_(std::move(json_object)),
options_(PopulateAuthOptions(std::move(opts))) {}

ServiceAccountConfig::ServiceAccountConfig(std::string json_object,
std::string file_path, Options opts)
: json_object_(std::move(json_object)),
file_path_(std::move(file_path)),
options_(PopulateAuthOptions(std::move(opts))) {}

ExternalAccountConfig::ExternalAccountConfig(std::string json_object,
Options options)
: json_object_(std::move(json_object)),
Expand Down
4 changes: 4 additions & 0 deletions google/cloud/internal/credentials_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,18 @@ class ImpersonateServiceAccountConfig : public Credentials {
class ServiceAccountConfig : public Credentials {
public:
ServiceAccountConfig(std::string json_object, Options opts);
ServiceAccountConfig(std::string json_object, std::string file_path,
Options opts);

std::string const& json_object() const { return json_object_; }
absl::optional<std::string> const& file_path() const { return file_path_; }
Options const& options() const { return options_; }

private:
void dispatch(CredentialsVisitor& v) const override { v.visit(*this); }

std::string json_object_;
absl::optional<std::string> file_path_ = absl::nullopt;
Options options_;
};

Expand Down
4 changes: 4 additions & 0 deletions google/cloud/internal/curl_rest_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ CurlRestClient::CurlRestClient(std::string endpoint_address,
: endpoint_address_(std::move(endpoint_address)),
handle_factory_(std::move(factory)),
options_(std::move(options)) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
if (options_.has<UnifiedCredentialsOption>()) {
std::cout << __PRETTY_FUNCTION__ << ": has UnifiedCredentialsOption"
<< std::endl;
Comment on lines +115 to +118

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

These std::cout statements appear to be for debugging and should be removed before merging.

credentials_ = MapCredentials(*options_.get<UnifiedCredentialsOption>());
}
}
Expand All @@ -124,6 +127,7 @@ StatusOr<std::unique_ptr<CurlImpl>> CurlRestClient::CreateCurlImpl(
auto impl =
std::make_unique<CurlImpl>(std::move(handle), handle_factory_, options);
if (credentials_) {
std::cout << __PRETTY_FUNCTION__ << ": has credentials_" << std::endl;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This std::cout statement appears to be for debugging and should be removed before merging.

auto auth_header =
credentials_->AuthenticationHeader(std::chrono::system_clock::now());
if (!auth_header.ok()) return std::move(auth_header).status();
Expand Down
4 changes: 3 additions & 1 deletion google/cloud/internal/oauth2_access_token_credentials.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN

AccessTokenCredentials::AccessTokenCredentials(
google::cloud::AccessToken access_token)
: access_token_(std::move(access_token)) {}
: access_token_(std::move(access_token)) {
std::cout << __PRETTY_FUNCTION__ << std::endl;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This std::cout statement appears to be for debugging and should be removed before merging.

}

StatusOr<AccessToken> AccessTokenCredentials::GetToken(
std::chrono::system_clock::time_point /*tp*/) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,13 @@ AuthorizedUserCredentials::AuthorizedUserCredentials(
HttpClientFactory client_factory)
: info_(std::move(info)),
options_(std::move(options)),
client_factory_(std::move(client_factory)) {}
client_factory_(std::move(client_factory)) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

StatusOr<AccessToken> AuthorizedUserCredentials::GetToken(
std::chrono::system_clock::time_point tp) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
Comment on lines +96 to +101

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

These std::cout statements appear to be for debugging and should be removed before merging.

rest_internal::RestRequest request;
request.SetPath(info_.token_uri);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
Expand Down
1 change: 1 addition & 0 deletions google/cloud/internal/oauth2_cached_credentials.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ CachedCredentials::~CachedCredentials() = default;
StatusOr<AccessToken> CachedCredentials::GetToken(
std::chrono::system_clock::time_point now) {
std::lock_guard<std::mutex> lk(mu_);
std::cout << __PRETTY_FUNCTION__ << std::endl;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This std::cout statement appears to be for debugging and should be removed before merging.

if (!ExpiringSoon(token_, now)) return token_;
auto refreshed = impl_->GetToken(now);
if (!refreshed) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,9 @@ ComputeEngineCredentials::ComputeEngineCredentials(
HttpClientFactory client_factory)
: options_(std::move(options)),
client_factory_(std::move(client_factory)),
service_account_email_(std::move(service_account_email)) {}
service_account_email_(std::move(service_account_email)) {
std::cout << __PRETTY_FUNCTION__ << std::endl;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This std::cout statement appears to be for debugging and should be removed before merging.

}

StatusOr<AccessToken> ComputeEngineCredentials::GetToken(
std::chrono::system_clock::time_point tp) {
Expand Down
1 change: 1 addition & 0 deletions google/cloud/internal/oauth2_credentials.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ StatusOr<std::string> Credentials::project_id(

StatusOr<std::pair<std::string, std::string>> Credentials::AuthenticationHeader(
std::chrono::system_clock::time_point tp) {
std::cout << __PRETTY_FUNCTION__ << std::endl;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This std::cout statement appears to be for debugging and should be removed before merging.

auto token = GetToken(tp);
if (!token) return std::move(token).status();
if (token->token.empty()) return std::make_pair(std::string{}, std::string{});
Expand Down
1 change: 1 addition & 0 deletions google/cloud/internal/oauth2_logging_credentials.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ LoggingCredentials::~LoggingCredentials() = default;

StatusOr<AccessToken> LoggingCredentials::GetToken(
std::chrono::system_clock::time_point now) {
std::cout << __PRETTY_FUNCTION__ << std::endl;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This std::cout statement appears to be for debugging and should be removed before merging.

auto token = impl_->GetToken(now);
if (!token) {
GCP_LOG(DEBUG) << __func__ << "(" << phase_ << ") failed "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,17 +248,21 @@ ServiceAccountCredentials::ServiceAccountCredentials(
std::move(options),
Options{}.set<ServiceAccountCredentialsTokenUriOption>(
info_.token_uri))),
client_factory_(std::move(client_factory)) {}
client_factory_(std::move(client_factory)) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

StatusOr<AccessToken> ServiceAccountCredentials::GetToken(
std::chrono::system_clock::time_point tp) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
Comment on lines +252 to +257

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

These std::cout statements appear to be for debugging and should be removed before merging.

if (UseOAuth()) return GetTokenOAuth(tp);
return GetTokenSelfSigned(tp);
}

StatusOr<std::vector<std::uint8_t>> ServiceAccountCredentials::SignBlob(
absl::optional<std::string> const& signing_account,
std::string const& blob) const {
std::cout << __PRETTY_FUNCTION__ << std::endl;
if (signing_account.has_value() &&
signing_account.value() != info_.client_email) {
return internal::InvalidArgumentError(
Expand Down
11 changes: 9 additions & 2 deletions google/cloud/internal/unified_grpc_credentials.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,15 @@ std::shared_ptr<GrpcAuthenticationStrategy> CreateAuthenticationStrategy(
std::move(options));
}
void visit(ServiceAccountConfig const& cfg) override {
result = std::make_unique<GrpcServiceAccountAuthentication>(
cfg.json_object(), std::move(options));
if (cfg.file_path().has_value()) {
std::ifstream is(*cfg.file_path());
std::string contents(std::istreambuf_iterator<char>{is}, {});
result = std::make_unique<GrpcServiceAccountAuthentication>(
std::move(contents), std::move(options));
} else {
result = std::make_unique<GrpcServiceAccountAuthentication>(
cfg.json_object(), std::move(options));
}
}
void visit(ExternalAccountConfig const& cfg) override {
grpc::SslCredentialsOptions ssl_options;
Expand Down
Loading