#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());
  SetInterfaceFqdns(ReadDomainNameFromOfflineNodeEntity(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;
}

std::vector<std::string>
BmcWebAuthorizerSingleton::ReadDomainNameFromOfflineNodeEntity(
    std::string_view primary_fqdn) const {
  std::ifstream offline_node_entity_file(offline_node_entity_path_);
  std::vector<std::string> interface_fqdns;
  if (!offline_node_entity_file.is_open()) {
    LOG(WARNING) << "Offline Node Entity file at '" << offline_node_entity_path_
                 << "' is missing." << '\n';
    return interface_fqdns;
  }
  absl::StatusOr<OfflineNodeEntityInformation> one =
      ReadOfflineNodeEntityInformation(offline_node_entity_path_);
  if (!one.ok()) {
    LOG(WARNING) << "Could not read offline node entities information: "
                 << one.status().message();
    return interface_fqdns;
  }
  for (const std::pair<const std::string, ResolvedNodeEntity>& entity :
       (*one).resolved_config().entities()) {
    if (absl::StrCat(entity.second.hostname(), ".prod.google.com") !=
        primary_fqdn)
      continue;
    for (const NetworkInterface& intf :
         entity.second.network_interfaces().network_interface()) {
      interface_fqdns.push_back(intf.hostname() + ".prod.google.com");
    }
    break;
  }
  return interface_fqdns;
}

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
