#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 "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/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 "grpc/grpc_security_constants.h"
#include "grpcpp/security/auth_context.h"
#include "grpcpp/support/status.h"
#include "grpcpp/support/string_ref.h"
#include "nlohmann/json.hpp"
#include "config_parser.h"
#include "oauth_utils.h"
#include "redfish_authorizer.h"
#include "redfish_privileges.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);
}

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

BmcWebAuthorizerSingleton::BmcWebAuthorizerSingleton(
    const AuthorizerOptions& options, std::string_view oauth_key_path)
    : 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 (grpc::Status status = AuthorizeWithoutTrustBundle(uri, verb);
        !status.ok()) {
      return status;
    }
    return grpc::Status::OK;
  }

  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;
    }
  }

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

  return grpc::Status::OK;
}

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);
}

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) {
  if (!context.IsPeerAuthenticated()) {
    return grpc::Status(grpc::StatusCode::UNAUTHENTICATED,
                        "Peer is unauthenticated");
  }
  if (context.GetPeerIdentityPropertyName() != GRPC_X509_SAN_PROPERTY_NAME) {
    return grpc::Status(grpc::StatusCode::PERMISSION_DENIED,
                        "Peer identity isn't X.509 SAN");
  }
  for (const grpc::string_ref& val : context.GetPeerIdentity()) {
    std::string_view str(val.data(), val.size());
    // As per SPIFFE specification, SPIFFE schema and trust domain are case
    // insensitive.
    // https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE-ID.md#24-spiffe-id-parsing
    if (absl::StartsWithIgnoreCase(str, "spiffe://")) {
      peer_identity.spiffe_id = str;
    } else if (absl::EndsWith(str, ".prod.google.com")) {
      peer_identity.fqdn = str;
    }
  }
  return grpc::Status::OK;
}

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 = client_metadata.find("target");
    if (it != client_metadata.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 hostname='$1'; BMC's FQDNs='$2'",
          host, primary_fqdn, absl::StrJoin(GetInterfaceFqdns(), " ")));
}

}  // namespace milotic::authz
