This is an automated email from the ASF dual-hosted git repository. fgerlits pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
commit 2e394616de4660e2ba62d85d8227baae144ab4f0 Author: Adam Markovics <[email protected]> AuthorDate: Thu Feb 17 13:34:47 2022 +0100 MINIFICPP-1754 - Always include agentManifestIdentifier in heartbeat Signed-off-by: Ferenc Gerlits <[email protected]> This closes #1269 --- extensions/http-curl/tests/HTTPHandlers.h | 7 +++++++ libminifi/include/core/state/Value.h | 2 ++ .../include/core/state/nodes/AgentInformation.h | 24 ++++++++++++++++------ libminifi/src/core/state/Value.cpp | 23 +++++++++++++++++++++ 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/extensions/http-curl/tests/HTTPHandlers.h b/extensions/http-curl/tests/HTTPHandlers.h index b198677..093deca 100644 --- a/extensions/http-curl/tests/HTTPHandlers.h +++ b/extensions/http-curl/tests/HTTPHandlers.h @@ -426,6 +426,13 @@ class HeartbeatHandler : public ServerAwareHandler { assert(root.HasMember("agentInfo")); assert(root["agentInfo"].HasMember("agentManifest")); assert(root["agentInfo"]["agentManifest"].HasMember("bundles")); + assert(root["agentInfo"].HasMember("agentManifestHash")); + const std::string manifestHash = root["agentInfo"]["agentManifestHash"].GetString(); + assert(manifestHash.length() == 128); + + // throws if not a valid hexadecimal hash + const auto hashVec = utils::StringUtils::from_hex(manifestHash); + assert(hashVec.size() == 64); for (auto &bundle : root["agentInfo"]["agentManifest"]["bundles"].GetArray()) { assert(bundle.HasMember("artifact")); diff --git a/libminifi/include/core/state/Value.h b/libminifi/include/core/state/Value.h index d8f8995..8aa2702 100644 --- a/libminifi/include/core/state/Value.h +++ b/libminifi/include/core/state/Value.h @@ -571,6 +571,8 @@ struct SerializedResponseNode { } }; +std::string hashResponseNodes(const std::vector<SerializedResponseNode>& nodes); + } // namespace response } // namespace state } // namespace minifi diff --git a/libminifi/include/core/state/nodes/AgentInformation.h b/libminifi/include/core/state/nodes/AgentInformation.h index 8eb0fa4..fb54e2e 100644 --- a/libminifi/include/core/state/nodes/AgentInformation.h +++ b/libminifi/include/core/state/nodes/AgentInformation.h @@ -600,12 +600,8 @@ class AgentMonitor { */ class AgentManifest : public DeviceInformation { public: - AgentManifest(const std::string& name, const utils::Identifier& uuid) - : DeviceInformation(name, uuid) { - } - - AgentManifest(const std::string &name) // NOLINT - : DeviceInformation(name) { + explicit AgentManifest(std::string name) + : DeviceInformation(std::move(name)) { } std::string getName() const { @@ -710,6 +706,11 @@ class AgentNode : public DeviceInformation, public AgentMonitor, public AgentIde serialized.push_back(agentClass); } + SerializedResponseNode agentManifestHash; + agentManifestHash.name = "agentManifestHash"; + agentManifestHash.value = getAgentManifestHash(); + serialized.push_back(agentManifestHash); + return serialized; } @@ -720,6 +721,14 @@ class AgentNode : public DeviceInformation, public AgentMonitor, public AgentIde return std::vector<SerializedResponseNode>{ agentManifest }; } + std::string getAgentManifestHash() { + if (!agentManifestHash_.has_value()) { + agentManifestHash_ = hashResponseNodes(getAgentManifest()); + } + + return *agentManifestHash_; + } + std::vector<SerializedResponseNode> getAgentStatus() const { std::vector<SerializedResponseNode> serialized; @@ -736,6 +745,9 @@ class AgentNode : public DeviceInformation, public AgentMonitor, public AgentIde serialized.push_back(agentStatus); return serialized; } + + private: + std::optional<std::string> agentManifestHash_; }; /** diff --git a/libminifi/src/core/state/Value.cpp b/libminifi/src/core/state/Value.cpp index 986ed55..49cc8fd 100644 --- a/libminifi/src/core/state/Value.cpp +++ b/libminifi/src/core/state/Value.cpp @@ -17,6 +17,7 @@ */ #include "core/state/Value.h" +#include <openssl/sha.h> #include <utility> #include <string> @@ -35,6 +36,28 @@ const std::type_index Value::BOOL_TYPE = std::type_index(typeid(bool)); const std::type_index Value::DOUBLE_TYPE = std::type_index(typeid(double)); const std::type_index Value::STRING_TYPE = std::type_index(typeid(std::string)); +void hashNode(const SerializedResponseNode& node, SHA512_CTX& ctx) { + SHA512_Update(&ctx, node.name.c_str(), node.name.length()); + const auto valueStr = node.value.to_string(); + SHA512_Update(&ctx, valueStr.c_str(), valueStr.length()); + SHA512_Update(&ctx, &node.array, sizeof(node.array)); + SHA512_Update(&ctx, &node.collapsible, sizeof(node.collapsible)); + for (const auto& child : node.children) { + hashNode(child, ctx); + } +} + +std::string hashResponseNodes(const std::vector<SerializedResponseNode>& nodes) { + SHA512_CTX ctx; + SHA512_Init(&ctx); + for (const auto& node : nodes) { + hashNode(node, ctx); + } + std::array<std::byte, SHA512_DIGEST_LENGTH> digest{}; + SHA512_Final(reinterpret_cast<unsigned char*>(digest.data()), &ctx); + return utils::StringUtils::to_hex(digest, true /*uppercase*/); +} + } /* namespace response */ } /* namespace state */ } /* namespace minifi */
