<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
#include "tink/integration/gcpkms/gcp_kms_client.h"

#include <iostream>
#include <fstream>
#include <sstream>

#include "absl/memory/memory.h"
#include "absl/strings/ascii.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "grpcpp/channel.h"
#include "grpcpp/create_channel.h"
#include "grpcpp/security/credentials.h"
#include "tink/integration/gcpkms/gcp_kms_aead.h"
#include "tink/kms_client.h"
#include "tink/util/errors.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"

namespace crypto {
namespace tink {
namespace integration {
namespace gcpkms {

namespace {

using crypto::tink::ToStatusF;
using crypto::tink::util::Status;
using crypto::tink::util::StatusOr;
using google::cloud::kms::v1::KeyManagementService;
using grpc::Channel;
using grpc::ChannelCredentials;

static constexpr char kKeyUriPrefix[] = "gcp-kms://";
static constexpr char kGcpKmsServer[] = "cloudkms.googleapis.com";

StatusOr<std::string> ReadFile(absl::string_view filename) {
  std::ifstream input_stream;
  input_stream.open(std::string(filename), std::ifstream::in);
  if (!input_stream.is_open()) {
    return ToStatusF(util::error::INVALID_ARGUMENT, "Error reading file %s",
                     filename);
  }
  std::stringstream input;
  input << input_stream.rdbuf();
  input_stream.close();
  return input.str();
}

StatusOr<std::shared_ptr<ChannelCredentials>> GetCredentials(
    absl::string_view credentials_path) {
  if (credentials_path.empty()) {
    auto creds = grpc::GoogleDefaultCredentials();
    if (creds == nullptr) {
      return Status(util::error::INTERNAL,
                    "Could not read default credentials");
    }
    return creds;
  }

  // Try reading credentials from a file.
  auto json_creds_result = ReadFile(credentials_path);
  if (!json_creds_result.ok()) return json_creds_result.status();
  auto creds = grpc::ServiceAccountJWTAccessCredentials(
      json_creds_result.ValueOrDie());
  if (creds != nullptr) {
    // Creating "empty" 'channel_creds', to convert 'creds'
    // to ChannelCredentials via CompositeChannelCredentials().
    auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
    return grpc::CompositeChannelCredentials(channel_creds, creds);
  }
  return ToStatusF(util::error::INVALID_ARGUMENT,
                   "Could not load credentials from file %s", credentials_path);
}

// Returns GCP KMS key name contained in 'key_uri'.
// If 'key_uri' does not refer to an GCP key, returns an empty string.
std::string GetKeyName(absl::string_view key_uri) {
  if (!absl::StartsWithIgnoreCase(key_uri, kKeyUriPrefix)) return "";
  return std::string(key_uri.substr(std::string(kKeyUriPrefix).length()));
}

}  // namespace

// static
StatusOr<std::unique_ptr<GcpKmsClient>>
GcpKmsClient::New(absl::string_view key_uri,
                  absl::string_view credentials_path) {
  std::unique_ptr<GcpKmsClient> client(new GcpKmsClient());

  // If a specific key is given, create an AWS KMSClient.
  if (!key_uri.empty()) {
    client->key_name_ = GetKeyName(key_uri);
    if (client->key_name_.empty()) {<commit_msg>Fix typo in GCP KMS Client comment.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
#include "tink/integration/gcpkms/gcp_kms_client.h"

#include <iostream>
#include <fstream>
#include <sstream>

#include "absl/memory/memory.h"
#include "absl/strings/ascii.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "grpcpp/channel.h"
#include "grpcpp/create_channel.h"
#include "grpcpp/security/credentials.h"
#include "tink/integration/gcpkms/gcp_kms_aead.h"
#include "tink/kms_client.h"
#include "tink/util/errors.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"

namespace crypto {
namespace tink {
namespace integration {
namespace gcpkms {

namespace {

using crypto::tink::ToStatusF;
using crypto::tink::util::Status;
using crypto::tink::util::StatusOr;
using google::cloud::kms::v1::KeyManagementService;
using grpc::Channel;
using grpc::ChannelCredentials;

static constexpr char kKeyUriPrefix[] = "gcp-kms://";
static constexpr char kGcpKmsServer[] = "cloudkms.googleapis.com";

StatusOr<std::string> ReadFile(absl::string_view filename) {
  std::ifstream input_stream;
  input_stream.open(std::string(filename), std::ifstream::in);
  if (!input_stream.is_open()) {
    return ToStatusF(util::error::INVALID_ARGUMENT, "Error reading file %s",
                     filename);
  }
  std::stringstream input;
  input << input_stream.rdbuf();
  input_stream.close();
  return input.str();
}

StatusOr<std::shared_ptr<ChannelCredentials>> GetCredentials(
    absl::string_view credentials_path) {
  if (credentials_path.empty()) {
    auto creds = grpc::GoogleDefaultCredentials();
    if (creds == nullptr) {
      return Status(util::error::INTERNAL,
                    "Could not read default credentials");
    }
    return creds;
  }

  // Try reading credentials from a file.
  auto json_creds_result = ReadFile(credentials_path);
  if (!json_creds_result.ok()) return json_creds_result.status();
  auto creds = grpc::ServiceAccountJWTAccessCredentials(
      json_creds_result.ValueOrDie());
  if (creds != nullptr) {
    // Creating "empty" 'channel_creds', to convert 'creds'
    // to ChannelCredentials via CompositeChannelCredentials().
    auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
    return grpc::CompositeChannelCredentials(channel_creds, creds);
  }
  return ToStatusF(util::error::INVALID_ARGUMENT,
                   "Could not load credentials from file %s", credentials_path);
}

// Returns GCP KMS key name contained in 'key_uri'.
// If 'key_uri' does not refer to an GCP key, returns an empty string.
std::string GetKeyName(absl::string_view key_uri) {
  if (!absl::StartsWithIgnoreCase(key_uri, kKeyUriPrefix)) return "";
  return std::string(key_uri.substr(std::string(kKeyUriPrefix).length()));
}

}  // namespace

// static
StatusOr<std::unique_ptr<GcpKmsClient>>
GcpKmsClient::New(absl::string_view key_uri,
                  absl::string_view credentials_path) {
  std::unique_ptr<GcpKmsClient> client(new GcpKmsClient());

  // If a specific key is given, create a GCP KMSClient.
  if (!key_uri.empty()) {
    client->key_name_ = GetKeyName(key_uri);
    if (client->key_name_.empty()) {
{'fraction_non_alphanumeric': 0.14575913467880228, 'fraction_numerical': 0.001319087191663369, 'mean_word_length': 4.129905277401894, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3418527', 'n_tokens_mistral': 2371, 'n_tokens_neox': 2374, 'n_words': 582}