Add multiple license support (#618)

Make license info available through LicenseChecker
Add LicenseInfoSender
Move license library from utils
Rename telemetry_lib to mg-telemetry
This commit is contained in:
Jure Bajic 2022-11-04 15:23:43 +01:00 committed by GitHub
parent 2a2b99b02a
commit ff21c0705c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 834 additions and 364 deletions

View File

@ -15,6 +15,7 @@ add_subdirectory(query)
add_subdirectory(glue)
add_subdirectory(slk)
add_subdirectory(rpc)
add_subdirectory(license)
add_subdirectory(auth)
if(MG_ENTERPRISE)
@ -36,7 +37,8 @@ set(mg_single_node_v2_sources
)
set(mg_single_node_v2_libs stdc++fs Threads::Threads
telemetry_lib mg-query mg-communication mg-memory mg-utils mg-auth mg-license mg-settings mg-glue)
mg-telemetry mg-query mg-communication mg-memory mg-utils mg-auth mg-license mg-settings mg-glue)
if(MG_ENTERPRISE)
# These are enterprise subsystems
set(mg_single_node_v2_libs ${mg_single_node_v2_libs} mg-audit)
@ -46,20 +48,25 @@ endif()
add_executable(memgraph ${mg_single_node_v2_sources})
target_include_directories(memgraph PUBLIC ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(memgraph ${mg_single_node_v2_libs})
# NOTE: `include/mg_procedure.syms` describes a pattern match for symbols which
# should be dynamically exported, so that `dlopen` can correctly link the
# symbols in custom procedure module libraries.
target_link_libraries(memgraph "-Wl,--dynamic-list=${CMAKE_SOURCE_DIR}/include/mg_procedure.syms")
set_target_properties(memgraph PROPERTIES
# Set the executable output name to include version information.
OUTPUT_NAME "memgraph-${MEMGRAPH_VERSION}_${CMAKE_BUILD_TYPE}"
# Output the executable in main binary dir.
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# Create symlink to the built executable.
add_custom_command(TARGET memgraph POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:memgraph> ${CMAKE_BINARY_DIR}/memgraph
BYPRODUCTS ${CMAKE_BINARY_DIR}/memgraph
COMMENT "Creating symlink to memgraph executable")
# Emulate the installed python_support, by creating a symlink
add_custom_command(TARGET memgraph POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/python_support
@ -95,9 +102,11 @@ set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "memgraph")
# we cannot use the recommended `install(TARGETS ...)`.
install(PROGRAMS $<TARGET_FILE:memgraph>
DESTINATION lib/memgraph RENAME memgraph)
# Install Python source for supporting our embedded Python.
install(FILES ${CMAKE_SOURCE_DIR}/include/mgp.py
DESTINATION lib/memgraph/python_support)
# Install the includes file for writing custom procedures in C and C++>
install(FILES ${CMAKE_SOURCE_DIR}/include/mg_procedure.h
DESTINATION include/memgraph)
@ -107,9 +116,11 @@ install(FILES ${CMAKE_SOURCE_DIR}/include/mg_exceptions.hpp
DESTINATION include/memgraph)
install(FILES ${CMAKE_SOURCE_DIR}/include/mgp.hpp
DESTINATION include/memgraph)
# Install the config file (must use absolute path).
install(FILES ${CMAKE_BINARY_DIR}/config/memgraph.conf
DESTINATION /etc/memgraph RENAME memgraph.conf)
# Install logrotate configuration (must use absolute path).
install(FILES ${CMAKE_SOURCE_DIR}/release/logrotate.conf
DESTINATION /etc/logrotate.d RENAME memgraph)
@ -125,7 +136,6 @@ install(CODE "file(MAKE_DIRECTORY \$ENV{DESTDIR}/var/log/memgraph
# ----------------------------------------------------------------------------
# Memgraph CSV Import Tool Executable
# ----------------------------------------------------------------------------
add_executable(mg_import_csv mg_import_csv.cpp)
target_link_libraries(mg_import_csv mg-storage-v2)

View File

@ -16,8 +16,8 @@
#include <fmt/format.h>
#include "auth/exceptions.hpp"
#include "license/license.hpp"
#include "utils/flag_validation.hpp"
#include "utils/license.hpp"
#include "utils/logging.hpp"
#include "utils/message.hpp"
#include "utils/settings.hpp"
@ -68,10 +68,9 @@ Auth::Auth(const std::string &storage_directory) : storage_(storage_directory),
std::optional<User> Auth::Authenticate(const std::string &username, const std::string &password) {
if (module_.IsUsed()) {
const auto license_check_result = utils::license::global_license_checker.IsValidLicense(utils::global_settings);
const auto license_check_result = license::global_license_checker.IsEnterpriseValid(utils::global_settings);
if (license_check_result.HasError()) {
spdlog::warn(
utils::license::LicenseCheckErrorToString(license_check_result.GetError(), "authentication modules"));
spdlog::warn(license::LicenseCheckErrorToString(license_check_result.GetError(), "authentication modules"));
return std::nullopt;
}

View File

@ -15,8 +15,8 @@
#include "auth/crypto.hpp"
#include "auth/exceptions.hpp"
#include "license/license.hpp"
#include "utils/cast.hpp"
#include "utils/license.hpp"
#include "utils/logging.hpp"
#include "utils/settings.hpp"
#include "utils/string.hpp"
@ -242,7 +242,7 @@ FineGrainedAccessPermissions::FineGrainedAccessPermissions(const std::unordered_
PermissionLevel FineGrainedAccessPermissions::Has(const std::string &permission,
const FineGrainedPermission fine_grained_permission) const {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return PermissionLevel::GRANT;
}
const auto concrete_permission = std::invoke([&]() -> uint64_t {
@ -281,7 +281,7 @@ void FineGrainedAccessPermissions::Revoke(const std::string &permission) {
}
nlohmann::json FineGrainedAccessPermissions::Serialize() const {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return {};
}
nlohmann::json data = nlohmann::json::object();
@ -294,7 +294,7 @@ FineGrainedAccessPermissions FineGrainedAccessPermissions::Deserialize(const nlo
if (!data.is_object()) {
throw AuthException("Couldn't load permissions data!");
}
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return FineGrainedAccessPermissions{};
}
std::optional<uint64_t> global_permission;
@ -347,7 +347,7 @@ const FineGrainedAccessPermissions &FineGrainedAccessHandler::edge_type_permissi
FineGrainedAccessPermissions &FineGrainedAccessHandler::edge_type_permissions() { return edge_type_permissions_; }
nlohmann::json FineGrainedAccessHandler::Serialize() const {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return {};
}
nlohmann::json data = nlohmann::json::object();
@ -363,7 +363,7 @@ FineGrainedAccessHandler FineGrainedAccessHandler::Deserialize(const nlohmann::j
if (!data["label_permissions"].is_object() || !data["edge_type_permissions"].is_object()) {
throw AuthException("Couldn't load label_permissions or edge_type_permissions data!");
}
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return FineGrainedAccessHandler{};
}
auto label_permissions = FineGrainedAccessPermissions::Deserialize(data["label_permissions"]);
@ -414,7 +414,7 @@ nlohmann::json Role::Serialize() const {
data["rolename"] = rolename_;
data["permissions"] = permissions_.Serialize();
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize();
} else {
data["fine_grained_access_handler"] = {};
@ -432,7 +432,7 @@ Role Role::Deserialize(const nlohmann::json &data) {
}
auto permissions = Permissions::Deserialize(data["permissions"]);
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
if (!data["fine_grained_access_handler"].is_object()) {
throw AuthException("Couldn't load user data!");
}
@ -445,7 +445,7 @@ Role Role::Deserialize(const nlohmann::json &data) {
bool operator==(const Role &first, const Role &second) {
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_ &&
first.fine_grained_access_handler_ == second.fine_grained_access_handler_;
}
@ -483,13 +483,13 @@ void User::UpdatePassword(const std::optional<std::string> &password) {
}
if (FLAGS_auth_password_strength_regex != default_password_regex) {
if (const auto license_check_result = utils::license::global_license_checker.IsValidLicense(utils::global_settings);
if (const auto license_check_result = license::global_license_checker.IsEnterpriseValid(utils::global_settings);
license_check_result.HasError()) {
throw AuthException(
"Custom password regex is a Memgraph Enterprise feature. Please set the config "
"(\"--auth-password-strength-regex\") to its default value (\"{}\") or remove the flag.\n{}",
default_password_regex,
utils::license::LicenseCheckErrorToString(license_check_result.GetError(), "password regex"));
license::LicenseCheckErrorToString(license_check_result.GetError(), "password regex"));
}
}
std::regex re(FLAGS_auth_password_strength_regex);
@ -517,7 +517,7 @@ Permissions User::GetPermissions() const {
#ifdef MG_ENTERPRISE
FineGrainedAccessPermissions User::GetFineGrainedAccessLabelPermissions() const {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return FineGrainedAccessPermissions{};
}
@ -530,7 +530,7 @@ FineGrainedAccessPermissions User::GetFineGrainedAccessLabelPermissions() const
}
FineGrainedAccessPermissions User::GetFineGrainedAccessEdgeTypePermissions() const {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return FineGrainedAccessPermissions{};
}
if (role_) {
@ -563,7 +563,7 @@ nlohmann::json User::Serialize() const {
data["password_hash"] = password_hash_;
data["permissions"] = permissions_.Serialize();
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize();
} else {
data["fine_grained_access_handler"] = {};
@ -582,7 +582,7 @@ User User::Deserialize(const nlohmann::json &data) {
}
auto permissions = Permissions::Deserialize(data["permissions"]);
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
if (!data["fine_grained_access_handler"].is_object()) {
throw AuthException("Couldn't load user data!");
}
@ -595,7 +595,7 @@ User User::Deserialize(const nlohmann::json &data) {
bool operator==(const User &first, const User &second) {
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return first.username_ == second.username_ && first.password_hash_ == second.password_hash_ &&
first.permissions_ == second.permissions_ && first.role_ == second.role_ &&
first.fine_grained_access_handler_ == second.fine_grained_access_handler_;

View File

@ -14,8 +14,8 @@
#include "auth/auth.hpp"
#include "auth/models.hpp"
#include "glue/auth.hpp"
#include "license/license.hpp"
#include "query/frontend/ast/ast.hpp"
#include "utils/license.hpp"
#include "utils/synchronized.hpp"
#ifdef MG_ENTERPRISE
@ -23,7 +23,7 @@ namespace {
bool IsUserAuthorizedLabels(const memgraph::auth::User &user, const memgraph::query::DbAccessor *dba,
const std::vector<memgraph::storage::LabelId> &labels,
const memgraph::query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return true;
}
return std::all_of(labels.begin(), labels.end(), [dba, &user, fine_grained_privilege](const auto &label) {
@ -35,7 +35,7 @@ bool IsUserAuthorizedLabels(const memgraph::auth::User &user, const memgraph::qu
bool IsUserAuthorizedGloballyLabels(const memgraph::auth::User &user,
const memgraph::auth::FineGrainedPermission fine_grained_permission) {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return true;
}
return user.GetFineGrainedAccessLabelPermissions().Has(memgraph::auth::kAsterisk, fine_grained_permission) ==
@ -44,7 +44,7 @@ bool IsUserAuthorizedGloballyLabels(const memgraph::auth::User &user,
bool IsUserAuthorizedGloballyEdges(const memgraph::auth::User &user,
const memgraph::auth::FineGrainedPermission fine_grained_permission) {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return true;
}
return user.GetFineGrainedAccessEdgeTypePermissions().Has(memgraph::auth::kAsterisk, fine_grained_permission) ==
@ -54,7 +54,7 @@ bool IsUserAuthorizedGloballyEdges(const memgraph::auth::User &user,
bool IsUserAuthorizedEdgeType(const memgraph::auth::User &user, const memgraph::query::DbAccessor *dba,
const memgraph::storage::EdgeTypeId &edgeType,
const memgraph::query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return true;
}
return user.GetFineGrainedAccessEdgeTypePermissions().Has(
@ -87,7 +87,7 @@ bool AuthChecker::IsUserAuthorized(const std::optional<std::string> &username,
#ifdef MG_ENTERPRISE
std::unique_ptr<memgraph::query::FineGrainedAuthChecker> AuthChecker::GetFineGrainedAuthChecker(
const std::string &username, const memgraph::query::DbAccessor *dba) const {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return {};
}
try {
@ -154,7 +154,7 @@ bool FineGrainedAuthChecker::Has(const memgraph::storage::EdgeTypeId &edge_type,
bool FineGrainedAuthChecker::HasGlobalPrivilegeOnVertices(
const memgraph::query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) const {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return true;
}
return IsUserAuthorizedGloballyLabels(user_, FineGrainedPrivilegeToFineGrainedPermission(fine_grained_privilege));
@ -162,7 +162,7 @@ bool FineGrainedAuthChecker::HasGlobalPrivilegeOnVertices(
bool FineGrainedAuthChecker::HasGlobalPrivilegeOnEdges(
const memgraph::query::AuthQuery::FineGrainedPrivilege fine_grained_privilege) const {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return true;
}
return IsUserAuthorizedGloballyEdges(user_, FineGrainedPrivilegeToFineGrainedPermission(fine_grained_privilege));

View File

@ -17,7 +17,7 @@
#include "auth/models.hpp"
#include "glue/auth.hpp"
#include "utils/license.hpp"
#include "license/license.hpp"
namespace {
@ -125,7 +125,7 @@ std::vector<FineGrainedPermissionForPrivilegeResult> GetFineGrainedPermissionFor
const memgraph::auth::FineGrainedAccessPermissions &permissions, const std::string &permission_type,
const std::string &user_or_role) {
std::vector<FineGrainedPermissionForPrivilegeResult> fine_grained_permissions;
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return fine_grained_permissions;
}
const auto global_permission = permissions.GetGlobalPermission();
@ -166,7 +166,7 @@ std::vector<FineGrainedPermissionForPrivilegeResult> GetFineGrainedPermissionFor
std::vector<std::vector<memgraph::query::TypedValue>> ConstructFineGrainedPrivilegesResult(
const std::vector<FineGrainedPermissionForPrivilegeResult> &privileges) {
std::vector<std::vector<memgraph::query::TypedValue>> grants;
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return {};
}
grants.reserve(privileges.size());
@ -182,7 +182,7 @@ std::vector<std::vector<memgraph::query::TypedValue>> ConstructFineGrainedPrivil
std::vector<std::vector<memgraph::query::TypedValue>> ShowFineGrainedUserPrivileges(
const std::optional<memgraph::auth::User> &user) {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return {};
}
const auto &label_permissions = user->GetFineGrainedAccessLabelPermissions();
@ -201,7 +201,7 @@ std::vector<std::vector<memgraph::query::TypedValue>> ShowFineGrainedUserPrivile
std::vector<std::vector<memgraph::query::TypedValue>> ShowFineGrainedRolePrivileges(
const std::optional<memgraph::auth::Role> &role) {
if (!memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (!memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
return {};
}
const auto &label_permissions = role->GetFineGrainedAccessLabelPermissions();
@ -231,13 +231,13 @@ AuthQueryHandler::AuthQueryHandler(
bool AuthQueryHandler::CreateUser(const std::string &username, const std::optional<std::string> &password) {
if (name_regex_string_ != kDefaultUserRoleRegex) {
if (const auto license_check_result =
memgraph::utils::license::global_license_checker.IsValidLicense(memgraph::utils::global_settings);
memgraph::license::global_license_checker.IsEnterpriseValid(memgraph::utils::global_settings);
license_check_result.HasError()) {
throw memgraph::auth::AuthException(
"Custom user/role regex is a Memgraph Enterprise feature. Please set the config "
"(\"--auth-user-or-role-name-regex\") to its default value (\"{}\") or remove the flag.\n{}",
kDefaultUserRoleRegex,
memgraph::utils::license::LicenseCheckErrorToString(license_check_result.GetError(), "user/role regex"));
memgraph::license::LicenseCheckErrorToString(license_check_result.GetError(), "user/role regex"));
}
}
if (!std::regex_match(username, name_regex_)) {
@ -473,20 +473,20 @@ std::vector<std::vector<memgraph::query::TypedValue>> AuthQueryHandler::GetPrivi
if (user) {
grants = ShowUserPrivileges(user);
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
fine_grained_grants = ShowFineGrainedUserPrivileges(user);
}
#endif
} else {
grants = ShowRolePrivileges(role);
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
fine_grained_grants = ShowFineGrainedRolePrivileges(role);
}
#endif
}
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
grants.insert(grants.end(), fine_grained_grants.begin(), fine_grained_grants.end());
}
#endif
@ -627,7 +627,7 @@ void AuthQueryHandler::EditPermissions(
edit_permissions_fun(user->permissions(), permission);
}
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
for (const auto &label_privilege_collection : label_privileges) {
edit_fine_grained_permissions_fun(user->fine_grained_access_handler().label_permissions(),
label_privilege_collection);
@ -644,7 +644,7 @@ void AuthQueryHandler::EditPermissions(
edit_permissions_fun(role->permissions(), permission);
}
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
for (const auto &label_privilege : label_privileges) {
edit_fine_grained_permissions_fun(role->fine_grained_access_handler().label_permissions(), label_privilege);
}

View File

@ -15,8 +15,8 @@
#include "auth/auth.hpp"
#include "glue/auth.hpp"
#include "license/license.hpp"
#include "query/interpreter.hpp"
#include "utils/license.hpp"
#include "utils/string.hpp"
namespace memgraph::glue {

View File

@ -0,0 +1,6 @@
set(license_src_files
license_sender.cpp
license.cpp)
add_library(mg-license STATIC ${license_src_files})
target_link_libraries(mg-license mg-settings mg-utils mg-requests spdlog::spdlog)

View File

@ -9,17 +9,19 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#include "utils/license.hpp"
#include "license/license.hpp"
#include <atomic>
#include <charconv>
#include <chrono>
#include <cstdint>
#include <functional>
#include <optional>
#include <unordered_map>
#include "slk/serialization.hpp"
#include "utils/base64.hpp"
#include "utils/cast.hpp"
#include "utils/exceptions.hpp"
#include "utils/logging.hpp"
#include "utils/memory_tracker.hpp"
@ -27,7 +29,7 @@
#include "utils/spin_lock.hpp"
#include "utils/synchronized.hpp"
namespace memgraph::utils::license {
namespace memgraph::license {
namespace {
inline constexpr std::string_view license_key_prefix = "mglk-";
@ -69,6 +71,17 @@ LicenseCheckResult IsValidLicenseInternal(const License &license, const std::str
}
} // namespace
std::string LicenseTypeToString(const LicenseType license_type) {
switch (license_type) {
case LicenseType::ENTERPRISE: {
return "enterprise";
}
case LicenseType::OEM: {
return "oem";
}
}
}
void RegisterLicenseSettings(LicenseChecker &license_checker, utils::Settings &settings) {
settings.RegisterSetting(std::string{kEnterpriseLicenseSettingKey}, "",
[&] { license_checker.RevalidateLicense(settings); });
@ -81,7 +94,7 @@ LicenseChecker global_license_checker;
LicenseChecker::~LicenseChecker() { scheduler_.Stop(); }
std::pair<std::string, std::string> LicenseChecker::GetLicenseInfo(const utils::Settings &settings) const {
std::pair<std::string, std::string> LicenseChecker::ExtractLicenseInfo(const utils::Settings &settings) const {
if (license_info_override_) {
spdlog::warn("Ignoring license info stored in the settings because a different source was specified.");
return *license_info_override_;
@ -96,7 +109,7 @@ std::pair<std::string, std::string> LicenseChecker::GetLicenseInfo(const utils::
}
void LicenseChecker::RevalidateLicense(const utils::Settings &settings) {
const auto license_info = GetLicenseInfo(settings);
const auto license_info = ExtractLicenseInfo(settings);
RevalidateLicense(license_info.first, license_info.second);
}
@ -117,18 +130,7 @@ void LicenseChecker::RevalidateLicense(const std::string &license_key, const std
return;
}
struct PreviousLicenseInfo {
PreviousLicenseInfo(std::string license_key, std::string organization_name)
: license_key(std::move(license_key)), organization_name(std::move(organization_name)) {}
std::string license_key;
std::string organization_name;
bool is_valid{false};
};
static utils::Synchronized<std::optional<PreviousLicenseInfo>, utils::SpinLock> previous_license_info;
auto locked_previous_license_info_ptr = previous_license_info.Lock();
auto locked_previous_license_info_ptr = previous_license_info_.Lock();
auto &locked_previous_license_info = *locked_previous_license_info_ptr;
const bool same_license_info = locked_previous_license_info &&
locked_previous_license_info->license_key == license_key &&
@ -140,7 +142,7 @@ void LicenseChecker::RevalidateLicense(const std::string &license_key, const std
locked_previous_license_info.emplace(license_key, organization_name);
const auto maybe_license = GetLicense(locked_previous_license_info->license_key);
auto maybe_license = GetLicense(locked_previous_license_info->license_key);
if (!maybe_license) {
spdlog::warn(LicenseCheckErrorToString(LicenseCheckError::INVALID_LICENSE_KEY_STRING, "Enterprise features"));
is_valid_.store(false, std::memory_order_relaxed);
@ -156,22 +158,30 @@ void LicenseChecker::RevalidateLicense(const std::string &license_key, const std
spdlog::warn(LicenseCheckErrorToString(license_check_result.GetError(), "Enterprise features"));
is_valid_.store(false, std::memory_order_relaxed);
locked_previous_license_info->is_valid = false;
license_type_ = maybe_license->type;
set_memory_limit(0);
return;
}
if (!same_license_info) {
spdlog::info("All Enterprise features are active.");
license_type_ = maybe_license->type;
if (license_type_ == LicenseType::ENTERPRISE) {
spdlog::info("Enterprise license is active.");
} else {
spdlog::info("OEM license is active.");
}
is_valid_.store(true, std::memory_order_relaxed);
locked_previous_license_info->is_valid = true;
set_memory_limit(maybe_license->memory_limit);
locked_previous_license_info->license = std::move(*maybe_license);
}
}
void LicenseChecker::EnableTesting() {
void LicenseChecker::EnableTesting(const LicenseType license_type) {
enterprise_enabled_ = true;
is_valid_.store(true, std::memory_order_relaxed);
spdlog::info("All Enterprise features are activated for testing.");
license_type_ = license_type;
spdlog::info("The license type {} is set for testing.", LicenseTypeToString(license_type));
}
void LicenseChecker::CheckEnvLicense() {
@ -216,20 +226,26 @@ std::string LicenseCheckErrorToString(LicenseCheckError error, const std::string
"following query:\n"
"SET DATABASE SETTING \"enterprise.license\" TO \"your-license-key\"",
feature);
case LicenseCheckError::NOT_ENTERPRISE_LICENSE:
return fmt::format("Your license has an invalid type. To use {} you need to have an enterprise license. \n",
feature);
}
}
LicenseCheckResult LicenseChecker::IsValidLicense(const utils::Settings &settings) const {
LicenseCheckResult LicenseChecker::IsEnterpriseValid(const utils::Settings &settings) const {
if (enterprise_enabled_) [[unlikely]] {
return {};
}
const auto license_info = GetLicenseInfo(settings);
const auto license_info = ExtractLicenseInfo(settings);
const auto maybe_license = GetLicense(license_info.first);
if (!maybe_license) {
return LicenseCheckError::INVALID_LICENSE_KEY_STRING;
}
if (maybe_license->type != LicenseType::ENTERPRISE) {
return LicenseCheckError::NOT_ENTERPRISE_LICENSE;
}
return IsValidLicenseInternal(*maybe_license, license_info.second);
}
@ -239,7 +255,13 @@ void LicenseChecker::StartBackgroundLicenseChecker(const utils::Settings &settin
scheduler_.Run("licensechecker", std::chrono::minutes{5}, [&, this] { RevalidateLicense(settings); });
}
bool LicenseChecker::IsValidLicenseFast() const { return is_valid_.load(std::memory_order_relaxed); }
utils::Synchronized<std::optional<LicenseInfo>, utils::SpinLock> &LicenseChecker::GetLicenseInfo() {
return previous_license_info_;
}
bool LicenseChecker::IsEnterpriseValidFast() const {
return license_type_ == LicenseType::ENTERPRISE && is_valid_.load(std::memory_order_relaxed);
}
std::string Encode(const License &license) {
std::vector<uint8_t> buffer;
@ -252,9 +274,10 @@ std::string Encode(const License &license) {
slk::Save(license.organization_name, &builder);
slk::Save(license.valid_until, &builder);
slk::Save(license.memory_limit, &builder);
slk::Save(utils::UnderlyingCast(license.type), &builder);
builder.Finalize();
return std::string{license_key_prefix} + base64_encode(buffer.data(), buffer.size());
return std::string{license_key_prefix} + utils::base64_encode(buffer.data(), buffer.size());
}
std::optional<License> Decode(std::string_view license_key) {
@ -266,7 +289,7 @@ std::optional<License> Decode(std::string_view license_key) {
const auto decoded = std::invoke([license_key]() -> std::optional<std::string> {
try {
return base64_decode(license_key);
return utils::base64_decode(license_key);
} catch (const std::runtime_error & /*exception*/) {
return std::nullopt;
}
@ -284,10 +307,12 @@ std::optional<License> Decode(std::string_view license_key) {
slk::Load(&valid_until, &reader);
int64_t memory_limit{0};
slk::Load(&memory_limit, &reader);
return License{.organization_name = organization_name, .valid_until = valid_until, .memory_limit = memory_limit};
std::underlying_type_t<LicenseType> license_type{0};
slk::Load(&license_type, &reader);
return {License{organization_name, valid_until, memory_limit, LicenseType(license_type)}};
} catch (const slk::SlkReaderException &e) {
return std::nullopt;
}
}
} // namespace memgraph::utils::license
} // namespace memgraph::license

View File

@ -12,26 +12,57 @@
#pragma once
#include <cstdint>
#include <optional>
#include <string>
#include "utils/result.hpp"
#include "utils/scheduler.hpp"
#include "utils/settings.hpp"
#include "utils/spin_lock.hpp"
#include "utils/synchronized.hpp"
namespace memgraph::utils::license {
namespace memgraph::license {
enum class LicenseType : uint8_t { ENTERPRISE, OEM };
std::string LicenseTypeToString(LicenseType license_type);
struct License {
License() = default;
License(std::string organization_name, int64_t valid_until, int64_t memory_limit, LicenseType license_type)
: organization_name{std::move(organization_name)},
valid_until{valid_until},
memory_limit{memory_limit},
type{license_type} {}
std::string organization_name;
int64_t valid_until;
int64_t memory_limit;
LicenseType type;
bool operator==(const License &) const = default;
};
struct LicenseInfo {
LicenseInfo(std::string license_key, std::string organization_name)
: license_key(std::move(license_key)), organization_name{std::move(organization_name)} {}
std::string license_key;
std::string organization_name;
bool is_valid{false};
License license;
};
inline constexpr std::string_view kEnterpriseLicenseSettingKey = "enterprise.license";
inline constexpr std::string_view kOrganizationNameSettingKey = "organization.name";
enum class LicenseCheckError : uint8_t { INVALID_LICENSE_KEY_STRING, INVALID_ORGANIZATION_NAME, EXPIRED_LICENSE };
enum class LicenseCheckError : uint8_t {
INVALID_LICENSE_KEY_STRING,
INVALID_ORGANIZATION_NAME,
EXPIRED_LICENSE,
NOT_ENTERPRISE_LICENSE
};
std::string LicenseCheckErrorToString(LicenseCheckError error, std::string_view feature);
@ -49,19 +80,25 @@ struct LicenseChecker {
void CheckEnvLicense();
void SetLicenseInfoOverride(std::string license_key, std::string organization_name);
void EnableTesting();
LicenseCheckResult IsValidLicense(const utils::Settings &settings) const;
bool IsValidLicenseFast() const;
void EnableTesting(LicenseType license_type = LicenseType::ENTERPRISE);
// Checks if license is valid and if enterprise is enabled
LicenseCheckResult IsEnterpriseValid(const utils::Settings &settings) const;
bool IsEnterpriseValidFast() const;
void StartBackgroundLicenseChecker(const utils::Settings &settings);
utils::Synchronized<std::optional<LicenseInfo>, utils::SpinLock> &GetLicenseInfo();
private:
std::pair<std::string, std::string> GetLicenseInfo(const utils::Settings &settings) const;
std::pair<std::string, std::string> ExtractLicenseInfo(const utils::Settings &settings) const;
void RevalidateLicense(const utils::Settings &settings);
void RevalidateLicense(const std::string &license_key, const std::string &organization_name);
std::optional<std::pair<std::string, std::string>> license_info_override_;
utils::Synchronized<std::optional<LicenseInfo>, utils::SpinLock> previous_license_info_{std::nullopt};
bool enterprise_enabled_{false};
std::atomic<bool> is_valid_{false};
LicenseType license_type_;
utils::Scheduler scheduler_;
friend void RegisterLicenseSettings(LicenseChecker &license_checker, utils::Settings &settings);
@ -74,4 +111,4 @@ std::string Encode(const License &license);
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
extern LicenseChecker global_license_checker;
} // namespace memgraph::utils::license
} // namespace memgraph::license

View File

@ -0,0 +1,71 @@
// Copyright 2022 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#include "license/license_sender.hpp"
#include <spdlog/spdlog.h>
#include <cstdint>
#include "requests/requests.hpp"
#include "utils/memory_tracker.hpp"
#include "utils/stat.hpp"
#include "utils/synchronized.hpp"
#include "utils/system_info.hpp"
#include "utils/timestamp.hpp"
namespace memgraph::license {
LicenseInfoSender::LicenseInfoSender(std::string url, std::string uuid, std::string machine_id, int64_t memory_limit,
utils::Synchronized<std::optional<LicenseInfo>, utils::SpinLock> &license_info,
std::chrono::seconds request_frequency)
: url_{std::move(url)},
uuid_{std::move(uuid)},
machine_id_{std::move(machine_id)},
memory_limit_{memory_limit},
license_info_{license_info} {
scheduler_.Run("LicenseCheck", request_frequency, [&] { SendData(); });
}
LicenseInfoSender::~LicenseInfoSender() { scheduler_.Stop(); }
void LicenseInfoSender::SendData() {
nlohmann::json data = nlohmann::json::object();
license_info_.WithLock([&data, this](const auto &license_info) mutable {
if (license_info && !license_info->organization_name.empty()) {
const auto memory_info = utils::GetMemoryInfo();
const auto memory_usage = utils::GetMemoryUsage();
data = {{"run_id", uuid_},
{"machine_id", machine_id_},
{"type", "license-check"},
{"license_type", LicenseTypeToString(license_info->license.type)},
{"license_key", license_info->license_key},
{"organization", license_info->organization_name},
{"valid", license_info->is_valid},
{"physical_memory_size", memory_info.memory},
{"swap_memory_size", memory_info.swap},
{"memory_used", memory_usage},
{"runtime_memory_limit", memory_limit_},
{"license_memory_limit", license_info->license.memory_limit},
{"timestamp", utils::Timestamp::Now().SecWithNsecSinceTheEpoch()}};
}
});
if (data.empty()) {
return;
}
if (!requests::RequestPostJson(url_, data,
/* timeout_in_seconds = */ 2 * 60)) {
spdlog::trace("Cannot send license information, enable {} availability!", url_);
}
}
} // namespace memgraph::license

View File

@ -0,0 +1,50 @@
// Copyright 2022 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#pragma once
#include <chrono>
#include <cstdint>
#include <string>
#include <json/json.hpp>
#include "license/license.hpp"
#include "utils/scheduler.hpp"
#include "utils/timer.hpp"
namespace memgraph::license {
class LicenseInfoSender final {
public:
LicenseInfoSender(std::string url, std::string uuid, std::string machine_id, int64_t memory_limit,
utils::Synchronized<std::optional<LicenseInfo>, utils::SpinLock> &license_info,
std::chrono::seconds request_frequency = std::chrono::seconds(8 * 60 * 60));
LicenseInfoSender(const LicenseInfoSender &) = delete;
LicenseInfoSender(LicenseInfoSender &&) noexcept = delete;
LicenseInfoSender &operator=(const LicenseInfoSender &) = delete;
LicenseInfoSender &operator=(LicenseInfoSender &&) noexcept = delete;
~LicenseInfoSender();
private:
void SendData();
const std::string url_;
const std::string uuid_;
const std::string machine_id_;
const int64_t memory_limit_;
utils::Synchronized<std::optional<LicenseInfo>, utils::SpinLock> &license_info_;
utils::Scheduler scheduler_;
};
} // namespace memgraph::license

View File

@ -40,6 +40,8 @@
#include "glue/auth_checker.hpp"
#include "glue/auth_handler.hpp"
#include "helpers.hpp"
#include "license/license.hpp"
#include "license/license_sender.hpp"
#include "py/py.hpp"
#include "query/auth_checker.hpp"
#include "query/discard_value_stream.hpp"
@ -57,7 +59,6 @@
#include "utils/event_counter.hpp"
#include "utils/file.hpp"
#include "utils/flag_validation.hpp"
#include "utils/license.hpp"
#include "utils/logging.hpp"
#include "utils/memory_tracker.hpp"
#include "utils/message.hpp"
@ -68,6 +69,7 @@
#include "utils/string.hpp"
#include "utils/synchronized.hpp"
#include "utils/sysinfo/memory.hpp"
#include "utils/system_info.hpp"
#include "utils/terminate_handler.hpp"
#include "version.hpp"
@ -506,7 +508,7 @@ class BoltSession final : public memgraph::communication::bolt::Session<memgraph
username = &user_->username();
}
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
audit_log_->Record(endpoint_.address().to_string(), user_ ? *username : "", query,
memgraph::storage::PropertyValue(params_pv));
}
@ -779,15 +781,15 @@ int main(int argc, char **argv) {
memgraph::utils::OnScopeExit settings_finalizer([&] { memgraph::utils::global_settings.Finalize(); });
// register all runtime settings
memgraph::utils::license::RegisterLicenseSettings(memgraph::utils::license::global_license_checker,
memgraph::license::RegisterLicenseSettings(memgraph::license::global_license_checker,
memgraph::utils::global_settings);
memgraph::utils::license::global_license_checker.CheckEnvLicense();
memgraph::license::global_license_checker.CheckEnvLicense();
if (!FLAGS_organization_name.empty() && !FLAGS_license_key.empty()) {
memgraph::utils::license::global_license_checker.SetLicenseInfoOverride(FLAGS_license_key, FLAGS_organization_name);
memgraph::license::global_license_checker.SetLicenseInfoOverride(FLAGS_license_key, FLAGS_organization_name);
}
memgraph::utils::license::global_license_checker.StartBackgroundLicenseChecker(memgraph::utils::global_settings);
memgraph::license::global_license_checker.StartBackgroundLicenseChecker(memgraph::utils::global_settings);
// All enterprise features should be constructed before the main database
// storage. This will cause them to be destructed *after* the main database
@ -906,12 +908,15 @@ int main(int argc, char **argv) {
ServerT server(server_endpoint, &session_data, &context, FLAGS_bolt_session_inactivity_timeout, service_name,
FLAGS_bolt_num_workers);
const auto run_id = memgraph::utils::GenerateUUID();
const auto machine_id = memgraph::utils::GetMachineId();
session_data.run_id = run_id;
// Setup telemetry
static constexpr auto telemetry_server{"https://telemetry.memgraph.com/88b5e7e8-746a-11e8-9f85-538a9e9690cc/"};
std::optional<memgraph::telemetry::Telemetry> telemetry;
if (FLAGS_telemetry_enabled) {
telemetry.emplace("https://telemetry.memgraph.com/88b5e7e8-746a-11e8-9f85-538a9e9690cc/",
data_directory / "telemetry", std::chrono::minutes(10));
session_data.run_id = telemetry->GetRunId();
telemetry.emplace(telemetry_server, data_directory / "telemetry", run_id, machine_id, std::chrono::minutes(10));
telemetry->AddCollector("storage", [&db]() -> nlohmann::json {
auto info = db.GetInfo();
return {{"vertices", info.vertex_count}, {"edges", info.edge_count}};
@ -927,6 +932,8 @@ int main(int argc, char **argv) {
return memgraph::query::plan::CallProcedure::GetAndResetCounters();
});
}
memgraph::license::LicenseInfoSender license_info_sender(telemetry_server, run_id, machine_id, memory_limit,
memgraph::license::global_license_checker.GetLicenseInfo());
memgraph::communication::websocket::SafeAuth websocket_auth{&auth};
memgraph::communication::websocket::Server websocket_server{

View File

@ -25,6 +25,7 @@
#include "auth/models.hpp"
#include "glue/communication.hpp"
#include "license/license.hpp"
#include "memory/memory_control.hpp"
#include "query/constants.hpp"
#include "query/context.hpp"
@ -54,7 +55,6 @@
#include "utils/event_counter.hpp"
#include "utils/exceptions.hpp"
#include "utils/flag_validation.hpp"
#include "utils/license.hpp"
#include "utils/likely.hpp"
#include "utils/logging.hpp"
#include "utils/memory.hpp"
@ -299,7 +299,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
Callback callback;
const auto license_check_result = utils::license::global_license_checker.IsValidLicense(utils::global_settings);
const auto license_check_result = license::global_license_checker.IsEnterpriseValid(utils::global_settings);
static const std::unordered_set enterprise_only_methods{
AuthQuery::Action::CREATE_ROLE, AuthQuery::Action::DROP_ROLE, AuthQuery::Action::SET_ROLE,
@ -309,7 +309,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
if (license_check_result.HasError() && enterprise_only_methods.contains(auth_query->action_)) {
throw utils::BasicException(
utils::license::LicenseCheckErrorToString(license_check_result.GetError(), "advanced authentication features"));
license::LicenseCheckErrorToString(license_check_result.GetError(), "advanced authentication features"));
}
switch (auth_query->action_) {
@ -1017,7 +1017,7 @@ PullPlan::PullPlan(const std::shared_ptr<CachedPlan> plan, const Parameters &par
ctx_.evaluation_context.properties = NamesToProperties(plan->ast_storage().properties_, dba);
ctx_.evaluation_context.labels = NamesToLabels(plan->ast_storage().labels_, dba);
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && username.has_value() && dba) {
if (license::global_license_checker.IsEnterpriseValidFast() && username.has_value() && dba) {
ctx_.auth_checker = interpreter_context->auth_checker->GetFineGrainedAuthChecker(*username, dba);
}
#endif

View File

@ -27,6 +27,7 @@
#include <cppitertools/imap.hpp>
#include "spdlog/spdlog.h"
#include "license/license.hpp"
#include "query/auth_checker.hpp"
#include "query/context.hpp"
#include "query/db_accessor.hpp"
@ -47,7 +48,6 @@
#include "utils/event_counter.hpp"
#include "utils/exceptions.hpp"
#include "utils/fnv.hpp"
#include "utils/license.hpp"
#include "utils/likely.hpp"
#include "utils/logging.hpp"
#include "utils/memory.hpp"
@ -242,7 +242,7 @@ CreateNode::CreateNodeCursor::CreateNodeCursor(const CreateNode &self, utils::Me
bool CreateNode::CreateNodeCursor::Pull(Frame &frame, ExecutionContext &context) {
SCOPED_PROFILE_OP("CreateNode");
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(self_.node_info_.labels,
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
throw QueryRuntimeException("Vertex not created due to not having enough permission!");
@ -334,7 +334,7 @@ bool CreateExpand::CreateExpandCursor::Pull(Frame &frame, ExecutionContext &cont
if (!input_cursor_->Pull(frame, context)) return false;
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast()) {
if (license::global_license_checker.IsEnterpriseValidFast()) {
const auto fine_grained_permission = self_.existing_node_
? memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE
@ -433,8 +433,7 @@ class ScanAllCursor : public Cursor {
vertices_it_.emplace(vertices_.value().begin());
}
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
!FindNextVertex(context)) {
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker && !FindNextVertex(context)) {
return false;
}
#endif
@ -731,7 +730,7 @@ bool Expand::ExpandCursor::Pull(Frame &frame, ExecutionContext &context) {
if (in_edges_ && *in_edges_it_ != in_edges_->end()) {
auto edge = *(*in_edges_it_)++;
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge.From(), self_.view_,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -752,7 +751,7 @@ bool Expand::ExpandCursor::Pull(Frame &frame, ExecutionContext &context) {
// already done in the block above
if (self_.common_.direction == EdgeAtom::Direction::BOTH && edge.IsCycle()) continue;
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge.To(), self_.view_,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -1089,7 +1088,7 @@ class ExpandVariableCursor : public Cursor {
VertexAccessor current_vertex =
current_edge.second == EdgeAtom::Direction::IN ? current_edge.first.From() : current_edge.first.To();
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(current_edge.first, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(current_vertex, storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -1258,7 +1257,7 @@ class STShortestPathCursor : public query::plan::Cursor {
auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types));
for (const auto &edge : out_edges) {
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge.To(), storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -1284,7 +1283,7 @@ class STShortestPathCursor : public query::plan::Cursor {
auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types));
for (const auto &edge : in_edges) {
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge.From(), storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -1324,7 +1323,7 @@ class STShortestPathCursor : public query::plan::Cursor {
auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types));
for (const auto &edge : out_edges) {
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge.To(), storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -1349,7 +1348,7 @@ class STShortestPathCursor : public query::plan::Cursor {
auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types));
for (const auto &edge : in_edges) {
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge.From(), storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -1406,7 +1405,7 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
// if we already processed the given vertex it doesn't get expanded
if (processed_.find(vertex) != processed_.end()) return;
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(vertex, storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -1592,7 +1591,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
int64_t depth) {
auto *memory = evaluator.GetMemoryResource();
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(vertex, storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -1902,7 +1901,7 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
auto out_edges = UnwrapEdgesResult(vertex.OutEdges(storage::View::OLD, self_.common_.edge_types));
for (const auto &edge : out_edges) {
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(edge.To(), storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -1916,7 +1915,7 @@ class ExpandAllShortestPathsCursor : public query::plan::Cursor {
auto in_edges = UnwrapEdgesResult(vertex.InEdges(storage::View::OLD, self_.common_.edge_types));
for (const auto &edge : in_edges) {
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(edge.From(), storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::READ) &&
context.auth_checker->Has(edge, memgraph::query::AuthQuery::FineGrainedPrivilege::READ))) {
@ -2366,7 +2365,7 @@ bool Delete::DeleteCursor::Pull(Frame &frame, ExecutionContext &context) {
if (expression_result.type() == TypedValue::Type::Edge) {
auto &ea = expression_result.ValueEdge();
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!(context.auth_checker->Has(ea, query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE) &&
context.auth_checker->Has(ea.To(), storage::View::NEW, query::AuthQuery::FineGrainedPrivilege::UPDATE) &&
context.auth_checker->Has(ea.From(), storage::View::NEW, query::AuthQuery::FineGrainedPrivilege::UPDATE))) {
@ -2399,7 +2398,7 @@ bool Delete::DeleteCursor::Pull(Frame &frame, ExecutionContext &context) {
case TypedValue::Type::Vertex: {
auto &va = expression_result.ValueVertex();
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(va, storage::View::NEW, query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
throw QueryRuntimeException("Vertex not deleted due to not having enough permission!");
}
@ -2508,7 +2507,7 @@ bool SetProperty::SetPropertyCursor::Pull(Frame &frame, ExecutionContext &contex
switch (lhs.type()) {
case TypedValue::Type::Vertex: {
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(lhs.ValueVertex(), storage::View::NEW,
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw QueryRuntimeException("Vertex property not set due to not having enough permission!");
@ -2525,7 +2524,7 @@ bool SetProperty::SetPropertyCursor::Pull(Frame &frame, ExecutionContext &contex
}
case TypedValue::Type::Edge: {
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(lhs.ValueEdge(), memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw QueryRuntimeException("Edge property not set due to not having enough permission!");
}
@ -2724,7 +2723,7 @@ bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, ExecutionContext &co
switch (lhs.type()) {
case TypedValue::Type::Vertex:
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(lhs.ValueVertex(), storage::View::NEW,
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw QueryRuntimeException("Vertex properties not set due to not having enough permission!");
@ -2735,7 +2734,7 @@ bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, ExecutionContext &co
break;
case TypedValue::Type::Edge:
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(lhs.ValueEdge(), memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw QueryRuntimeException("Edge properties not set due to not having enough permission!");
}
@ -2778,7 +2777,7 @@ bool SetLabels::SetLabelsCursor::Pull(Frame &frame, ExecutionContext &context) {
SCOPED_PROFILE_OP("SetLabels");
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(self_.labels_, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
throw QueryRuntimeException("Couldn't set label due to not having enough permission!");
}
@ -2793,7 +2792,7 @@ bool SetLabels::SetLabelsCursor::Pull(Frame &frame, ExecutionContext &context) {
auto &vertex = vertex_value.ValueVertex();
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(vertex, storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw QueryRuntimeException("Couldn't set label due to not having enough permission!");
@ -2883,7 +2882,7 @@ bool RemoveProperty::RemovePropertyCursor::Pull(Frame &frame, ExecutionContext &
switch (lhs.type()) {
case TypedValue::Type::Vertex:
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(lhs.ValueVertex(), storage::View::NEW,
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw QueryRuntimeException("Vertex property not removed due to not having enough permission!");
@ -2893,7 +2892,7 @@ bool RemoveProperty::RemovePropertyCursor::Pull(Frame &frame, ExecutionContext &
break;
case TypedValue::Type::Edge:
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(lhs.ValueEdge(), memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw QueryRuntimeException("Edge property not removed due to not having enough permission!");
}
@ -2936,7 +2935,7 @@ bool RemoveLabels::RemoveLabelsCursor::Pull(Frame &frame, ExecutionContext &cont
SCOPED_PROFILE_OP("RemoveLabels");
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(self_.labels_, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
throw QueryRuntimeException("Couldn't remove label due to not having enough permission!");
}
@ -2951,7 +2950,7 @@ bool RemoveLabels::RemoveLabelsCursor::Pull(Frame &frame, ExecutionContext &cont
auto &vertex = vertex_value.ValueVertex();
#ifdef MG_ENTERPRISE
if (utils::license::global_license_checker.IsValidLicenseFast() && context.auth_checker &&
if (license::global_license_checker.IsEnterpriseValidFast() && context.auth_checker &&
!context.auth_checker->Has(vertex, storage::View::OLD,
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw QueryRuntimeException("Couldn't remove label due to not having enough permission!");

View File

@ -22,6 +22,7 @@
#include <type_traits>
#include <utility>
#include "license/license.hpp"
#include "mg_procedure.h"
#include "module.hpp"
#include "query/frontend/ast/ast.hpp"
@ -32,7 +33,6 @@
#include "storage/v2/view.hpp"
#include "utils/algorithm.hpp"
#include "utils/concepts.hpp"
#include "utils/license.hpp"
#include "utils/logging.hpp"
#include "utils/math.hpp"
#include "utils/memory.hpp"
@ -1653,7 +1653,7 @@ mgp_error mgp_vertex_set_property(struct mgp_vertex *v, const char *property_nam
auto *ctx = v->graph->ctx;
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker &&
!ctx->auth_checker->Has(v->getImpl(), v->graph->view,
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw AuthorizationException{"Insufficient permissions for setting a property on vertex!"};
@ -1706,7 +1706,7 @@ mgp_error mgp_vertex_add_label(struct mgp_vertex *v, mgp_label label) {
const auto label_id = std::visit([label](auto *impl) { return impl->NameToLabel(label.name); }, v->graph->impl);
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker &&
!(ctx->auth_checker->Has(v->getImpl(), v->graph->view,
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE) &&
ctx->auth_checker->Has({label_id}, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE))) {
@ -1750,7 +1750,7 @@ mgp_error mgp_vertex_remove_label(struct mgp_vertex *v, mgp_label label) {
const auto label_id = std::visit([&label](auto *impl) { return impl->NameToLabel(label.name); }, v->graph->impl);
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker &&
!(ctx->auth_checker->Has(v->getImpl(), v->graph->view,
memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE) &&
ctx->auth_checker->Has({label_id}, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE))) {
@ -1989,7 +1989,7 @@ mgp_error mgp_vertex_iter_in_edges(mgp_vertex *v, mgp_memory *memory, mgp_edges_
it->in.emplace(std::move(*maybe_edges));
it->in_it.emplace(it->in->begin());
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
NextPermittedEdge(*it, true);
}
#endif
@ -2041,7 +2041,7 @@ mgp_error mgp_vertex_iter_out_edges(mgp_vertex *v, mgp_memory *memory, mgp_edges
it->out_it.emplace(it->out->begin());
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
NextPermittedEdge(*it, false);
}
#endif
@ -2099,7 +2099,7 @@ mgp_error mgp_edges_iterator_next(mgp_edges_iterator *it, mgp_edge **result) {
++*impl_it;
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
NextPermittedEdge(*it, for_in);
}
#endif
@ -2202,7 +2202,7 @@ mgp_error mgp_edge_set_property(struct mgp_edge *e, const char *property_name, m
auto *ctx = e->from.graph->ctx;
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker &&
!ctx->auth_checker->Has(e->impl, memgraph::query::AuthQuery::FineGrainedPrivilege::UPDATE)) {
throw AuthorizationException{"Insufficient permissions for setting a property on edge!"};
}
@ -2310,7 +2310,7 @@ mgp_error mgp_graph_create_vertex(struct mgp_graph *graph, mgp_memory *memory, m
[=]() -> mgp_vertex * {
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && graph->ctx &&
if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && graph->ctx &&
graph->ctx->auth_checker &&
!graph->ctx->auth_checker->HasGlobalPrivilegeOnVertices(
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
@ -2340,7 +2340,7 @@ mgp_error mgp_graph_delete_vertex(struct mgp_graph *graph, mgp_vertex *vertex) {
auto *ctx = graph->ctx;
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker &&
!ctx->auth_checker->Has(vertex->getImpl(), graph->view,
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
throw AuthorizationException{"Insufficient permissions for deleting a vertex!"};
@ -2391,7 +2391,7 @@ mgp_error mgp_graph_detach_delete_vertex(struct mgp_graph *graph, mgp_vertex *ve
return WrapExceptions([=] {
auto *ctx = graph->ctx;
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker &&
!ctx->auth_checker->Has(vertex->getImpl(), graph->view,
memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
throw AuthorizationException{"Insufficient permissions for deleting a vertex!"};
@ -2455,7 +2455,7 @@ mgp_error mgp_graph_create_edge(mgp_graph *graph, mgp_vertex *from, mgp_vertex *
#ifdef MG_ENTERPRISE
const auto edge_id =
std::visit([type](auto *impl) { return impl->NameToEdgeType(type.name); }, from->graph->impl);
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker &&
!ctx->auth_checker->Has(edge_id, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
throw AuthorizationException{"Insufficient permissions for creating edges!"};
}
@ -2516,7 +2516,7 @@ mgp_error mgp_graph_delete_edge(struct mgp_graph *graph, mgp_edge *edge) {
return WrapExceptions([=] {
auto *ctx = graph->ctx;
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast() && ctx && ctx->auth_checker &&
if (memgraph::license::global_license_checker.IsEnterpriseValidFast() && ctx && ctx->auth_checker &&
!ctx->auth_checker->Has(edge->impl, memgraph::query::AuthQuery::FineGrainedPrivilege::CREATE_DELETE)) {
throw AuthorizationException{"Insufficient permissions for deleting an edge!"};
}
@ -2578,7 +2578,7 @@ mgp_vertices_iterator::mgp_vertices_iterator(mgp_graph *graph, memgraph::utils::
vertices(std::visit([graph](auto *impl) { return impl->Vertices(graph->view); }, graph->impl)),
current_it(vertices.begin()) {
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
NextPermitted(*this);
}
#endif
@ -2627,7 +2627,7 @@ mgp_error mgp_vertices_iterator_next(mgp_vertices_iterator *it, mgp_vertex **res
++it->current_it;
#ifdef MG_ENTERPRISE
if (memgraph::utils::license::global_license_checker.IsValidLicenseFast()) {
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
NextPermitted(*it);
}
#endif

View File

@ -1,12 +1,12 @@
set(telemetry_src_files
collectors.cpp
telemetry.cpp
system_info.cpp)
telemetry.cpp)
add_library(telemetry_lib STATIC ${telemetry_src_files})
target_link_libraries(telemetry_lib mg-requests mg-kvstore mg-utils)
add_library(mg-telemetry STATIC ${telemetry_src_files})
target_link_libraries(mg-telemetry mg-requests mg-kvstore mg-utils)
option(MG_TELEMETRY_ID_OVERRIDE "Override for the telemetry ID" STRING)
if(MG_TELEMETRY_ID_OVERRIDE)
message(WARNING "Using telemetry ID override: ${MG_TELEMETRY_ID_OVERRIDE}")
target_compile_definitions(telemetry_lib PRIVATE MG_TELEMETRY_ID_OVERRIDE="${MG_TELEMETRY_ID_OVERRIDE}")
target_compile_definitions(mg-telemetry PRIVATE MG_TELEMETRY_ID_OVERRIDE="${MG_TELEMETRY_ID_OVERRIDE}")
endif()

View File

@ -17,38 +17,24 @@
#include "requests/requests.hpp"
#include "telemetry/collectors.hpp"
#include "telemetry/system_info.hpp"
#include "utils/file.hpp"
#include "utils/logging.hpp"
#include "utils/system_info.hpp"
#include "utils/timestamp.hpp"
#include "utils/uuid.hpp"
namespace memgraph::telemetry {
namespace {
std::string GetMachineId() {
#ifdef MG_TELEMETRY_ID_OVERRIDE
return MG_TELEMETRY_ID_OVERRIDE;
#else
// We assume we're on linux and we need to read the machine id from /etc/machine-id
const auto machine_id_lines = utils::ReadLines("/etc/machine-id");
if (machine_id_lines.size() != 1) {
return "UNKNOWN";
}
return machine_id_lines[0];
#endif
}
} // namespace
const int kMaxBatchSize = 100;
constexpr auto kMaxBatchSize{100};
Telemetry::Telemetry(std::string url, std::filesystem::path storage_directory,
Telemetry::Telemetry(std::string url, std::filesystem::path storage_directory, std::string uuid, std::string machine_id,
std::chrono::duration<int64_t> refresh_interval, const uint64_t send_every_n)
: url_(std::move(url)),
uuid_(utils::GenerateUUID()),
machine_id_(GetMachineId()),
uuid_(uuid),
machine_id_(machine_id),
send_every_n_(send_every_n),
storage_(std::move(storage_directory)) {
StoreData("startup", GetSystemInfo());
StoreData("startup", utils::GetSystemInfo());
AddCollector("resources", GetResourceUsage);
AddCollector("uptime", [&]() -> nlohmann::json { return GetUptime(); });
scheduler_.Run("Telemetry", refresh_interval, [&] { CollectData(); });
@ -59,19 +45,15 @@ void Telemetry::AddCollector(const std::string &name, const std::function<const
collectors_.emplace_back(name, func);
}
std::string Telemetry::GetRunId() const { return uuid_; }
Telemetry::~Telemetry() {
scheduler_.Stop();
CollectData("shutdown");
}
void Telemetry::StoreData(const nlohmann::json &event, const nlohmann::json &data) {
nlohmann::json payload = {{"run_id", uuid_},
{"machine_id", machine_id_},
{"event", event},
{"data", data},
{"timestamp", utils::Timestamp::Now().SecWithNsecSinceTheEpoch()}};
nlohmann::json payload = {
{"run_id", uuid_}, {"type", "telemetry"}, {"machine_id", machine_id_},
{"event", event}, {"data", data}, {"timestamp", utils::Timestamp::Now().SecWithNsecSinceTheEpoch()}};
storage_.Put(fmt::format("{}:{}", uuid_, event.dump()), payload.dump());
}

View File

@ -26,7 +26,7 @@ namespace memgraph::telemetry {
* This class implements the telemetry collector service. It periodically scapes
* all registered collectors and stores their data. With periodically scraping
* the collectors the service collects machine information in the constructor
* and stores it. Also, it calles all collectors once more in the destructor so
* and stores it. Also, it calls all collectors once more in the destructor so
* that final stats can be collected. All data is stored persistently. If there
* is no internet connection the data will be sent when the internet connection
* is reestablished. If there is an issue with the internet connection that
@ -34,14 +34,11 @@ namespace memgraph::telemetry {
*/
class Telemetry final {
public:
Telemetry(std::string url, std::filesystem::path storage_directory,
Telemetry(std::string url, std::filesystem::path storage_directory, std::string uuid, std::string machine_id,
std::chrono::duration<int64_t> refresh_interval = std::chrono::minutes(10), uint64_t send_every_n = 10);
void AddCollector(const std::string &name, const std::function<const nlohmann::json(void)> &func);
/// Required to expose run_id to Bolt server.
std::string GetRunId() const;
~Telemetry();
Telemetry(const Telemetry &) = delete;

View File

@ -14,6 +14,7 @@ set(utils_src_files
thread.cpp
thread_pool.cpp
tsc.cpp
system_info.cpp
uuid.cpp)
find_package(Boost REQUIRED)
@ -23,16 +24,10 @@ find_package(Threads REQUIRED)
add_library(mg-utils STATIC ${utils_src_files})
target_link_libraries(mg-utils PUBLIC Boost::headers fmt::fmt spdlog::spdlog)
target_link_libraries(mg-utils PRIVATE librdtsc stdc++fs Threads::Threads gflags uuid rt)
target_link_libraries(mg-utils PRIVATE librdtsc stdc++fs Threads::Threads gflags json uuid rt)
set(settings_src_files
settings.cpp)
add_library(mg-settings STATIC ${settings_src_files})
target_link_libraries(mg-settings mg-kvstore mg-slk mg-utils)
set(license_src_files
license.cpp)
add_library(mg-license STATIC ${license_src_files})
target_link_libraries(mg-license mg-settings mg-utils)

View File

@ -43,7 +43,7 @@ inline uint64_t GetMemoryUsage() {
pid_t pid = getpid();
uint64_t memory = 0;
auto statm_data = utils::ReadLines(fmt::format("/proc/{}/statm", pid));
if (statm_data.size() >= 1) {
if (!statm_data.empty()) {
auto split = utils::Split(statm_data[0]);
if (split.size() >= 2) {
memory = std::stoull(split[1]) * sysconf(_SC_PAGESIZE);

View File

@ -9,56 +9,35 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#include "telemetry/system_info.hpp"
#include "utils/system_info.hpp"
#include <string>
#include <sys/utsname.h>
#include <gflags/gflags.h>
#include <sys/utsname.h>
#include "utils/file.hpp"
#include "utils/string.hpp"
namespace memgraph::telemetry {
namespace memgraph::utils {
const nlohmann::json GetSystemInfo() {
// Get `uname`.
struct utsname info;
if (uname(&info) != 0) return {};
// Parse `/etc/os-release`.
std::string os_name, os_version, os_full;
auto os_data = utils::ReadLines("/etc/os-release");
for (auto &row : os_data) {
auto split = utils::Split(row, "=");
if (split.size() < 2) continue;
if (split[0] == "NAME") {
os_name = utils::Trim(split[1], "\"");
} else if (split[0] == "VERSION") {
os_version = utils::Trim(split[1], "\"");
}
os_full = fmt::format("{} {}", os_name, os_version);
}
// Parse `/proc/cpuinfo`.
std::string cpu_model;
uint64_t cpu_count = 0;
auto cpu_data = utils::ReadLines("/proc/cpuinfo");
for (auto &row : cpu_data) {
auto tmp = utils::Trim(row);
if (tmp == "") {
++cpu_count;
} else if (utils::StartsWith(tmp, "model name")) {
auto split = utils::Split(tmp, ":");
if (split.size() != 2) continue;
cpu_model = utils::Trim(split[1]);
std::string GetMachineId() {
#ifdef MG_TELEMETRY_ID_OVERRIDE
return MG_TELEMETRY_ID_OVERRIDE;
#else
// We assume we're on linux and we need to read the machine id from /etc/machine-id
const auto machine_id_lines = memgraph::utils::ReadLines("/etc/machine-id");
if (machine_id_lines.size() != 1) {
return "UNKNOWN";
}
return machine_id_lines[0];
#endif
}
MemoryInfo GetMemoryInfo() {
// Parse `/proc/meminfo`.
nlohmann::json ret;
uint64_t memory = 0, swap = 0;
uint64_t memory{0};
uint64_t swap{0};
auto mem_data = utils::ReadLines("/proc/meminfo");
for (auto &row : mem_data) {
auto tmp = utils::Trim(row);
@ -74,15 +53,55 @@ const nlohmann::json GetSystemInfo() {
}
memory *= 1024;
swap *= 1024;
return {{"architecture", info.machine},
{"cpu_count", cpu_count},
{"cpu_model", cpu_model},
{"kernel", fmt::format("{} {}", info.release, info.version)},
{"memory", memory},
{"os", os_full},
{"swap", swap},
{"version", gflags::VersionString()}};
return {memory, swap};
}
} // namespace memgraph::telemetry
CPUInfo GetCPUInfo() {
// Parse `/proc/cpuinfo`.
std::string cpu_model;
uint64_t cpu_count{0};
auto cpu_data = utils::ReadLines("/proc/cpuinfo");
for (auto &row : cpu_data) {
auto tmp = utils::Trim(row);
if (tmp.empty()) {
++cpu_count;
} else if (utils::StartsWith(tmp, "model name")) {
auto split = utils::Split(tmp, ":");
if (split.size() != 2) continue;
cpu_model = utils::Trim(split[1]);
}
}
return {cpu_model, cpu_count};
}
nlohmann::json GetSystemInfo() {
// Get `uname`.
struct utsname info;
if (uname(&info) != 0) return {};
// Parse `/etc/os-release`.
std::string os_name;
std::string os_version;
std::string os_full;
auto os_data = utils::ReadLines("/etc/os-release");
for (auto &row : os_data) {
auto split = utils::Split(row, "=");
if (split.size() < 2) continue;
if (split[0] == "NAME") {
os_name = utils::Trim(split[1], "\"");
} else if (split[0] == "VERSION") {
os_version = utils::Trim(split[1], "\"");
}
os_full = fmt::format("{} {}", os_name, os_version);
}
const auto cpu_info = GetCPUInfo();
const auto mem_info = GetMemoryInfo();
return {{"architecture", info.machine}, {"cpu_count", cpu_info.cpu_count},
{"cpu_model", cpu_info.cpu_model}, {"kernel", fmt::format("{} {}", info.release, info.version)},
{"memory", mem_info.memory}, {"os", os_full},
{"swap", mem_info.swap}, {"version", gflags::VersionString()}};
}
} // namespace memgraph::utils

View File

@ -11,16 +11,33 @@
#pragma once
#include <cstdint>
#include <string>
#include <json/json.hpp>
namespace memgraph::telemetry {
namespace memgraph::utils {
// TODO (mferencevic): merge with `utils/sysinfo`
struct MemoryInfo {
uint64_t memory;
uint64_t swap;
};
struct CPUInfo {
std::string cpu_model;
uint64_t cpu_count;
};
std::string GetMachineId();
MemoryInfo GetMemoryInfo();
CPUInfo GetCPUInfo();
/**
* This function returs a dictionary containing some basic system information
* This function return a dictionary containing some basic system information
* (eg. operating system name, cpu information, memory information, etc.).
*/
const nlohmann::json GetSystemInfo();
nlohmann::json GetSystemInfo();
} // namespace memgraph::telemetry
} // namespace memgraph::utils

View File

@ -13,24 +13,6 @@ add_subdirectory(auth)
# lba test binaries
add_subdirectory(fine_grained_access)
## distributed ha/basic binaries
#add_subdirectory(ha/basic)
#
## distributed ha/constraints binaries
#add_subdirectory(ha/constraints)
#
## distributed ha/index binaries
#add_subdirectory(ha/index)
#
## distributed ha/large_log_entries binaries
#add_subdirectory(ha/large_log_entries)
#
## distributed ha/leader_election binaries
#add_subdirectory(ha/leader_election)
#
## distributed ha/term_updates binaries
#add_subdirectory(ha/term_updates)
# audit test binaries
add_subdirectory(audit)
@ -39,3 +21,6 @@ add_subdirectory(ldap)
# mg_import_csv test binaries
add_subdirectory(mg_import_csv)
# license_check test binaries
add_subdirectory(license_info)

View File

@ -0,0 +1,6 @@
set(target_name memgraph__integration__license_info)
set(client_target_name ${target_name}__client)
add_executable(${client_target_name} client.cpp)
set_target_properties(${client_target_name} PROPERTIES OUTPUT_NAME client)
target_link_libraries(${client_target_name} mg-requests mg-license mg-utils)

View File

@ -0,0 +1,62 @@
// Copyright 2022 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#include <exception>
#include <string>
#include <gflags/gflags.h>
#include "license/license.hpp"
#include "license/license_sender.hpp"
#include "requests/requests.hpp"
#include "spdlog/spdlog.h"
#include "utils/logging.hpp"
#include "utils/synchronized.hpp"
#include "utils/system_info.hpp"
#include "utils/uuid.hpp"
DEFINE_string(endpoint, "http://127.0.0.1:5500/", "Endpoint that should be used for the test.");
DEFINE_string(license_type, "enterprise", "License type; can be oem or enterprise.");
DEFINE_int64(interval, 1, "Interval used for reporting telemetry in seconds.");
DEFINE_int64(duration, 10, "Duration of the test in seconds.");
memgraph::license::LicenseType StringToLicenseType(const std::string_view license_type) {
if (license_type == "enterprise") {
return memgraph::license::LicenseType::ENTERPRISE;
}
if (license_type == "oem") {
return memgraph::license::LicenseType::OEM;
}
spdlog::critical("Invalid license type!");
std::terminate();
}
int main(int argc, char **argv) {
gflags::SetVersionString("license-info");
gflags::ParseCommandLineFlags(&argc, &argv, true);
memgraph::requests::Init();
memgraph::license::License license{"Memgraph", 0, 0, StringToLicenseType(FLAGS_license_type)};
memgraph::utils::Synchronized<std::optional<memgraph::license::LicenseInfo>, memgraph::utils::SpinLock> license_info{
memgraph::license::LicenseInfo{"mg-testkey", "Memgraph"}};
license_info.WithLock([license = std::move(license)](auto &license_info) {
license_info->license = license;
license_info->is_valid = true;
});
memgraph::license::LicenseInfoSender license_sender(FLAGS_endpoint, memgraph::utils::GenerateUUID(),
memgraph::utils::GetMachineId(), 10000000, license_info,
std::chrono::seconds(FLAGS_interval));
std::this_thread::sleep_for(std::chrono::seconds(FLAGS_duration));
return 0;
}

View File

@ -0,0 +1,96 @@
#!/usr/bin/python3 -u
# Copyright 2021 Memgraph Ltd.
#
# Use of this software is governed by the Business Source License
# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
# License, and you may not use this file except in compliance with the Business Source License.
#
# As of the Change Date specified in that file, in accordance with
# the Business Source License, use of this software will be governed
# by the Apache License, Version 2.0, included in the file
# licenses/APL.txt.
import argparse
import json
import os
import subprocess
import sys
import time
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
PROJECT_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "..", "..", ".."))
def execute_test(**kwargs):
client_binary = kwargs.pop("client")
server_binary = kwargs.pop("server")
start_server = kwargs.pop("start_server", True)
interval = kwargs.pop("interval", 1)
duration = kwargs.pop("duration", 5)
license_type = kwargs.pop("license-type", "enterprise")
timeout = duration * 2 if "hang" not in kwargs else duration * 2 + 60
success = False
client_args = [client_binary, "--interval", interval, "--duration", duration, "--license-type", license_type]
server = None
if start_server:
server = subprocess.Popen(server_binary)
time.sleep(0.4)
assert server.poll() is None, "Server process died prematurely!"
try:
subprocess.run(list(map(str, client_args)), timeout=timeout, check=True)
finally:
if server is None:
success = True
else:
server.terminate()
try:
success = server.wait(timeout=5) == 0
success = True
except subprocess.TimeoutExpired:
server.kill()
return success
def main():
server_binary = os.path.join(SCRIPT_DIR, "server.py")
client_binary = os.path.join(PROJECT_DIR, "build", "tests", "integration", "license_info", "client")
parser = argparse.ArgumentParser()
parser.add_argument("--client", default=client_binary)
parser.add_argument("--server", default=server_binary)
parser.add_argument("--server-url", default="127.0.0.1")
parser.add_argument("--server-port", default="5500")
args = parser.parse_args()
tests = [
{"interval": 2},
{"duration": 10},
{"interval": 2, "duration": 10},
{"license-type": "oem"},
{"license-type": "enterprise"},
]
for test in tests:
print("\033[1;36m~~ Executing test with arguments:", json.dumps(test, sort_keys=True), "~~\033[0m")
try:
success = execute_test(client=args.client, server=args.server, **test)
except Exception as e:
print("\033[1;33m", e, "\033[0m", sep="")
success = False
if not success:
print("\033[1;31m~~", "Test failed!", "~~\033[0m")
sys.exit(1)
else:
print("\033[1;32m~~", "Test ok!", "~~\033[0m")
sys.exit(0)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,69 @@
#!/usr/bin/python3 -u
# Copyright 2021 Memgraph Ltd.
#
# Use of this software is governed by the Business Source License
# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
# License, and you may not use this file except in compliance with the Business Source License.
#
# As of the Change Date specified in that file, in accordance with
# the Business Source License, use of this software will be governed
# by the Apache License, Version 2.0, included in the file
# licenses/APL.txt.
import argparse
import json
from http.server import HTTPServer, SimpleHTTPRequestHandler
EXPECTED_LICENSE_INFO_FIELDS = {
"run_id": str,
"machine_id": str,
"type": str,
"license_type": str,
"license_key": str,
"organization": str,
"valid": bool,
"physical_memory_size": int,
"swap_memory_size": int,
"memory_used": int,
"runtime_memory_limit": int,
"license_memory_limit": int,
"timestamp": float,
}
class ServerHandler(SimpleHTTPRequestHandler):
def do_POST(self):
assert self.headers["user-agent"] == "memgraph/license-info", f"The header is {self.headers['user-agent']}"
assert self.headers["accept"] == "application/json", f"The header is {self.headers['accept']}"
assert self.headers["content-type"] == "application/json", f"The header is {self.headers['content-type']}"
content_len = int(self.headers.get("content-length", 0))
data = json.loads(self.rfile.read(content_len).decode("utf-8"))
assert isinstance(data, dict)
for expected_field, expected_type in EXPECTED_LICENSE_INFO_FIELDS.items():
assert expected_field in data, f"Field {expected_field} not found in received data"
assert isinstance(
data[expected_field], expected_type
), f"Field {expected_field} is not correct type: expected {expected_type} got {type(data[expected_field])}"
assert len(EXPECTED_LICENSE_INFO_FIELDS) == len(data), "Expected data size does not match received"
self.send_response(200)
self.end_headers()
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--address", type=str, default="127.0.0.1")
parser.add_argument("--port", type=int, default=5500)
args = parser.parse_args()
with HTTPServer((args.address, args.port), ServerHandler) as srv:
print(f"Serving HTTP server at {args.address}:{args.port}")
srv.serve_forever()
if __name__ == "__main__":
main()

View File

@ -3,4 +3,4 @@ set(client_target_name ${target_name}__client)
add_executable(${client_target_name} client.cpp)
set_target_properties(${client_target_name} PROPERTIES OUTPUT_NAME client)
target_link_libraries(${client_target_name} mg-requests telemetry_lib)
target_link_libraries(${client_target_name} mg-requests mg-telemetry)

View File

@ -13,6 +13,8 @@
#include "requests/requests.hpp"
#include "telemetry/telemetry.hpp"
#include "utils/system_info.hpp"
#include "utils/uuid.hpp"
DEFINE_string(endpoint, "http://127.0.0.1:9000/", "Endpoint that should be used for the test.");
DEFINE_int64(interval, 1, "Interval used for reporting telemetry in seconds.");
@ -24,8 +26,8 @@ int main(int argc, char **argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
memgraph::requests::Init();
memgraph::telemetry::Telemetry telemetry(FLAGS_endpoint, FLAGS_storage_directory,
std::chrono::seconds(FLAGS_interval), 1);
memgraph::telemetry::Telemetry telemetry(FLAGS_endpoint, FLAGS_storage_directory, memgraph::utils::GenerateUUID(),
memgraph::utils::GetMachineId(), std::chrono::seconds(FLAGS_interval), 1);
uint64_t counter = 0;
telemetry.AddCollector("db", [&counter]() -> nlohmann::json {

View File

@ -36,8 +36,7 @@ def execute_test(**kwargs):
timeout = duration * 2 if "hang" not in kwargs else duration * 2 + 60
success = False
server_args = [server_binary, "--interval", interval,
"--duration", duration]
server_args = [server_binary, "--interval", interval, "--duration", duration]
for flag, value in kwargs.items():
flag = "--" + flag.replace("_", "-")
# We handle boolean flags here. The type of value must be `bool`, and
@ -48,9 +47,15 @@ def execute_test(**kwargs):
else:
server_args.extend([flag, value])
client_args = [client_binary, "--interval", interval,
"--duration", duration,
"--storage-directory", storage_directory]
client_args = [
client_binary,
"--interval",
interval,
"--duration",
duration,
"--storage-directory",
storage_directory,
]
if endpoint:
client_args.extend(["--endpoint", endpoint])
@ -61,8 +66,7 @@ def execute_test(**kwargs):
assert server.poll() is None, "Server process died prematurely!"
try:
subprocess.run(list(map(str, client_args)), timeout=timeout,
check=True)
subprocess.run(list(map(str, client_args)), timeout=timeout, check=True)
finally:
if server is None:
success = True
@ -89,15 +93,13 @@ TESTS = [
{"start_server": False},
{"startups": 4, "no_check_duration": True}, # the last 3 tests failed
# to send any data + this test
{"add_garbage": True}
{"add_garbage": True},
]
if __name__ == "__main__":
server_binary = os.path.join(SCRIPT_DIR, "server.py")
client_binary = os.path.join(PROJECT_DIR, "build", "tests",
"integration", "telemetry", "client")
kvstore_console_binary = os.path.join(PROJECT_DIR, "build", "tests",
"manual", "kvstore_console")
client_binary = os.path.join(PROJECT_DIR, "build", "tests", "integration", "telemetry", "client")
kvstore_console_binary = os.path.join(PROJECT_DIR, "build", "tests", "manual", "kvstore_console")
parser = argparse.ArgumentParser()
parser.add_argument("--client", default=client_binary)
@ -108,19 +110,17 @@ if __name__ == "__main__":
storage = tempfile.TemporaryDirectory()
for test in TESTS:
print("\033[1;36m~~ Executing test with arguments:",
json.dumps(test, sort_keys=True), "~~\033[0m")
print("\033[1;36m~~ Executing test with arguments:", json.dumps(test, sort_keys=True), "~~\033[0m")
if test.pop("add_garbage", False):
proc = subprocess.Popen([args.kvstore_console, "--path",
storage.name], stdin=subprocess.PIPE,
stdout=subprocess.DEVNULL)
proc = subprocess.Popen(
[args.kvstore_console, "--path", storage.name], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL
)
proc.communicate("put garbage garbage".encode("utf-8"))
assert proc.wait() == 0
try:
success = execute_test(client=args.client, server=args.server,
storage=storage.name, **test)
success = execute_test(client=args.client, server=args.server, storage=storage.name, **test)
except Exception as e:
print("\033[1;33m", e, "\033[0m", sep="")
success = False

View File

@ -12,13 +12,12 @@
# licenses/APL.txt.
import argparse
import itertools
import json
import os
import signal
import sys
import time
import itertools
from http.server import BaseHTTPRequestHandler, HTTPServer
@ -46,7 +45,7 @@ def build_handler(storage, args):
assert self.headers["accept"] == "application/json"
assert self.headers["content-type"] == "application/json"
content_len = int(self.headers.get('content-length', 0))
content_len = int(self.headers.get("content-length", 0))
data = json.loads(self.rfile.read(content_len).decode("utf-8"))
if self.path not in [args.path, args.redirect_path]:
@ -70,6 +69,7 @@ def build_handler(storage, args):
assert type(item) == dict
assert "event" in item
assert "run_id" in item
assert "type" in item
assert "machine_id" in item
assert "data" in item
assert "timestamp" in item
@ -188,11 +188,11 @@ if __name__ == "__main__":
startups[-1].append(item)
# Check that there were the correct number of startups.
assert len(startups) == args.startups
assert len(startups) == args.startups, f"Expected: {args.startups}, actual: {len(startups)}"
# Verify each startup.
for startup in startups:
verify_storage(startup, args)
# machine id has to be same for every run on the same machine
assert len(set(map(lambda x: x['machine_id'], itertools.chain(*startups)))) == 1
assert len(set(map(lambda x: x["machine_id"], itertools.chain(*startups)))) == 1

View File

@ -10,11 +10,11 @@
// licenses/APL.txt.
#include "communication/result_stream_faker.hpp"
#include "license/license.hpp"
#include "query/config.hpp"
#include "query/interpreter.hpp"
#include "storage/v2/isolation_level.hpp"
#include "storage/v2/storage.hpp"
#include "utils/license.hpp"
#include "utils/on_scope_exit.hpp"
int main(int argc, char *argv[]) {
@ -30,7 +30,7 @@ int main(int argc, char *argv[]) {
auto data_directory = std::filesystem::temp_directory_path() / "single_query_test";
memgraph::utils::OnScopeExit([&data_directory] { std::filesystem::remove_all(data_directory); });
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
memgraph::query::InterpreterContext interpreter_context{&db, memgraph::query::InterpreterConfig{}, data_directory};
memgraph::query::Interpreter interpreter{&interpreter_context};

View File

@ -269,8 +269,8 @@ target_link_libraries(${test_prefix}utils_csv_parsing mg-utils fmt)
add_unit_test(utils_async_timer.cpp)
target_link_libraries(${test_prefix}utils_async_timer mg-utils)
add_unit_test(utils_license.cpp)
target_link_libraries(${test_prefix}utils_license mg-utils mg-license)
add_unit_test(license.cpp)
target_link_libraries(${test_prefix}license mg-utils mg-license)
add_unit_test(utils_settings.cpp)
target_link_libraries(${test_prefix}utils_settings mg-utils mg-settings)

View File

@ -19,9 +19,9 @@
#include "auth/auth.hpp"
#include "auth/crypto.hpp"
#include "auth/models.hpp"
#include "license/license.hpp"
#include "utils/cast.hpp"
#include "utils/file.hpp"
#include "utils/license.hpp"
using namespace memgraph::auth;
namespace fs = std::filesystem;
@ -36,7 +36,7 @@ class AuthWithStorage : public ::testing::Test {
FLAGS_auth_password_permit_null = true;
FLAGS_auth_password_strength_regex = ".+";
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
}
virtual void TearDown() { fs::remove_all(test_folder_); }

View File

@ -15,9 +15,9 @@
#include "auth/models.hpp"
#include "glue/auth_checker.hpp"
#include "license/license.hpp"
#include "query_plan_common.hpp"
#include "storage/v2/view.hpp"
#include "utils/license.hpp"
#ifdef MG_ENTERPRISE
class FineGrainedAuthCheckerFixture : public testing::Test {
@ -39,7 +39,7 @@ class FineGrainedAuthCheckerFixture : public testing::Test {
memgraph::query::EdgeAccessor r4{*dba.InsertEdge(&v1, &v3, edge_type_two)};
void SetUp() override {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("l1")).HasValue());
ASSERT_TRUE(v2.AddLabel(dba.NameToLabel("l2")).HasValue());
ASSERT_TRUE(v3.AddLabel(dba.NameToLabel("l3")).HasValue());

View File

@ -37,7 +37,7 @@ class AuthQueryHandlerFixture : public testing::Test {
#endif
virtual void SetUp() {
memgraph::utils::EnsureDir(test_folder_);
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
}
virtual void TearDown() {

View File

@ -18,7 +18,7 @@
#include <gtest/internal/gtest-param-util-generated.h>
#include "auth/models.hpp"
#include "utils/license.hpp"
#include "license/license.hpp"
using namespace memgraph::query;
using namespace memgraph::query::plan;
@ -80,7 +80,7 @@ class FineGrainedBfsTest
std::tuple<int, int, EdgeAtom::Direction, std::vector<std::string>, bool, FineGrainedTestType>> {
public:
static void SetUpTestCase() {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
db_ = std::make_unique<VertexDb>();
}
static void TearDownTestCase() { db_ = nullptr; }

View File

@ -10,8 +10,9 @@
// licenses/APL.txt.
#include <gtest/gtest.h>
#include <cstdint>
#include "utils/license.hpp"
#include "license/license.hpp"
#include "utils/settings.hpp"
class LicenseTest : public ::testing::Test {
@ -21,7 +22,7 @@ class LicenseTest : public ::testing::Test {
settings->Initialize(settings_directory);
license_checker.emplace();
memgraph::utils::license::RegisterLicenseSettings(*license_checker, *settings);
memgraph::license::RegisterLicenseSettings(*license_checker, *settings);
license_checker->StartBackgroundLicenseChecker(*settings);
}
@ -33,24 +34,25 @@ class LicenseTest : public ::testing::Test {
const std::filesystem::path settings_directory{test_directory / "settings"};
void CheckLicenseValidity(const bool expected_valid) {
ASSERT_EQ(!license_checker->IsValidLicense(*settings).HasError(), expected_valid);
ASSERT_EQ(license_checker->IsValidLicenseFast(), expected_valid);
ASSERT_EQ(!license_checker->IsEnterpriseValid(*settings).HasError(), expected_valid);
ASSERT_EQ(license_checker->IsEnterpriseValidFast(), expected_valid);
}
std::optional<memgraph::utils::Settings> settings;
std::optional<memgraph::utils::license::LicenseChecker> license_checker;
std::optional<memgraph::license::LicenseChecker> license_checker;
};
TEST_F(LicenseTest, EncodeDecode) {
const std::array licenses = {
memgraph::utils::license::License{"Organization", 1, 2},
memgraph::utils::license::License{"", -1, 0},
memgraph::utils::license::License{"Some very long name for the organization Ltd", -999, -9999},
memgraph::license::License{"Organization", 1, 2, memgraph::license::LicenseType::OEM},
memgraph::license::License{"", -1, 0, memgraph::license::LicenseType::ENTERPRISE},
memgraph::license::License{"Some very long name for the organization Ltd", -999, -9999,
memgraph::license::LicenseType::ENTERPRISE},
};
for (const auto &license : licenses) {
const auto result = memgraph::utils::license::Encode(license);
auto maybe_license = memgraph::utils::license::Decode(result);
const auto result = memgraph::license::Encode(license);
auto maybe_license = memgraph::license::Decode(result);
ASSERT_TRUE(maybe_license);
ASSERT_EQ(*maybe_license, license);
}
@ -69,10 +71,9 @@ TEST_F(LicenseTest, TestingFlag) {
TEST_F(LicenseTest, LicenseOrganizationName) {
const std::string organization_name{"Memgraph"};
memgraph::utils::license::License license{
.organization_name = organization_name, .valid_until = 0, .memory_limit = 0};
memgraph::license::License license{organization_name, 0, 0, memgraph::license::LicenseType::ENTERPRISE};
settings->SetValue("enterprise.license", memgraph::utils::license::Encode(license));
settings->SetValue("enterprise.license", memgraph::license::Encode(license));
settings->SetValue("organization.name", organization_name);
CheckLicenseValidity(true);
@ -91,22 +92,21 @@ TEST_F(LicenseTest, Expiration) {
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch());
const auto delta = std::chrono::seconds(1);
const auto valid_until = now + delta;
memgraph::utils::license::License license{
.organization_name = organization_name, .valid_until = valid_until.count(), .memory_limit = 0};
memgraph::license::License license{organization_name, valid_until.count(), 0,
memgraph::license::LicenseType::ENTERPRISE};
settings->SetValue("enterprise.license", memgraph::utils::license::Encode(license));
settings->SetValue("enterprise.license", memgraph::license::Encode(license));
settings->SetValue("organization.name", organization_name);
CheckLicenseValidity(true);
std::this_thread::sleep_for(delta + std::chrono::seconds(1));
ASSERT_TRUE(license_checker->IsValidLicense(*settings).HasError());
ASSERT_TRUE(license_checker->IsEnterpriseValid(*settings).HasError());
// We can't check fast checker because it has unknown refresh rate
}
{
SCOPED_TRACE("License with valid_until = 0 is always valid");
memgraph::utils::license::License license{
.organization_name = organization_name, .valid_until = 0, .memory_limit = 0};
settings->SetValue("enterprise.license", memgraph::utils::license::Encode(license));
memgraph::license::License license{organization_name, 0, 0, memgraph::license::LicenseType::ENTERPRISE};
settings->SetValue("enterprise.license", memgraph::license::Encode(license));
settings->SetValue("organization.name", organization_name);
CheckLicenseValidity(true);
}
@ -116,9 +116,8 @@ TEST_F(LicenseTest, LicenseInfoOverride) {
CheckLicenseValidity(false);
const std::string organization_name{"Memgraph"};
memgraph::utils::license::License license{
.organization_name = organization_name, .valid_until = 0, .memory_limit = 0};
const std::string license_key = memgraph::utils::license::Encode(license);
memgraph::license::License license{organization_name, 0, 0, memgraph::license::LicenseType::ENTERPRISE};
const std::string license_key = memgraph::license::Encode(license);
{
SCOPED_TRACE("Checker should use overrides instead of info from the settings");
@ -139,3 +138,40 @@ TEST_F(LicenseTest, LicenseInfoOverride) {
CheckLicenseValidity(false);
}
}
TEST_F(LicenseTest, LicenseType) {
CheckLicenseValidity(false);
const std::string organization_name{"Memgraph"};
{
memgraph::license::License license_entr{organization_name, 0, 0, memgraph::license::LicenseType::ENTERPRISE};
const std::string license_key = memgraph::license::Encode(license_entr);
license_checker->SetLicenseInfoOverride(license_key, organization_name);
CheckLicenseValidity(true);
}
{
memgraph::license::License license_oem{organization_name, 0, 0, memgraph::license::LicenseType::OEM};
const std::string license_key = memgraph::license::Encode(license_oem);
license_checker->SetLicenseInfoOverride(license_key, organization_name);
CheckLicenseValidity(false);
}
{
memgraph::license::License license_oem{organization_name, 0, 0, memgraph::license::LicenseType::OEM};
const std::string license_key = memgraph::license::Encode(license_oem);
license_checker->SetLicenseInfoOverride(license_key, organization_name);
CheckLicenseValidity(false);
}
{
memgraph::license::License license_oem{organization_name, std::numeric_limits<int64_t>::min(),
std::numeric_limits<int64_t>::max(), memgraph::license::LicenseType::OEM};
const std::string license_key = memgraph::license::Encode(license_oem);
license_checker->SetLicenseInfoOverride(license_key, organization_name);
CheckLicenseValidity(false);
}
{
memgraph::license::License license_oem{organization_name, std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::min(), memgraph::license::LicenseType::OEM};
const std::string license_key = memgraph::license::Encode(license_oem);
license_checker->SetLicenseInfoOverride(license_key, organization_name);
CheckLicenseValidity(false);
}
}

View File

@ -20,11 +20,11 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "license/license.hpp"
#include "query/context.hpp"
#include "query/exceptions.hpp"
#include "query/interpret/frame.hpp"
#include "query/plan/operator.hpp"
#include "utils/license.hpp"
#include "query_plan_common.hpp"
#include "storage/v2/id_types.hpp"
@ -80,7 +80,7 @@ TEST(QueryPlan, CreateNodeWithAttributes) {
#ifdef MG_ENTERPRISE
TEST(QueryPlan, FineGrainedCreateNodeWithAttributes) {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
memgraph::query::AstStorage ast;
memgraph::query::SymbolTable symbol_table;
memgraph::storage::Storage db;
@ -164,7 +164,7 @@ TEST(QueryPlan, CreateReturn) {
#ifdef MG_ENTERPRISE
TEST(QueryPlan, FineGrainedCreateReturn) {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
// test CREATE (n:Person {age: 42}) RETURN n, n.age
memgraph::storage::Storage db;
@ -310,7 +310,7 @@ class CreateExpandWithAuthFixture : public testing::Test {
AstStorage storage;
SymbolTable symbol_table;
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); }
void ExecuteCreateExpand(bool cycle, memgraph::auth::User &user) {
const auto label_node_1 = dba.NameToLabel("Node1");
@ -470,7 +470,7 @@ class MatchCreateNodeWithAuthFixture : public testing::Test {
AstStorage storage;
SymbolTable symbol_table;
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); }
void InitGraph() {
// add three nodes we'll match and expand-create from
@ -600,7 +600,7 @@ class MatchCreateExpandWithAuthFixture : public testing::Test {
AstStorage storage;
SymbolTable symbol_table;
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); }
void InitGraph() {
// add three nodes we'll match and expand-create from
@ -818,7 +818,7 @@ class DeleteOperatorWithAuthFixture : public testing::Test {
AstStorage storage;
SymbolTable symbol_table;
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); }
void InitGraph() {
std::vector<memgraph::query::VertexAccessor> vertices;
@ -1253,7 +1253,7 @@ TEST(QueryPlan, SetLabels) {
#ifdef MG_ENTERPRISE
TEST(QueryPlan, SetLabelsWithFineGrained) {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
auto set_labels = [&](memgraph::auth::User user, memgraph::query::DbAccessor dba,
std::vector<memgraph::storage::LabelId> labels) {
ASSERT_TRUE(dba.InsertVertex().AddLabel(labels[0]).HasValue());
@ -1426,7 +1426,7 @@ TEST(QueryPlan, RemoveLabels) {
#ifdef MG_ENTERPRISE
TEST(QueryPlan, RemoveLabelsFineGrainedFiltering) {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
auto remove_labels = [&](memgraph::auth::User user, memgraph::query::DbAccessor dba,
std::vector<memgraph::storage::LabelId> labels) {
auto v1 = dba.InsertVertex();
@ -1896,7 +1896,7 @@ class UpdatePropertiesWithAuthFixture : public testing::Test {
const memgraph::storage::PropertyId edge_prop{dba.NameToProperty(edge_prop_name)};
const memgraph::storage::PropertyValue edge_prop_value{1};
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); }
void SetVertexProperty(memgraph::query::VertexAccessor vertex) {
static_cast<void>(vertex.SetProperty(entity_prop, entity_prop_value));

View File

@ -30,10 +30,10 @@
#include "auth/auth.hpp"
#include "auth/models.hpp"
#include "glue/auth_checker.hpp"
#include "license/license.hpp"
#include "query/context.hpp"
#include "query/exceptions.hpp"
#include "query/plan/operator.hpp"
#include "utils/license.hpp"
#include "utils/synchronized.hpp"
using namespace memgraph::query;
@ -50,7 +50,7 @@ class MatchReturnFixture : public testing::Test {
void AddVertices(int count) {
for (int i = 0; i < count; i++) dba.InsertVertex();
}
void SetUp() override { memgraph::utils::license::global_license_checker.EnableTesting(); }
void SetUp() override { memgraph::license::global_license_checker.EnableTesting(); }
std::vector<Path> PathResults(std::shared_ptr<Produce> &op) {
std::vector<Path> res;
@ -485,7 +485,7 @@ class ExpandFixture : public testing::Test {
ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("l1")).HasValue());
ASSERT_TRUE(v2.AddLabel(dba.NameToLabel("l2")).HasValue());
ASSERT_TRUE(v3.AddLabel(dba.NameToLabel("l3")).HasValue());
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
dba.AdvanceCommand();
}
@ -628,7 +628,7 @@ class QueryPlanExpandVariable : public testing::Test {
std::nullopt_t nullopt = std::nullopt;
void SetUp() {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
// create the graph
int chain_length = 3;
@ -1778,7 +1778,7 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test {
Symbol total_weight = symbol_table.CreateSymbol("total_weight", true);
void SetUp() {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
for (int i = 0; i < 5; i++) {
v.push_back(dba.InsertVertex());
@ -2208,7 +2208,7 @@ class QueryPlanExpandAllShortestPaths : public testing::Test {
Symbol total_weight = symbol_table.CreateSymbol("total_weight", true);
void SetUp() {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
for (int i = 0; i < 5; i++) {
v.push_back(dba.InsertVertex());

View File

@ -13,11 +13,11 @@
#include <gtest/gtest.h>
#include <unordered_map>
#include "license/license.hpp"
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/ast/ast_visitor.hpp"
#include "query/frontend/semantic/required_privileges.hpp"
#include "storage/v2/id_types.hpp"
#include "utils/license.hpp"
#include "query_common.hpp"
@ -100,7 +100,7 @@ TEST_F(TestPrivilegeExtractor, CreateIndex) {
}
#ifdef MG_ENTERPRISE
TEST_F(TestPrivilegeExtractor, AuthQuery) {
memgraph::utils::license::global_license_checker.EnableTesting();
memgraph::license::global_license_checker.EnableTesting();
auto label_privileges = std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>{};
auto edge_type_privileges =
std::vector<std::unordered_map<AuthQuery::FineGrainedPrivilege, std::vector<std::string>>>{};