// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 "kudu/security/security-test-util.h"

#include <cstdint>
#include <optional>
#include <string>

#include "kudu/security/ca/cert_management.h"
#include "kudu/security/cert.h"
#include "kudu/security/crypto.h"
#include "kudu/security/test/test_certs.h"
#include "kudu/security/tls_context.h"
#include "kudu/util/test_util.h"

using kudu::security::ca::CaCertRequestGenerator;
using kudu::security::ca::CertSigner;

namespace kudu {
namespace security {

Status GenerateSelfSignedCAForTests(PrivateKey* ca_key, Cert* ca_cert) {
  constexpr int64_t kRootCaCertExpirationSeconds = 24 * 60 * 60;
  // Create a key for the self-signed CA.
  //
  // OpenSSL has a concept of "security levels" which, amongst other things,
  // place certain restrictions on key strength. OpenSSL 1.0 defaults to level
  // 0 (no restrictions) while 1.1 defaults to level 1, which requires RSA keys
  // to have at least 1024 bits. For simplicity, we'll just use 1024 bits here,
  // even though shorter keys would decrease test running time.
  //
  // See https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_get_security_level.html
  // for more details.
  RETURN_NOT_OK(GeneratePrivateKey(1024, ca_key));
  return CertSigner::SelfSignCA(*ca_key,
                                CaCertRequestGenerator::Config{ "test-ca-cn" },
                                kRootCaCertExpirationSeconds,
                                ca_cert);
}

std::ostream& operator<<(std::ostream& o, PkiConfig c) {
    switch (c) {
      case PkiConfig::NONE: o << "NONE"; break;
      case PkiConfig::SELF_SIGNED: o << "SELF_SIGNED"; break;
      case PkiConfig::TRUSTED: o << "TRUSTED"; break;
      case PkiConfig::SIGNED: o << "SIGNED"; break;
      case PkiConfig::EXTERNALLY_SIGNED: o << "EXTERNALLY_SIGNED"; break;
    }
    return o;
}

Status ConfigureTlsContext(PkiConfig config,
                           const Cert& ca_cert,
                           const PrivateKey& ca_key,
                           TlsContext* tls_context) {
  switch (config) {
    case PkiConfig::NONE: break;
    case PkiConfig::SELF_SIGNED:
      RETURN_NOT_OK(tls_context->GenerateSelfSignedCertAndKey());
      break;
    case PkiConfig::TRUSTED:
      RETURN_NOT_OK(tls_context->AddTrustedCertificate(ca_cert));
      break;
    case PkiConfig::SIGNED: {
      RETURN_NOT_OK(tls_context->AddTrustedCertificate(ca_cert));
      RETURN_NOT_OK(tls_context->GenerateSelfSignedCertAndKey());
      Cert cert;
      RETURN_NOT_OK(CertSigner(&ca_cert, &ca_key).Sign(*tls_context->GetCsrIfNecessary(), &cert));
      RETURN_NOT_OK(tls_context->AdoptSignedCert(cert));
      break;
    };
    case PkiConfig::EXTERNALLY_SIGNED: {
      std::string cert_path, key_path;
      // Write certificate and private key to file.
      RETURN_NOT_OK(CreateTestSSLCertWithPlainKey(GetTestDataDirectory(), &cert_path, &key_path));
      RETURN_NOT_OK(tls_context->LoadCertificateAndKey(cert_path, key_path));
      RETURN_NOT_OK(tls_context->LoadCertificateAuthority(cert_path));
    };
  }
  return Status::OK();
}

} // namespace security
} // namespace kudu
