// 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/master/master_cert_authority.h"

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

#include <gflags/gflags.h>

#include "kudu/gutil/strings/substitute.h"
#include "kudu/rpc/remote_user.h"
#include "kudu/security/ca/cert_management.h"
#include "kudu/security/cert.h"
#include "kudu/security/crypto.h"
#include "kudu/util/flag_tags.h"
#include "kudu/util/monotime.h"
#include "kudu/util/openssl_util.h"
#include "kudu/util/status.h"

using std::optional;
using std::string;
using std::unique_ptr;

using kudu::security::Cert;
using kudu::security::CertSignRequest;
using kudu::security::PrivateKey;
using kudu::security::ca::CaCertRequestGenerator;
using kudu::security::ca::CertSigner;

DEFINE_int32(ipki_ca_key_size, 2048,
             "the number of bits for self-signed root CA cert used by Kudu IPKI "
             "(Internal Private Key Infrastructure, a.k.a. Internal Kudu CA)");
TAG_FLAG(ipki_ca_key_size, experimental);

DEFINE_int64(ipki_ca_cert_expiration_seconds, 10 * 365 * 24 * 60 * 60,
             "validity interval for self-signed root CA certifcate "
             "issued by Kudu IPKI "
             "(Internal Private Key Infrastructure, a.k.a. Internal Kudu CA)");
TAG_FLAG(ipki_ca_cert_expiration_seconds, experimental);

DEFINE_int64(ipki_server_cert_expiration_seconds, 10 * 365 * 24 * 60 * 60,
             "validity interval for server certificates issued by Kudu IPKI "
             "(Internal Private Key Infrastructure, a.k.a. Internal Kudu CA)");
TAG_FLAG(ipki_server_cert_expiration_seconds, experimental);

namespace kudu {
namespace master {

Status MasterCertAuthority::Generate(security::PrivateKey* key,
                                     security::Cert* cert) {
  CHECK(key);
  CHECK(cert);
  // Create a key and cert for the self-signed CA.
  CaCertRequestGenerator::Config config = { "kudu-ipki-ca" };
  RETURN_NOT_OK(GeneratePrivateKey(FLAGS_ipki_ca_key_size, key));
  return CertSigner::SelfSignCA(*key,
                                config,
                                FLAGS_ipki_ca_cert_expiration_seconds,
                                cert);
}

MasterCertAuthority::MasterCertAuthority(string server_uuid)
    : server_uuid_(std::move(server_uuid)) {
}

MasterCertAuthority::~MasterCertAuthority() {
}

Status MasterCertAuthority::Init(unique_ptr<PrivateKey> key,
                                 unique_ptr<Cert> cert) {
  CHECK(key);
  CHECK(cert);

  // Cache the exported DER-format cert.
  string ca_cert_der;
  RETURN_NOT_OK(cert->ToString(&ca_cert_der, security::DataFormat::DER));

  ca_private_key_ = std::move(key);
  ca_cert_ = std::move(cert);
  ca_cert_der_ = std::move(ca_cert_der);
  return Status::OK();
}

Status MasterCertAuthority::SignServerCSR(const CertSignRequest& csr,
                                          Cert* cert) {
  CHECK(ca_cert_ && ca_private_key_) << "not initialized";
  RETURN_NOT_OK_PREPEND(CertSigner(ca_cert_.get(), ca_private_key_.get())
                        .set_expiration_interval(MonoDelta::FromSeconds(
                            FLAGS_ipki_server_cert_expiration_seconds))
                        .Sign(csr, cert),
                        "failed to sign cert");
  return Status::OK();
}

Status MasterCertAuthority::SignServerCSR(const string& csr_der, const rpc::RemoteUser& user,
                                          string* cert_der) {
  CHECK(ca_cert_ && ca_private_key_) << "not initialized";

  CertSignRequest csr;
  RETURN_NOT_OK_PREPEND(csr.FromString(csr_der, security::DataFormat::DER),
                        "could not parse CSR");
  Cert cert;
  RETURN_NOT_OK(SignServerCSR(csr, &cert));

  // Validate that the cert has an included user ID.
  // It may seem funny to validate after signing, but we already have the functions
  // to get the cert details out of a Cert object, and not out of a CSR object.
  optional<string> cert_uid = cert.UserId();
  if (cert_uid != user.username()) {
    return Status::NotAuthorized(strings::Substitute(
        "CSR did not contain expected username. (CSR: '$0' RPC: '$1')",
        cert_uid.value_or(""),
        user.username()));
  }
  optional<string> cert_principal = cert.KuduKerberosPrincipal();
  if (cert_principal != user.principal()) {
    return Status::NotAuthorized(strings::Substitute(
        "CSR did not contain expected krb5 principal (CSR: '$0' RPC: '$1')",
        cert_principal.value_or(""),
        user.principal().value_or("")));
  }

  RETURN_NOT_OK_PREPEND(cert.ToString(cert_der, security::DataFormat::DER),
                        "failed to signed cert as DER format");
  return Status::OK();
}

} // namespace master
} // namespace kudu
