#include "config_parser.h"

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "gmi/machine_identity.pb.h"
#include "one/node_entities_api.pb.h"
#include "one/offline_node_entities.pb.h"
#include "one/resolved_entities.pb.h"
#include "one/public_offline_node_entities.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include <nlohmann/json.hpp>
#include <nlohmann/json_fwd.hpp>
#include "json_utils.h"
#include "authorized_entity.pb.h"
#include "zatar/certificate_metadata.h"

namespace milotic::authz {

using ::milotic::redfish::CertificateMetadataParser;
using ::production_msv::node_entities::ReadOfflineNodeEntityInformation;
using ::production_msv::node_entities_proto::OfflineNodeEntityInformation;
using ::security_prodid::GoogleMachineIdentityProto;
using EntityTagIdentity = AuthzConfiguration::EntityTagIdentity;

AuthzConfiguration::AuthzConfiguration(
    const nlohmann::json& config, absl::string_view offline_node_entities_path,
    absl::string_view gmi_path)
    : offline_node_entities_path_(offline_node_entities_path),
      gmi_path_(gmi_path) {
  ReloadConfig(config, nlohmann::json());
};

std::optional<AuthzConfiguration::SpiffeIdentityMatcher>
AuthzConfiguration::CreateIdentityMatcherFromPeerSpiffeIdentity(
    const PeerSpiffeIdentity& peer) {
  AuthzConfiguration::SpiffeIdentityMatcher matcher;
  matcher.fqdn = peer.fqdn;

  const std::string spiffe_id = absl::AsciiStrToLower(peer.spiffe_id);
  // 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
  constexpr std::string_view kSpiffeSchema = "spiffe://";
  if (!absl::StartsWithIgnoreCase(spiffe_id, kSpiffeSchema)) {
    return std::nullopt;
  }

  std::size_t path_start = spiffe_id.find_first_of('/', kSpiffeSchema.size());
  if (path_start == std::string_view::npos) {
    return std::nullopt;
  }

  matcher.spiffe_id_matcher.path = spiffe_id.substr(path_start);

  const std::string trust_domain = absl::AsciiStrToLower(spiffe_id.substr(
      kSpiffeSchema.size(), path_start - kSpiffeSchema.size()));

  // Trust domain consists of (issuing-role).(context).(realm).(suffix)
  // See go/zatar-prod-certificates for details.
  std::vector<std::string_view> trust_domain_pieces =
      absl::StrSplit(trust_domain, '.');

  // There should be at least 4 elements in this array for a property trust
  // domain
  if (trust_domain_pieces.size() < 4) {
    return std::nullopt;
  }

  matcher.spiffe_id_matcher.issuer = trust_domain_pieces[0];
  matcher.spiffe_id_matcher.ca_context = trust_domain_pieces[1];
  matcher.spiffe_id_matcher.realm = trust_domain_pieces[2];

  matcher.spiffe_id_matcher.trust_domain_suffix =
      absl::StrCat(".", absl::StrJoin(trust_domain_pieces.begin() + 3,
                                      trust_domain_pieces.end(), "."));

  return matcher;
}

std::optional<AuthzConfiguration::SpiffeIdentityMatcher>
AuthzConfiguration::ParseSpiffeIdentityMatcher(const nlohmann::json& config) {
  const nlohmann::json* spiffe_id_matcher =
      GetValueAsJson(config, "spiffe_id_matcher");
  if (spiffe_id_matcher == nullptr) {
    return std::nullopt;
  }
  const std::string* trust_domain_suffix =
      GetValueAsString(*spiffe_id_matcher, "trust_domain_suffix");
  if (trust_domain_suffix == nullptr) {
    LOG(WARNING) << "Warning: trust_domain_suffix isn't a string; "
                 << "|spiffe_id_matcher|=" << spiffe_id_matcher->dump(2);
    return std::nullopt;
  }

  AuthzConfiguration::SpiffeIdentityMatcher matcher;
  matcher.spiffe_id_matcher.trust_domain_suffix =
      absl::AsciiStrToLower(*trust_domain_suffix);

  const std::string* path = GetValueAsString(*spiffe_id_matcher, "path");
  if (path == nullptr) {
    return std::nullopt;
  }
  matcher.spiffe_id_matcher.path = absl::AsciiStrToLower(*path);

  const std::string* ca_context =
      GetValueAsString(*spiffe_id_matcher, "ca_context");
  if (ca_context == nullptr) {
    return std::nullopt;
  }
  matcher.spiffe_id_matcher.ca_context = absl::AsciiStrToLower(*ca_context);

  const std::string* issuer = GetValueAsString(*spiffe_id_matcher, "issuer");
  if (issuer != nullptr) {
    matcher.spiffe_id_matcher.issuer = absl::AsciiStrToLower(*issuer);
  }

  // If realm_check is enabled, get current realm from GMI
  const bool* realm_check = GetValueAsBool(*spiffe_id_matcher, "realm_check");
  if (realm_check != nullptr && *realm_check) {
    matcher.spiffe_id_matcher.realm = GetNodeRealm();
  }

  const std::string* fqdn = GetValueAsString(config, "fqdn");
  // Non-string value
  if (fqdn == nullptr && config.find("fqdn") != config.end()) {
    return std::nullopt;
  }

  if (fqdn != nullptr) {
    matcher.fqdn = *fqdn;
  }

  return matcher;
}

bool AuthzConfiguration::IsResourceOwnerExisting(
    const ResourceOwner& resource_owner) const {
  absl::MutexLock lock(mutex_);
  return std::binary_search(resource_owners_.begin(), resource_owners_.end(),
                            resource_owner);
}

bool AuthzConfiguration::IsPeerResourceOwner(
    const PeerSpiffeIdentity& peer) const {
  std::optional<SpiffeIdentityMatcher> peer_matcher =
      CreateIdentityMatcherFromPeerSpiffeIdentity(peer);

  if (peer_matcher == std::nullopt) {
    LOG(WARNING) << "Peer spiffe id" << peer.spiffe_id << "is malformed";
    return false;
  }
  ResourceOwner peer_to_resource_owner{.identity_matcher = *peer_matcher};

  return IsResourceOwnerExisting(peer_to_resource_owner);
}

absl::StatusOr<std::string> AuthzConfiguration::GetRedfishRoleOfSpiffeMatcher(
    const SpiffeUser& spiffe_user) const {
  absl::MutexLock lock(mutex_);

  auto it =
      std::lower_bound(spiffe_users_.begin(), spiffe_users_.end(), spiffe_user);
  // Comparing equality
  if (it == spiffe_users_.end() || *it != spiffe_user) {
    return absl::NotFoundError(
        absl::StrCat("No user with matching spiffe; spiffe_user is ",
                     spiffe_user.identity_matcher.DebugString()));
  }

  return it->redfish_role;
}

std::string AuthzConfiguration::GetPeerRedfishRole(
    const PeerSpiffeIdentity& peer) const {
  std::optional<SpiffeIdentityMatcher> peer_matcher =
      CreateIdentityMatcherFromPeerSpiffeIdentity(peer);
  if (peer_matcher == std::nullopt) {
    LOG(WARNING) << "Peer spiffe id" << peer.spiffe_id << "is malformed";
    return "";
  }

  SpiffeUser peer_to_spiffe_user{.identity_matcher = *peer_matcher,
                                 .redfish_role = ""};

  absl::StatusOr<std::string> role =
      GetRedfishRoleOfSpiffeMatcher(peer_to_spiffe_user);

  if (!role.ok()) {
    LOG(WARNING) << role.status();
    return "";
  }

  return *role;
}

uint64_t AuthzConfiguration::GetSampleRateLimit(
    const std::string& peer_role) const {
  absl::MutexLock lock(mutex_);
  auto it = role_to_sample_rate_limit_.find(peer_role);
  if (it != role_to_sample_rate_limit_.end()) {
    return it->second;
  }
  return 0;
}

std::string AuthzConfiguration::GetAnycastAddress(
    const std::string& peer_role) const {
  absl::MutexLock lock(mutex_);
  auto it = role_to_anycast_address_.find(peer_role);
  if (it != role_to_anycast_address_.end()) {
    return it->second;
  }
  return "";
}

std::unordered_set<std::string> AuthzConfiguration::GetPeerRedfishPrivileges(
    const PeerSpiffeIdentity& peer) const {
  std::optional<SpiffeIdentityMatcher> peer_matcher =
      CreateIdentityMatcherFromPeerSpiffeIdentity(peer);

  if (peer_matcher == std::nullopt) {
    LOG(WARNING) << "Peer spiffe id" << peer.spiffe_id << "is malformed";
    return {"NoAuth"};
  }

  SpiffeUser peer_to_spiffe_user{.identity_matcher = *peer_matcher,
                                 .redfish_role = ""};

  absl::StatusOr<std::string> role =
      GetRedfishRoleOfSpiffeMatcher(peer_to_spiffe_user);

  if (!role.ok()) {
    LOG(WARNING) << role.status();
    return {"NoAuth"};
  }

  return GetRedfishPrivileges(*role);
}

std::unordered_set<std::string> AuthzConfiguration::GetPeerRedfishPrivileges(
    const PeerLoasIdentity& peer) const {
  std::optional<std::string> role = GetRoleByUsername(peer.username);
  if (role) {
    return GetRedfishPrivileges(*role);
  }
  role = GetRoleByGroup(peer.username);
  if (role) {
    return GetRedfishPrivileges(*role);
  }
  return {"NoAuth"};
}

absl::string_view AuthzConfiguration::GetCertNodeOwner(
    absl::string_view node_owner) const {
  if (IsHwopsState()) {
    return kHwopsRole;
  }
  return node_owner;
}

std::vector<AuthzConfiguration::SpiffeIdentityMatcher>
AuthzConfiguration::ParseSpiffeIdentityMatchersUsingOne(
    const nlohmann::json& config) const {
  const std::string* entity = GetValueAsString(config, "entity");
  if (entity == nullptr) {
    return {};
  }

  AuthorizedEntity entity_enum;
  if (!AuthorizedEntity_Parse(*entity, &entity_enum)) {
    LOG(WARNING) << "Warning: entity " << *entity
                 << " is not a valid AuthorizedEntity";
    return {};
  };
  std::vector<AuthzConfiguration::SpiffeIdentityMatcher> matchers;

  for (const std::string& entity_tag :
       GetAllEntityTagsFromAuthorizedEntity(entity_enum)) {
    AuthzConfiguration::SpiffeIdentityMatcher matcher;
    absl::StatusOr<AuthzConfiguration::EntityTagIdentity> entity_tag_identity =
        GetEntityTagIdentity(entity_tag);
    if (!entity_tag_identity.ok()) {
      continue;
    }
    matcher.fqdn =
        absl::StrCat(entity_tag_identity->hostname, ".prod.google.com");

    matcher.spiffe_id_matcher.trust_domain_suffix = ".prod.google.com";
    matcher.spiffe_id_matcher.ca_context =
        CertificateMetadataParser::kCaContextNode;

    matcher.spiffe_id_matcher.path =
        absl::StrCat("/role/", GetCertNodeOwner(entity_tag_identity->owner));

    matchers.push_back(std::move(matcher));
  }

  return matchers;
}

void AuthzConfiguration::ReloadSampleRateLimit(const nlohmann::json& config) {
  if (config.is_discarded()) {
    return;
  }
  const nlohmann::json::array_t* role_sample_rate_limits =
      GetValueAsArray(config, "role_sample_rate_limits");
  if (role_sample_rate_limits == nullptr) {
    return;
  }
  std::unordered_map<std::string, std::string> new_role_to_anycast_address;
  std::unordered_map<std::string, uint64_t> new_role_to_sample_rate_limit;
  for (const nlohmann::json& role_sample_rate_limit :
       *role_sample_rate_limits) {
    const std::string* role =
        GetValueAsString(role_sample_rate_limit, "redfish_role");
    if (role == nullptr) {
      continue;
    }
    const uint64_t* sample_rate_limit =
        GetValueAsUint(role_sample_rate_limit, "sample_rate_limit");
    if (sample_rate_limit == nullptr) {
      continue;
    }
    const std::string* anycast_address =
        GetValueAsString(role_sample_rate_limit, "anycast_address");
    if (anycast_address != nullptr) {
      new_role_to_anycast_address[*role] = *anycast_address;
    }
    new_role_to_sample_rate_limit[*role] = *sample_rate_limit;
  }
  absl::MutexLock lock(mutex_);
  role_to_sample_rate_limit_ = std::move(new_role_to_sample_rate_limit);
  role_to_anycast_address_ = std::move(new_role_to_anycast_address);
}

void AuthzConfiguration::ReloadResourceOwners(const nlohmann::json& config) {
  if (config.is_discarded()) {
    return;
  }
  const nlohmann::json::array_t* resource_owners =
      GetValueAsArray(config, "resource_owners");
  if (resource_owners == nullptr) {
    return;
  }
  std::vector<ResourceOwner> new_resource_owners;
  for (const nlohmann::json& resource_owner : *resource_owners) {
    // If the spiffe matcher is explicitly defined, parse it.
    if (resource_owner.contains("spiffe_id_matcher")) {
      ResourceOwner owner;
      std::optional<SpiffeIdentityMatcher> matcher =
          ParseSpiffeIdentityMatcher(resource_owner);
      if (matcher) {
        owner.identity_matcher = *matcher;
        new_resource_owners.push_back(std::move(owner));
      }
      continue;
    }
    // Otherwise continue with entity based parsing
    std::vector<SpiffeIdentityMatcher> matchers =
        ParseSpiffeIdentityMatchersUsingOne(resource_owner);
    for (const SpiffeIdentityMatcher& matcher : matchers) {
      ResourceOwner owner;
      owner.identity_matcher = matcher;
      new_resource_owners.push_back(std::move(owner));
    }
  }

  std::sort(new_resource_owners.begin(), new_resource_owners.end());
  new_resource_owners.erase(
      std::unique(new_resource_owners.begin(), new_resource_owners.end()),
      new_resource_owners.end());

  absl::MutexLock lock(mutex_);
  resource_owners_ = std::move(new_resource_owners);
}

void AuthzConfiguration::AddRedfishUsersInfoFromConfig(
    const nlohmann::json& config, std::vector<SpiffeUser>& spiffe_users,
    std::unordered_map<std::string, std::string>& username_to_role,
    std::unordered_map<std::string, std::string>& group_to_role) {
  if (config.is_discarded()) {
    return;
  }
  const nlohmann::json::array_t* exchange_mappings =
      GetValueAsArray(config, "exchange_mappings");
  if (exchange_mappings == nullptr) {
    return;
  }

  for (const nlohmann::json& exchange_mapping : *exchange_mappings) {
    const std::string* redfish_role =
        GetValueAsString(exchange_mapping, "redfish_role");
    if (redfish_role == nullptr) {
      continue;
    }
    // If peer is explicitly defined, then create exchange mapping with peer.
    if (exchange_mapping.contains("peer")) {
      const nlohmann::json* peer = GetValueAsJson(exchange_mapping, "peer");
      if (peer == nullptr) {
        continue;
      }
      // If it is username based, parse the username and continue
      const std::string* username = GetValueAsString(*peer, "username");
      if (username != nullptr) {
        username_to_role[*username] = *redfish_role;
        continue;
      }
      // If it is group based, parse the group and continue
      const std::string* group = GetValueAsString(*peer, "group");
      if (group != nullptr) {
        group_to_role[*group] = *redfish_role;
        continue;
      }
      // Otherwise, it is spiffe based
      SpiffeUser user;
      std::optional<SpiffeIdentityMatcher> matcher =
          ParseSpiffeIdentityMatcher(*peer);
      if (!matcher) {
        continue;
      }
      user.identity_matcher = *matcher;
      user.redfish_role = *redfish_role;
      spiffe_users.push_back(std::move(user));
      continue;
    }

    // Otherwise, continue with entity based parsing
    std::vector<SpiffeIdentityMatcher> matchers =
        ParseSpiffeIdentityMatchersUsingOne(exchange_mapping);
    for (const SpiffeIdentityMatcher& matcher : matchers) {
      SpiffeUser user;
      user.identity_matcher = matcher;
      user.redfish_role = *redfish_role;
      // TODO(edwarddl): This is n^2. We can make it linear with refactoring of
      // vector into hashmap. Do profiling and benchmarking to see if this would
      // lead to better performance.

      // Update the redfish_role of the matcher if
      //  the user already exists.
      auto it = std::find(spiffe_users.begin(), spiffe_users.end(), user);
      if (it != spiffe_users.end()) {
        it->redfish_role = *redfish_role;
        continue;
      }

      // Add the user to the list if they aren't there
      spiffe_users.push_back(std::move(user));
    }
  }
}

void AuthzConfiguration::ReloadRedfishUsers(
    const nlohmann::json& config, const nlohmann::json& platform_config) {
  if (config.is_discarded()) {
    return;
  }

  std::vector<SpiffeUser> new_spiffe_users;
  std::unordered_map<std::string, std::string> new_username_to_role;
  std::unordered_map<std::string, std::string> new_group_to_role;

  AddRedfishUsersInfoFromConfig(config, new_spiffe_users, new_username_to_role,
                                new_group_to_role);
  AddRedfishUsersInfoFromConfig(platform_config, new_spiffe_users,
                                new_username_to_role, new_group_to_role);

  std::sort(new_spiffe_users.begin(), new_spiffe_users.end());

  absl::MutexLock lock(mutex_);
  spiffe_users_ = std::move(new_spiffe_users);
  username_to_role_ = std::move(new_username_to_role);
  group_to_role_ = std::move(new_group_to_role);
}

static void AddRoleToPrivilegesToMap(
    const nlohmann::json& role_privileges,
    std::unordered_map<std::string, std::unordered_set<std::string>>&
        role_to_privileges) {
  if (role_privileges.is_discarded()) {
    return;
  }

  for (const nlohmann::json& role_privilege : role_privileges) {
    const std::string* role = GetValueAsString(role_privilege, "redfish_role");
    if (role == nullptr) {
      continue;
    }
    const nlohmann::json* privileges =
        GetValueAsJson(role_privilege, "privileges");
    if (privileges == nullptr) {
      continue;
    }
    std::unordered_set<std::string> privileges_set;
    const nlohmann::json::array_t* base_privileges =
        GetValueAsArray(*privileges, "base_privileges");
    if (base_privileges != nullptr) {
      for (const nlohmann::json& privilege : *base_privileges) {
        const std::string* privilege_str =
            privilege.get_ptr<const std::string*>();
        if (privilege_str == nullptr) {
          continue;
        }
        privileges_set.insert(*privilege_str);
      }
    }
    const nlohmann::json::array_t* oem_privileges =
        GetValueAsArray(*privileges, "oem_privileges");
    if (oem_privileges != nullptr) {
      for (const nlohmann::json& privilege : *oem_privileges) {
        const std::string* privilege_str =
            privilege.get_ptr<const std::string*>();
        if (privilege_str == nullptr) {
          continue;
        }
        privileges_set.insert(*privilege_str);
      }
    }

    privileges_set.insert("NoAuth");
    role_to_privileges[*role] = std::move(privileges_set);
  }
}

void AuthzConfiguration::ReloadRoleToPrivileges(
    const nlohmann::json& config, const nlohmann::json& platform_config) {
  if (config.is_discarded()) {
    return;
  }
  const nlohmann::json::array_t* role_privileges =
      GetValueAsArray(config, "role_privileges_mappings");
  std::unordered_map<std::string, std::unordered_set<std::string>>
      new_role_to_privileges;
  if (role_privileges != nullptr) {
    AddRoleToPrivilegesToMap(*role_privileges, new_role_to_privileges);
  }

  const nlohmann::json::array_t* platform_role_privileges =
      GetValueAsArray(platform_config, "role_privileges_mappings");
  if (platform_role_privileges != nullptr) {
    AddRoleToPrivilegesToMap(*platform_role_privileges, new_role_to_privileges);
  }

  absl::MutexLock lock(mutex_);
  role_to_privileges_ = std::move(new_role_to_privileges);
}

void AuthzConfiguration::ReloadOfflineNodeEntities() {
  if (offline_node_entities_path_.empty()) {
    return;
  }

  absl::StatusOr<OfflineNodeEntityInformation> parsed_offline_node_entities =
      ReadOfflineNodeEntityInformation(offline_node_entities_path_);

  if (!parsed_offline_node_entities.ok()) {
    LOG(WARNING) << "Could not read offline node entities information from "
                 << offline_node_entities_path_ << ": "
                 << parsed_offline_node_entities.status().message();
    return;
  }

  absl::MutexLock lock(mutex_);
  offline_node_entities_ = std::move(*parsed_offline_node_entities);
}

void AuthzConfiguration::ReloadGmi() {
  if (gmi_path_.empty()) {
    return;
  }

  std::ifstream gmi_file(gmi_path_);
  if (!gmi_file.is_open()) {
    LOG(ERROR) << "GMI file at '" << gmi_path_ << "' is missing.";
    return;
  }
  GoogleMachineIdentityProto gmi;
  if (!gmi.ParseFromIstream(&gmi_file)) {
    LOG(ERROR) << "GMI parsing failed at '" << gmi_path_ << "'";
    return;
  }

  absl::MutexLock lock(mutex_);
  gmi_ = std::move(gmi);
}

void AuthzConfiguration::ReloadConfig(const nlohmann::json& config,
                                      const nlohmann::json& platform_config) {
  if (config.is_discarded()) {
    LOG(WARNING) << "Warning: config isn't a valid JSON";
    return;
  }

  ReloadGmi();
  ReloadOfflineNodeEntities();
  ReloadResourceOwners(config);
  ReloadRedfishUsers(config, platform_config);
  ReloadRoleToPrivileges(config, platform_config);
  ReloadSampleRateLimit(config);

  absl::MutexLock lock(mutex_);
  config_ = config;
}

std::unordered_set<std::string> AuthzConfiguration::GetOemPrivileges() const {
  std::unordered_set<std::string> privileges;

  absl::MutexLock lock(mutex_);
  for (const auto& [role, privilege_set] : role_to_privileges_) {
    for (const std::string& privilege : privilege_set) {
      // If the privilege is not a default redfish privilege, it is OEM.
      if (!std::binary_search(kDefaultRedfishPrivileges.begin(),
                              kDefaultRedfishPrivileges.end(), privilege)) {
        privileges.insert(privilege);
      }
    }
  }

  return privileges;
}

absl::StatusOr<EntityTagIdentity> AuthzConfiguration::GetEntityTagIdentity(
    absl::string_view entity_tag) const {
  absl::MutexLock lock(mutex_);
  auto it =
      offline_node_entities_.resolved_config().entities().find(entity_tag);
  if (it == offline_node_entities_.resolved_config().entities().end()) {
    return absl::NotFoundError("Entity Tag Not Found");
  }
  return EntityTagIdentity{.hostname = it->second.hostname(),
                           .owner = it->second.owner()};
}

std::string AuthzConfiguration::GetMachineManagerEntityTag() const {
  absl::MutexLock lock(mutex_);
  return offline_node_entities_.resolved_config()
      .ecclesia_machine_manager_entity();
}

std::vector<std::string> AuthzConfiguration::GetAllComputeNodeEntityTags()
    const {
  std::vector<std::string> entity_tags;
  absl::MutexLock lock(mutex_);
  for (const auto& [entity_tag, entity] :
       offline_node_entities_.resolved_config().entities()) {
    if (entity.node_type_info().is_compute()) {
      entity_tags.push_back(entity_tag);
    }
  }

  return entity_tags;
}

std::vector<std::string> AuthzConfiguration::GetAllOffloadNodeEntityTags()
    const {
  std::vector<std::string> entity_tags;
  absl::MutexLock lock(mutex_);
  for (const auto& [entity_tag, entity] :
       offline_node_entities_.resolved_config().entities()) {
    if (entity.node_type_info().is_offload()) {
      entity_tags.push_back(entity_tag);
    }
  }

  return entity_tags;
}

std::vector<std::string> AuthzConfiguration::GetEntityTagsFromRedfishSystemId(
    absl::string_view system_id) const {
  std::vector<std::string> entity_tags;
  absl::MutexLock lock(mutex_);
  for (const auto& [entity_tag, entity] :
       offline_node_entities_.resolved_config().entities()) {
    if (entity.redfish_system_id() == system_id) {
      entity_tags.push_back(entity_tag);
    }
  }

  return entity_tags;
}

std::vector<std::string>
AuthzConfiguration::GetAllEntityTagsFromAuthorizedEntity(
    AuthorizedEntity entity) const {
  switch (entity) {
    case AuthorizedEntity::ComputeNode:
      return GetAllComputeNodeEntityTags();
    case AuthorizedEntity::ComputeNode1:
      return GetEntityTagsFromRedfishSystemId("system1");
    case AuthorizedEntity::ComputeNode2:
      return GetEntityTagsFromRedfishSystemId("system2");
    case AuthorizedEntity::OffloadNodes:
      return GetAllOffloadNodeEntityTags();
    case AuthorizedEntity::EcclesiaMachineManagerEntity:
      return {GetMachineManagerEntityTag()};
    case AuthorizedEntity::Undefined:
      return {};
    case AuthorizedEntity_INT_MIN_SENTINEL_DO_NOT_USE_:
    case AuthorizedEntity_INT_MAX_SENTINEL_DO_NOT_USE_:
      return {};
  }
  return {};
}

bool AuthzConfiguration::IsHwopsState() const {
  absl::MutexLock lock(mutex_);
  if (gmi_.has_in_hwops_state()) {
    return gmi_.in_hwops_state();
  }
  return false;
}

std::string AuthzConfiguration::GetNodeRealm() const {
  absl::MutexLock lock(mutex_);
  // GMI only supports 1 realm
  if (gmi_.security_realms_size() != 1) {
    LOG(ERROR) << "Machine GMI's realm is broken. All realm specific Borg jobs "
                  "will be denied.";
    return "";
  }
  return gmi_.security_realms(0);
}

}  // namespace milotic::authz
