#include "bmcweb_authorizer_singleton.h"

#include <array>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
#include <string_view>
#include <unordered_set>
#include <utility>
#include <vector>

#include "gmi/machine_identity.pb.h"
#include "tlbmc/anycast_user.h"
#include "one/network_interfaces.pb.h"
#include "one/offline_node_entities.pb.h"
#include "one/resolved_entities.pb.h"
#include "one/public_offline_node_entities.h"
#include "absl/base/no_destructor.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/log.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/substitute.h"
#include "boost/beast/http/verb.hpp"  // NOLINT
#include "authorizer_enums.h"
#include "redfish_v1.pb.h"
#include <nlohmann/json.hpp>
#include "config_parser.h"
#include "oauth_utils.h"
#include "peer_identity_grpc.h"
#include "redfish_authorizer.h"
#include "redfish_privileges.h"
#include "g3/grpc_headers.h"
#include "zatar/certificate_metadata.h"

namespace milotic::authz {

namespace {

using ::ecclesia::Operation;
using ::ecclesia::ResourceEntity;
using ::milotic::redfish::CertificateMetadata;
using ::milotic::redfish::CertificateMetadataParser;
using ::production_msv::node_entities::ReadOfflineNodeEntityInformation;
using ::production_msv::node_entities_proto::NetworkInterface;
using ::production_msv::node_entities_proto::OfflineNodeEntityInformation;
using ::production_msv::node_entities_proto::ResolvedNodeEntity;
using ::security_prodid::GoogleMachineIdentityProto;

}  // namespace

BmcWebAuthorizerSingleton& BmcWebAuthorizerSingleton::Initialize(
    const AuthorizerOptions& options, std::string_view oauth_key_path) {
  static absl::NoDestructor<BmcWebAuthorizerSingleton> singleton(
      options, oauth_key_path);

  return *singleton;
}

void BmcWebAuthorizerSingleton::ReloadRedfishAuthorizer(
    const std::string& configuration_path) {
  redfish_authorizer_.ReloadConfiguration(configuration_path);
}

void BmcWebAuthorizerSingleton::ReloadRedfishAuthorizer() {
  redfish_authorizer_.ReloadConfiguration();
}

void BmcWebAuthorizerSingleton::RegisterAnycastUser(
    const std::string& service,
    platforms_syshealth::collection::feed::AnycastUser* user) {
  redfish_authorizer_.RegisterAnycastUser(service, user);
}

BmcWebAuthorizerSingleton& BmcWebAuthorizerSingleton::GetInstance() {
  return Initialize(/*options=*/{}, /*oauth_key_path=*/"");
}

BmcWebAuthorizerSingleton::BmcWebAuthorizerSingleton(
    const AuthorizerOptions& options, std::string_view oauth_key_path)
    : tlbmc_trust_bundle_install_module_is_enabled_(
          options.tlbmc_trust_bundle_install_module_is_enabled),
      gmi_path_(options.google_machine_identity_path),
      oauth_key_path_(oauth_key_path),
      offline_node_entity_path_(options.offline_node_entities_path),
      redfish_authorizer_(options) {
  ReloadConfiguration();
}

void BmcWebAuthorizerSingleton::ReloadGmiPaths(std::string_view gmi_path) {
  gmi_path_ = gmi_path;
}

void BmcWebAuthorizerSingleton::ReloadConfiguration() {
  LOG(WARNING) << "Reload configuration started..";
  redfish_authorizer_.ReloadConfiguration();
  std::string primary_fqdn = ReadPrimaryFqdnFromGmi();
  SetPrimaryFqdn(primary_fqdn);
  SetOauthKey(ReadOauthKeyFromFile());
  ReadOfflineNodeEntity(primary_fqdn);
  LOG(WARNING) << "Reload configuration done.";
}

grpc::Status BmcWebAuthorizerSingleton::RecordNewSubscription(
    const PeerSpiffeIdentity& peer) {
  if (absl::Status status = redfish_authorizer_.RecordNewSubscription(peer);
      !status.ok()) {
    return grpc::Status(grpc::StatusCode::PERMISSION_DENIED, status.ToString());
  }
  return grpc::Status::OK;
}

grpc::Status BmcWebAuthorizerSingleton::RecordNewUnsubscription(
    const PeerSpiffeIdentity& peer) {
  if (absl::Status status = redfish_authorizer_.RecordNewUnsubscription(peer);
      !status.ok()) {
    return grpc::Status(grpc::StatusCode::PERMISSION_DENIED, status.ToString());
  }
  return grpc::Status::OK;
}

grpc::Status BmcWebAuthorizerSingleton::Authorize(
    std::string_view uri, boost::beast::http::verb verb,
    const RequestState& request_state) const {
  if (!request_state.peer_authenticated) {
    if (request_state.with_trust_bundle) {
      return grpc::Status(
          grpc::StatusCode::UNAUTHENTICATED,
          "Peer must be authenticated if BMC has trust bundle!");
    }
    if (tlbmc_trust_bundle_install_module_is_enabled_) {
      return RecoveryAuthorizeForBloom(uri, verb);
    }

    return AuthorizeWithoutTrustBundle(uri, verb);
  }

  return AuthorizeWithTrustBundle(uri, verb, request_state);
}

grpc::Status BmcWebAuthorizerSingleton::AuthorizeWithTrustBundle(
    std::string_view uri, boost::beast::http::verb verb,
    const RequestState& request_state) const {
  Operation operation = BoostVerbToOperation(verb);
  RedfishPrivileges peer_privileges =
      RedfishPrivileges(request_state.peer_privileges);
  if (!redfish_authorizer_.IsPeerAuthorized(uri, operation, peer_privileges)) {
    return grpc::Status(grpc::StatusCode::PERMISSION_DENIED,
                        "Client doesn't have enough permissions: " +
                            peer_privileges.GetDebugString());
  }
  return grpc::Status::OK;
}

Operation BmcWebAuthorizerSingleton::BoostVerbToOperation(
    boost::beast::http::verb verb) {
  switch (verb) {
    case boost::beast::http::verb::get:
      return Operation::kGet;
    case boost::beast::http::verb::post:
      return Operation::kPost;
    case boost::beast::http::verb::delete_:
      return Operation::kDelete;
    case boost::beast::http::verb::put:
      return Operation::kPut;
    case boost::beast::http::verb::patch:
      return Operation::kPatch;
    case boost::beast::http::verb::head:
      return Operation::kHead;
    default:
      return Operation::kUndefined;
  }
}

grpc::Status BmcWebAuthorizerSingleton::AuthorizeWithoutTrustBundle(
    std::string_view uri, boost::beast::http::verb verb) const {
  constexpr std::array<std::pair<ResourceEntity, boost::beast::http::verb>, 10>
      kRecoveryOperations = {
          std::pair<ResourceEntity, boost::beast::http::verb>{
              ResourceEntity::kServiceRoot, boost::beast::http::verb::get},
          {ResourceEntity::kChassisCollection, boost::beast::http::verb::get},
          {ResourceEntity::kChassis, boost::beast::http::verb::get},
          {ResourceEntity::kActionInfo, boost::beast::http::verb::get},
          {ResourceEntity::kChassis, boost::beast::http::verb::post},
          {ResourceEntity::kComputerSystem, boost::beast::http::verb::get},
          {ResourceEntity::kComputerSystemCollection,
           boost::beast::http::verb::get},
          {ResourceEntity::kComputerSystem, boost::beast::http::verb::post},
          {ResourceEntity::kManagerCollection, boost::beast::http::verb::get},
          {ResourceEntity::kManager, boost::beast::http::verb::get},
      };
  ResourceEntity entity = GetEntityTypeFromRedfishUri(uri);
  bool authorized = false;
  for (auto const& [allowed_entity, allowed_verb] : kRecoveryOperations) {
    if (entity == allowed_entity && verb == allowed_verb) {
      authorized = true;
      break;
    }
  }

  // Specifically hardcode the Manager.Reset operations to be allowed.
  if ((uri == "/redfish/v1/Managers/bmc/Actions/Manager.Reset") &&
      verb == boost::beast::http::verb::post) {
    authorized = true;
  }

  if (!authorized) {
    return grpc::Status(
        grpc::StatusCode::PERMISSION_DENIED,
        "Without trust bundle, only recovery operations are allowed");
  }

  return grpc::Status::OK;
}

grpc::Status BmcWebAuthorizerSingleton::RecoveryAuthorizeForBloom(
    std::string_view uri, boost::beast::http::verb verb) const {
  // allowlist during trust bundle installation
  static const absl::NoDestructor<absl::flat_hash_set<
      std::pair<std::string_view, boost::beast::http::verb>>>
      kAllowedEndpoints(
          {{"/redfish/v1", boost::beast::http::verb::get},
           {"/redfish/v1/CertificateService", boost::beast::http::verb::get},
           {"/redfish/v1/CertificateService/ReplaceCertificateActionInfo",
            boost::beast::http::verb::get},
           {"/redfish/v1/CertificateService/Actions/"
            "CertificateService.ReplaceCertificate",
            boost::beast::http::verb::post},
           {"/redfish/v1/Managers/bmc/Actions/Manager.Reset",
            boost::beast::http::verb::post},
           {"/redfish/v1/UpdateService/MultipartUpdate",
            boost::beast::http::verb::post},
           {"/redfish/v1/UpdateService/Oem/Google/DebugLogs",
            boost::beast::http::verb::get},
           {"/redfish/v1/UpdateService/FirmwareInventory/BMC_dauntless",
            boost::beast::http::verb::get},
           {"/redfish/v1/UpdateService/FirmwareInventory/tray_dauntless_BMC",
            boost::beast::http::verb::get},
           {"/redfish/v1/UpdateService/FirmwareInventory/BMC",
            boost::beast::http::verb::get},
           {"/redfish/v1/TaskService", boost::beast::http::verb::get},
           {"/redfish/v1/TaskService/Tasks", boost::beast::http::verb::get},
           {"/redfish/v1/TaskService/Tasks/FirmwareBundleDownload",
            boost::beast::http::verb::get},
           {"/redfish/v1/TaskService/Tasks/FirmwareBundleUpdate",
            boost::beast::http::verb::get}});

  if (kAllowedEndpoints->contains({uri, verb})) {
    return grpc::Status::OK;
  }

  return grpc::Status(
      grpc::StatusCode::PERMISSION_DENIED,
      "Please install your client *CA* certificate as trust bundle first.");
}

grpc::Status BmcWebAuthorizerSingleton::GetPeerRoleFromAuthContext(
    const grpc::AuthContext& context, std::string& peer_role) const {
  PeerSpiffeIdentity peer_identity;
  if (grpc::Status status =
          GetPeerIdentityFromAuthContext(context, peer_identity);
      !status.ok()) {
    peer_role.clear();
    return status;
  }
  peer_role = redfish_authorizer_.GetPeerRedfishRole(peer_identity);
  if (peer_role.empty()) {
    return grpc::Status(
        grpc::StatusCode::PERMISSION_DENIED,
        absl::StrCat(
            "Peer role is not specified in the auth config: peer_identity=",
            peer_identity.spiffe_id));
  }
  return grpc::Status::OK;
}

grpc::Status BmcWebAuthorizerSingleton::GetPrivilegesViaOAuth(
    const grpc::AuthContext& context, const std::string& token,
    std::unordered_set<std::string>& peer_privileges) const {
  PeerSpiffeIdentity peer_identity;
  if (grpc::Status status =
          GetPeerIdentityFromAuthContext(context, peer_identity);
      !status.ok()) {
    return status;
  }

  std::string redfish_role;
  constexpr const char* kExpectedIssuer = "BMC Local Authorization Server";
  if (grpc::Status status = VerifyAndExtractRoleFromToken(
          token, GetOauthKey(), GenerateOAuthSubject(peer_identity),
          GetPrimaryFqdn(), kExpectedIssuer, redfish_role);
      !status.ok()) {
    return status;
  }

  peer_privileges = redfish_authorizer_.GetRedfishPrivileges(redfish_role);
  return grpc::Status::OK;
}

grpc::Status BmcWebAuthorizerSingleton::GetPrivilegesViaMTls(
    const grpc::AuthContext& context,
    std::unordered_set<std::string>& peer_privileges) const {
  PeerSpiffeIdentity peer_identity;
  if (grpc::Status status =
          GetPeerIdentityFromAuthContext(context, peer_identity);
      !status.ok()) {
    return status;
  }
  LOG(INFO) << "Peer identity: " << peer_identity.spiffe_id;
  peer_privileges = redfish_authorizer_.GetPeerRedfishPrivileges(peer_identity);
  return grpc::Status::OK;
}

std::string BmcWebAuthorizerSingleton::ReadPrimaryFqdnFromGmi() const {
  std::ifstream gmi_file(gmi_path_);
  if (!gmi_file.is_open()) {
    LOG(WARNING) << "GMI file at '" << gmi_path_ << "' is missing." << '\n';
    return "";
  }
  GoogleMachineIdentityProto gmi;
  if (!gmi.ParseFromIstream(&gmi_file)) {
    std::cerr << "GMI parsing failed at '" << gmi_path_ << "'" << '\n';
    return "";
  }
  return gmi.fqdn();
}

std::string BmcWebAuthorizerSingleton::ReadOauthKeyFromFile() const {
  std::ifstream oauth_key_file(oauth_key_path_);
  if (!oauth_key_file.is_open()) {
    LOG(WARNING) << "OAuth key file at '" << oauth_key_path_ << "' is missing."
                 << '\n';
    return "";
  }
  std::string oauth_key = {std::istreambuf_iterator<char>(oauth_key_file),
                           std::istreambuf_iterator<char>()};
  return oauth_key;
}

void BmcWebAuthorizerSingleton::ReadOfflineNodeEntity(
    std::string_view primary_fqdn) {
  std::ifstream offline_node_entity_file(offline_node_entity_path_);
  std::vector<std::string> interface_fqdns;
  bool has_bmc_direct_ethernet = false;
  if (!offline_node_entity_file.is_open()) {
    LOG(WARNING) << "Offline Node Entity file at '" << offline_node_entity_path_
                 << "' is missing." << '\n';
    SetInterfaceFqdns(std::move(interface_fqdns));
    SetHasBmcDirectEthernet(has_bmc_direct_ethernet);
    return;
  }
  absl::StatusOr<OfflineNodeEntityInformation> one =
      ReadOfflineNodeEntityInformation(offline_node_entity_path_);
  if (!one.ok()) {
    LOG(WARNING) << "Could not read offline node entities information: "
                 << one.status().message();
    SetInterfaceFqdns(std::move(interface_fqdns));
    SetHasBmcDirectEthernet(has_bmc_direct_ethernet);
    return;
  }
  const auto& entities = one->resolved_config().entities();

  // Find target entity by current entity tag.
  const ResolvedNodeEntity* target_entity = nullptr;
  if (!one->entity_tag().empty()) {
    auto it = entities.find(one->entity_tag());
    if (it != entities.end()) {
      target_entity = &it->second;
    }
  }

  if (target_entity != nullptr) {
    for (const NetworkInterface& intf :
         target_entity->network_interfaces().network_interface()) {
      if (intf.has_bmc_interface_role() &&
          intf.bmc_interface_role() ==
              NetworkInterface::BMC_IR_DIRECT_ETHERNET) {
        has_bmc_direct_ethernet = true;
      }
      interface_fqdns.push_back(intf.hostname() + ".prod.google.com");
    }
  }

  SetInterfaceFqdns(std::move(interface_fqdns));
  SetHasBmcDirectEthernet(has_bmc_direct_ethernet);
}

uint64_t BmcWebAuthorizerSingleton::GetSampleRateLimit(
    const std::string& peer_role) const {
  return redfish_authorizer_.GetSampleRateLimit(peer_role);
}

std::string BmcWebAuthorizerSingleton::GetAnycastAddress(
    const std::string& peer_role) const {
  return redfish_authorizer_.GetAnycastAddress(peer_role);
}

ResourceEntity BmcWebAuthorizerSingleton::GetEntityTypeFromRedfishUri(
    std::string_view uri) const {
  return redfish_authorizer_.GetEntityTypeFromRedfishUri(uri);
}

std::size_t BmcWebAuthorizerSingleton::GetNodeIndexInPatternArray(
    std::string_view uri) const {
  return redfish_authorizer_.GetNodeIndexInPatternArray(uri);
}

nlohmann::json BmcWebAuthorizerSingleton::GetRedfishPrivilegeRegistry() const {
  return redfish_authorizer_.GetRedfishPrivilegeRegistry();
}

bool BmcWebAuthorizerSingleton::IsBasePrivilegeRegistryFound() const {
  nlohmann::json config_json = redfish_authorizer_.ParseAuthConfig();

  if (config_json.empty()) {
    return false;
  }

  std::string base_privilege_registry_path =
      redfish_authorizer_.FindBasePrivilegeRegistryPath(config_json);

  return !base_privilege_registry_path.empty();
}

void BmcWebAuthorizerSingleton::SetBasePrivilegesFolder(
    std::string_view base_privileges_folder) {
  redfish_authorizer_.SetBasePrivilegesFolder(base_privileges_folder);
}

grpc::Status BmcWebAuthorizerSingleton::GetPeerIdentityFromAuthContext(
    const grpc::AuthContext& context, PeerSpiffeIdentity& peer_identity) {
  return ExtractPeerIdentityFromAuthContext(context, peer_identity);
}

grpc::Status BmcWebAuthorizerSingleton::CheckTarget(
    const grpc::AuthContext& grpc_context,
    const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata,
    const ::redfish::v1::Request& request) const {
  PeerSpiffeIdentity peer_identity;
  if (grpc::Status status =
          GetPeerIdentityFromAuthContext(grpc_context, peer_identity);
      !status.ok()) {
    return status;
  }

  CertificateMetadata peer_metadata;
  if (absl::Status status = metadata_parser_.GetContextAndRoleFromSpiffe(
          peer_identity.spiffe_id, peer_metadata.context, peer_metadata.role);
      !status.ok()) {
    return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, status.ToString());
  }

  // If the service (BMCWeb) has a legitimate GMI, and peer is not a node (e.g.,
  // it's a Borg job), check that the intended recipient of the request matches
  // the identity in the certificate. This is to prevent redirect attacks in
  // powercycle trust model, where clients never verify server.
  std::string primary_fqdn = GetPrimaryFqdn();
  if (primary_fqdn.empty()) {
    LOG(WARNING) << "Can't parse primary fqdn. GMI is probably broken.";
    return grpc::Status::OK;
  }
  if (peer_metadata.context == CertificateMetadataParser::kCaContextNode) {
    return grpc::Status::OK;
  }

  std::string host;
  for (auto const& [key, val] : request.headers()) {
    // Both field name of the Authorization header and the token type are case
    // insensitive
    // References
    // https://www.rfc-editor.org/rfc/rfc7230#section-3.2
    // https://www.rfc-editor.org/rfc/rfc6749#section-5.1
    if (absl::EqualsIgnoreCase(key, "Host")) {
      host = val;
    }
  }

  // To keep backward compatibility, extract host from metadata as well if it's
  // not in headers.
  if (host.empty()) {
    auto [it, end] = client_metadata.equal_range("target");
    if (it != end) {
      host = {it->second.data(), it->second.length()};
    }
  }

  // DNS should be case insensitive
  // Reference: https://www.rfc-editor.org/rfc/rfc4343
  if (absl::EqualsIgnoreCase(host, primary_fqdn)) {
    return grpc::Status::OK;
  }

  // We could have multiple FQDNs on BMC and they can be different from the
  // hostname. Matching any of them should pass the validation
  for (const std::string& fqdn : GetInterfaceFqdns()) {
    if (absl::EqualsIgnoreCase(host, fqdn)) {
      return grpc::Status::OK;
    }
  }

  return grpc::Status(
      grpc::StatusCode::PERMISSION_DENIED,
      absl::Substitute(
          "Unauthorized user: request target doesn't match server; request's "
          "host header='$0'; BMC's primary FQDN='$1'; BMC's interface "
          "FQDNs='$2'",
          host, primary_fqdn, absl::StrJoin(GetInterfaceFqdns(), " ")));
}

void BmcWebAuthorizerSingleton::DeregisterAnycastUser(
    const std::string& service) {
  redfish_authorizer_.DeregisterAnycastUser(service);
}

nlohmann::json BmcWebAuthorizerSingleton::GetConfig() const {
  return redfish_authorizer_.GetConfig();
}

nlohmann::json BmcWebAuthorizerSingleton::GetPrivilegeRegistry() const {
  return redfish_authorizer_.GetPrivilegeRegistry();
}

}  // namespace milotic::authz
