/*
 * Copyright 2021 Google LLC
 *
 * 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 "tlbmc/grpc_tls_options.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "grpcpp/security/credentials.h"
#include "grpcpp/security/tls_certificate_provider.h"
#include "grpcpp/security/tls_certificate_verifier.h"
#include "grpcpp/security/tls_credentials_options.h"

namespace ecclesia {

namespace {
// gRPC API requires we pass a parsable root cert even if we do not verify the
// cert signature.
const char *kUnusedFakeRootCert =
    R"(-----BEGIN CERTIFICATE-----
MIIDiDCCAnCgAwIBAgIIdwMbYuGm3akwDQYJKoZIhvcNAQELBQAwRTEXMBUGA1UE
ChMOR29vZ2xlIFRFU1RJTkcxKjAoBgNVBAMMIUdvb2dsZSBCTUNXZWIgKipUZXN0
aW5nKiogUm9vdCBDQTAgFw03MDAxMDEwMDAwMDBaGA8yMTI1MDEwMTAwMDAwMFow
RTEXMBUGA1UEChMOR29vZ2xlIFRFU1RJTkcxKjAoBgNVBAMMIUdvb2dsZSBCTUNX
ZWIgKipUZXN0aW5nKiogUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAKprOCLzYyqb6Mxo+I3n70P32PQLtUQdgjDXHF2cpwI0w3ezBYn4Dx0H
T7RCRvMMlxnAcRPCTBcU4I+7HnUX+mBZvFkJPJukttCOS3usC6GtD8UMNassFkSL
Vepy5AV1cwXweklebe9gAgC8NsFetqbHz12jTGUfngYDdqhg2haiTTwXyoal+575
c6F2S5krWMnBcm9/bhQufi8nC8AzQ2r1e4/bSe64F+vXzsLODsGs7mtzXeEDB2/N
7pEhQbXmkuBudXtE5CpLwvNa1Y3XLZfXXewlzlxjqQarihEolv6e/XOAJma3XMh8
Ip5QE1F/YvX3PICAbjsaX4wmWNTv7tECAwEAAaN6MHgwDgYDVR0PAQH/BAQDAgIE
MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMBAf8EBTADAQH/
MBkGA1UdDgQSBBCuOIbUVxFjIbMIYjmL68mVMBsGA1UdIwQUMBKAEK44htRXEWMh
swhiOYvryZUwDQYJKoZIhvcNAQELBQADggEBAAZ7KtkYl4CLzPTLUhSiisckk+9K
/dbiG9TjRoiD8iG2j6/lTtZr0dkEq2xgz7kfHTbINzDONn45ea+BojAKSgWcwjzj
TvTX0lubQcTLNBHVAZQ8Ws/7QN2+WF6QPpKWzk44O1Lw1JLhaLSe4GauIQICt0P5
zUVrgX2EP1FdbS/PxgQvwM3gbHJh7iqWr7ASVypLzA5+YfuPRIJAEOimQbrs/0Gq
UEYO7y3ijBKwLs0lm6rCzCjwacWb/tFIJK4FNTg7iTWs2t94HWopoZqp0mouAERe
qOFbsHcmv8mSUfig0AaTorZQpS8htNtcsCl5HhNgAyCQh+QzvBvesrEz5Cw=
-----END CERTIFICATE-----
)";

constexpr unsigned int kRefreshIntervalSec = 60;
}  // namespace

void StaticBufferBasedTlsOptions::SetToInsecure() {
  auth_type_ = AuthType::kInsecure;
}

void StaticBufferBasedTlsOptions::SetToTls(
    absl::string_view root_certs_buffer, absl::string_view key_buffer,
    absl::string_view cert_buffer,
    std::optional<absl::string_view> crl_directory) {
  auth_type_ = AuthType::kTlsVerifyServer;
  root_certs_ = root_certs_buffer;
  key_cert_ = {.private_key = std::string(key_buffer),
               .certificate_chain = std::string(cert_buffer)};
  crl_directory_ = crl_directory;
}

void StaticBufferBasedTlsOptions::SetToTls(absl::string_view root_certs_buffer,
                                           absl::string_view key_buffer,
                                           absl::string_view cert_buffer) {
  SetToTls(root_certs_buffer, key_buffer, cert_buffer,
           /*crl_directory=*/std::nullopt);
}

void StaticBufferBasedTlsOptions::SetToTlsSkipHostname(
    absl::string_view root_certs_buffer, absl::string_view key_buffer,
    absl::string_view cert_buffer,
    std::shared_ptr<grpc::experimental::CertificateVerifier> cert_verifier,
    std::optional<absl::string_view> crl_directory) {
  auth_type_ = AuthType::kTlsVerifyServerSkipHostname;
  root_certs_ = root_certs_buffer;
  key_cert_ = {.private_key = std::string(key_buffer),
               .certificate_chain = std::string(cert_buffer)};
  cert_verifier_ = std::move(cert_verifier);
  crl_directory_ = crl_directory;
}

void StaticBufferBasedTlsOptions::SetToTlsSkipHostname(
    absl::string_view root_certs_buffer, absl::string_view key_buffer,
    absl::string_view cert_buffer,
    std::shared_ptr<grpc::experimental::CertificateVerifier> cert_verifier) {
  SetToTlsSkipHostname(root_certs_buffer, key_buffer, cert_buffer,
                       std::move(cert_verifier),
                       /*crl_directory=*/std::nullopt);
}

void StaticBufferBasedTlsOptions::SetToTlsNotVerifyServer(
    absl::string_view key_buffer, absl::string_view cert_buffer,
    std::shared_ptr<grpc::experimental::CertificateVerifier> cert_verifier,
    std::optional<absl::string_view> crl_directory) {
  auth_type_ = AuthType::kTlsNotVerifyServer;
  key_cert_ = {.private_key = std::string(key_buffer),
               .certificate_chain = std::string(cert_buffer)};
  cert_verifier_ = std::move(cert_verifier);
  crl_directory_ = crl_directory;
}

void StaticBufferBasedTlsOptions::SetToTlsNotVerifyServer(
    absl::string_view key_buffer, absl::string_view cert_buffer,
    std::shared_ptr<grpc::experimental::CertificateVerifier> cert_verifier) {
  SetToTlsNotVerifyServer(key_buffer, cert_buffer, std::move(cert_verifier),
                          /*crl_directory=*/std::nullopt);
}

std::shared_ptr<grpc::ChannelCredentials>
StaticBufferBasedTlsOptions::GetChannelCredentials() const {
  switch (auth_type_) {
    case AuthType::kTlsVerifyServer: {
      grpc::experimental::TlsChannelCredentialsOptions tls_options;
      tls_options.watch_identity_key_cert_pairs();
      tls_options.watch_root_certs();
      if (crl_directory_.has_value()) {
        tls_options.set_crl_directory(*crl_directory_);
      }
      tls_options.set_certificate_provider(GetCertificateProvider());
      tls_options.set_verify_server_certs(true);
      return grpc::experimental::TlsCredentials(tls_options);
    }
    case AuthType::kTlsVerifyServerSkipHostname: {
      grpc::experimental::TlsChannelCredentialsOptions tls_options;
      tls_options.watch_identity_key_cert_pairs();
      tls_options.watch_root_certs();
      if (crl_directory_.has_value()) {
        tls_options.set_crl_directory(*crl_directory_);
      }
      tls_options.set_certificate_provider(GetCertificateProvider());
      tls_options.set_certificate_verifier(cert_verifier_);
      tls_options.set_verify_server_certs(true);
      tls_options.set_check_call_host(false);
      return grpc::experimental::TlsCredentials(tls_options);
    }
    case AuthType::kTlsNotVerifyServer: {
      grpc::experimental::TlsChannelCredentialsOptions tls_options;
      tls_options.watch_identity_key_cert_pairs();
      tls_options.watch_root_certs();
      if (crl_directory_.has_value()) {
        tls_options.set_crl_directory(*crl_directory_);
      }
      tls_options.set_certificate_provider(GetCertificateProvider());
      tls_options.set_certificate_verifier(cert_verifier_);
      tls_options.set_verify_server_certs(false);
      tls_options.set_check_call_host(false);
      return grpc::experimental::TlsCredentials(tls_options);
    }
    case AuthType::kInsecure:
      return grpc::InsecureChannelCredentials();
      // No default. We own the AuthType enum.
  }
  CHECK(false) << absl::StrCat("Unexpected value for AuthType: ", auth_type_);
  return grpc::InsecureChannelCredentials();
}

std::shared_ptr<grpc::experimental::CertificateProviderInterface>
StaticBufferBasedTlsOptions::GetCertificateProvider() const {
  switch (auth_type_) {
    case AuthType::kTlsVerifyServer: {
      return std::make_shared<
          grpc::experimental::StaticDataCertificateProvider>(
          root_certs_,
          std::vector<grpc::experimental::IdentityKeyCertPair>{key_cert_});
    }
    case AuthType::kTlsVerifyServerSkipHostname: {
      return std::make_shared<
          grpc::experimental::StaticDataCertificateProvider>(
          root_certs_,
          std::vector<grpc::experimental::IdentityKeyCertPair>{key_cert_});
    }
    case AuthType::kTlsNotVerifyServer: {
      return std::make_shared<
          grpc::experimental::StaticDataCertificateProvider>(
          kUnusedFakeRootCert,
          std::vector<grpc::experimental::IdentityKeyCertPair>{key_cert_});
    }
    case AuthType::kInsecure:
      return nullptr;
      // No default. We own the AuthType enum.
  }
  CHECK(false) << absl::StrCat("Unexpected value for AuthType: ", auth_type_);
  return nullptr;
}

void FileWatcherBasedOptions::SetToTls(
    absl::string_view root_certs_path, absl::string_view key_path,
    absl::string_view cert_path,
    std::optional<absl::string_view> crl_directory) {
  auth_type_ = AuthType::kTlsVerifyServer;
  root_certs_path_ = root_certs_path;
  key_path_ = key_path;
  cert_path_ = cert_path;
  crl_directory_ = crl_directory;
}

void FileWatcherBasedOptions::SetToTlsSkipHostname(
    absl::string_view root_certs_path, absl::string_view key_path,
    absl::string_view cert_path,
    std::shared_ptr<grpc::experimental::CertificateVerifier> cert_verifier,
    std::optional<absl::string_view> crl_directory) {
  auth_type_ = AuthType::kTlsVerifyServerSkipHostname;
  root_certs_path_ = root_certs_path;
  key_path_ = key_path;
  cert_path_ = cert_path;
  cert_verifier_ = std::move(cert_verifier);
  crl_directory_ = crl_directory;
}

void FileWatcherBasedOptions::SetToTlsNotVerifyServer(
    absl::string_view key_path, absl::string_view cert_path,
    std::shared_ptr<grpc::experimental::CertificateVerifier> cert_verifier,
    std::optional<absl::string_view> crl_directory) {
  auth_type_ = AuthType::kTlsNotVerifyServer;
  key_path_ = key_path;
  cert_path_ = cert_path;
  cert_verifier_ = std::move(cert_verifier);
  crl_directory_ = crl_directory;
}

std::shared_ptr<grpc::experimental::CertificateProviderInterface>
FileWatcherBasedOptions::GetCertificateProvider() const {
  switch (auth_type_) {
    case AuthType::kTlsVerifyServer: {
      return std::make_shared<
          grpc::experimental::FileWatcherCertificateProvider>(
          key_path_, cert_path_, root_certs_path_, kRefreshIntervalSec);
    }
    case AuthType::kTlsVerifyServerSkipHostname: {
      return std::make_shared<
          grpc::experimental::FileWatcherCertificateProvider>(
          key_path_, cert_path_, root_certs_path_, kRefreshIntervalSec);
    }
    case AuthType::kTlsNotVerifyServer: {
      return std::make_shared<
          grpc::experimental::FileWatcherCertificateProvider>(
          key_path_, cert_path_, kRefreshIntervalSec);
    }
    case AuthType::kInsecure:
      return nullptr;
      // No default. We own the AuthType enum.
  }
  CHECK(false) << absl::StrCat("Unexpected value for AuthType: ", auth_type_);
  return nullptr;
}
}  // namespace ecclesia
