diff --git a/openframe/CMakeLists.txt b/openframe/CMakeLists.txt index cbe8acc40db..316e1e4c6fe 100644 --- a/openframe/CMakeLists.txt +++ b/openframe/CMakeLists.txt @@ -15,6 +15,7 @@ function(generateOsqueryOpenframeLibrary) openframe_token_extractor.cpp openframe_token_refresher.cpp openframe_authorization_manager.cpp + openframe_machine_id_provider.cpp ) target_link_libraries(osquery_openframe PUBLIC @@ -33,6 +34,7 @@ function(generateOsqueryOpenframeLibrary) openframe_token_refresher.h openframe_authorization_manager.h openframe_authorization_manager_provider.h + openframe_machine_id_provider.h ) generateIncludeNamespace(osquery_openframe "openframe" "FILE_ONLY" ${public_header_files}) diff --git a/openframe/openframe_machine_id_provider.cpp b/openframe/openframe_machine_id_provider.cpp new file mode 100644 index 00000000000..8be27c865ce --- /dev/null +++ b/openframe/openframe_machine_id_provider.cpp @@ -0,0 +1,76 @@ +#include "openframe_machine_id_provider.h" + +#include +#include + +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +namespace osquery { + +OpenframeMachineIdProvider& OpenframeMachineIdProvider::getInstance() { + static OpenframeMachineIdProvider instance; + return instance; +} + +std::string OpenframeMachineIdProvider::getMachineId() { + if (!initialized_) { + cached_machine_id_ = readFromFile(); + initialized_ = true; + } + return cached_machine_id_; +} + +void OpenframeMachineIdProvider::refresh() { + cached_machine_id_ = readFromFile(); + initialized_ = true; +} + +std::string OpenframeMachineIdProvider::getFilePath() { +#ifdef _WIN32 + char* programData = std::getenv("ProgramData"); + if (programData == nullptr) { + return ""; + } + return std::string(programData) + "\\OpenFrame\\machine_id"; +#elif defined(__APPLE__) + return "/Library/Application Support/OpenFrame/machine_id"; +#else + return "/var/lib/openframe/machine_id"; +#endif +} + +std::string OpenframeMachineIdProvider::readFromFile() { + std::string path = getFilePath(); + if (path.empty()) { + LOG(WARNING) << "Could not determine machine_id file path"; + return ""; + } + + std::ifstream file(path); + if (!file.is_open()) { + VLOG(1) << "Could not open machine_id file: " << path; + return ""; + } + + std::stringstream buffer; + buffer << file.rdbuf(); + std::string content = buffer.str(); + boost::algorithm::trim(content); + + if (content.empty()) { + LOG(WARNING) << "Machine ID file is empty: " << path; + return ""; + } + + VLOG(1) << "Read machine ID from " << path; + return content; +} + +} // namespace osquery diff --git a/openframe/openframe_machine_id_provider.h b/openframe/openframe_machine_id_provider.h new file mode 100644 index 00000000000..a037a640b84 --- /dev/null +++ b/openframe/openframe_machine_id_provider.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include + +namespace osquery { + +class OpenframeMachineIdProvider : private boost::noncopyable { + public: + /** + * @brief Get the singleton instance + */ + static OpenframeMachineIdProvider& getInstance(); + + /** + * @brief Get the machine ID, reading from file if not cached + * + * @return The machine ID string, or empty string if not available + */ + std::string getMachineId(); + + /** + * @brief Force re-read of machine ID from file + */ + void refresh(); + + private: + OpenframeMachineIdProvider() = default; + ~OpenframeMachineIdProvider() = default; + + std::string readFromFile(); + std::string getFilePath(); + + std::string cached_machine_id_; + bool initialized_ = false; +}; + +} // namespace osquery diff --git a/osquery/remote/transports/tls.cpp b/osquery/remote/transports/tls.cpp index e10ee3ac9ac..74794fa4a72 100644 --- a/osquery/remote/transports/tls.cpp +++ b/osquery/remote/transports/tls.cpp @@ -10,6 +10,7 @@ #include "tls.h" #include "openframe/openframe_authorization_manager.h" #include "openframe/openframe_authorization_manager_provider.h" +#include "openframe/openframe_machine_id_provider.h" #include #include @@ -96,13 +97,21 @@ void TLSTransport::decorateRequest(http::Request& r) { r << http::Request::Header("Content-Type", serializer_->getContentType()); r << http::Request::Header("Accept", serializer_->getContentType()); r << http::Request::Header("User-Agent", kTLSUserAgentBase + kVersion); - + if (FLAGS_openframe_mode) { auto& auth_manager = OpenframeAuthorizationManagerProvider::getInstance(); std::string token = auth_manager.getToken(); if (!token.empty()) { r << http::Request::Header("Authorization", "Bearer " + token); } + + // Add x-machine-id header for rate limiting + auto& machine_id_provider = OpenframeMachineIdProvider::getInstance(); + std::string machine_id = machine_id_provider.getMachineId(); + if (!machine_id.empty()) { + r << http::Request::Header("x-machine-id", machine_id); + VLOG(1) << "x-machine-id header added to request"; + } } }