This is an automated email from the ASF dual-hosted git repository. szaszm pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
commit dc3239dbf34c3a8beb65f52ea6ebf271b358d67a Author: Adam Debreceni <[email protected]> AuthorDate: Tue Aug 8 13:26:16 2023 +0200 MINIFICPP-2143 Resolve Security/UserID attribute Closes #1601 Signed-off-by: Marton Szasz <[email protected]> --- .../tests/ConsumeWindowsEventLogTests.cpp | 4 +- .../tests/MetadataWalkerTests.cpp | 15 +++++++ .../tests/resources/invalidxml.xml | 2 +- .../tests/resources/multiplesids.xml | 2 +- .../tests/resources/nobodysid.xml | 2 +- .../windows-event-log/tests/resources/nodata.xml | 2 +- .../resources/{withsids.xml => resolveduserid.xml} | 4 +- .../tests/resources/unknownsid.xml | 2 +- .../tests/resources/{nobodysid.xml => userid.xml} | 4 +- .../windows-event-log/tests/resources/withsids.xml | 2 +- extensions/windows-event-log/wel/JSONUtils.cpp | 6 +++ .../windows-event-log/wel/MetadataWalker.cpp | 48 ++++++++++++++++------ extensions/windows-event-log/wel/MetadataWalker.h | 7 +++- 13 files changed, 74 insertions(+), 26 deletions(-) diff --git a/extensions/windows-event-log/tests/ConsumeWindowsEventLogTests.cpp b/extensions/windows-event-log/tests/ConsumeWindowsEventLogTests.cpp index 285d0abd8..b0dfd1d42 100644 --- a/extensions/windows-event-log/tests/ConsumeWindowsEventLogTests.cpp +++ b/extensions/windows-event-log/tests/ConsumeWindowsEventLogTests.cpp @@ -539,12 +539,12 @@ TEST_CASE("ConsumeWindowsEventLog Simple JSON works with UserData", "[cwel][json REQUIRE(doc.load_string(event_xml)); SECTION("simple") { const auto simple_json = jsonToString(toSimpleJSON(doc)); - const auto expected_json = R"json({"System":{"Provider":{"Name":"Microsoft-Windows-AppLocker","Guid":"CBDA4DBF-8D5D-4F69-9578-BE14AA540D22"},"EventID":"8002","Version":"0","Level":"4","Task":"0","Opcode":"0","Keywords":"0x8000000000000000","TimeCreated":{"SystemTime":"2023-02-06T16:58:09.008534Z"},"EventRecordID":"46","Correlation":{},"Execution":{"ProcessID":"1234","ThreadID":"1235"},"Channel":"Microsoft-Windows-AppLocker/EXE and DLL","Computer":"example.local"},"EventData":[],"User [...] + const auto expected_json = R"json({"System":{"Provider":{"Name":"Microsoft-Windows-AppLocker","Guid":"CBDA4DBF-8D5D-4F69-9578-BE14AA540D22"},"EventID":"8002","Version":"0","Level":"4","Task":"0","Opcode":"0","Keywords":"0x8000000000000000","TimeCreated":{"SystemTime":"2023-02-06T16:58:09.008534Z"},"EventRecordID":"46","Correlation":{},"Execution":{"ProcessID":"1234","ThreadID":"1235"},"Channel":"Microsoft-Windows-AppLocker/EXE and DLL","Computer":"example.local","Security":{"UserID": [...] CHECK(expected_json == simple_json); } SECTION("flattened") { const auto flattened_json = jsonToString(toFlattenedJSON(doc)); - const auto expected_json = R"json({"Name":"Microsoft-Windows-AppLocker","Guid":"CBDA4DBF-8D5D-4F69-9578-BE14AA540D22","EventID":"8002","Version":"0","Level":"4","Task":"0","Opcode":"0","Keywords":"0x8000000000000000","SystemTime":"2023-02-06T16:58:09.008534Z","EventRecordID":"46","ProcessID":"1234","ThreadID":"1235","Channel":"Microsoft-Windows-AppLocker/EXE and DLL","Computer":"example.local","UserData.RuleAndFileData.PolicyNameLength":"3","UserData.RuleAndFileData.PolicyName":"EXE" [...] + const auto expected_json = R"json({"Name":"Microsoft-Windows-AppLocker","Guid":"CBDA4DBF-8D5D-4F69-9578-BE14AA540D22","EventID":"8002","Version":"0","Level":"4","Task":"0","Opcode":"0","Keywords":"0x8000000000000000","SystemTime":"2023-02-06T16:58:09.008534Z","EventRecordID":"46","ProcessID":"1234","ThreadID":"1235","Channel":"Microsoft-Windows-AppLocker/EXE and DLL","Computer":"example.local","UserID":"S-1-1-0","UserData.RuleAndFileData.PolicyNameLength":"3","UserData.RuleAndFileDat [...] CHECK(expected_json == flattened_json); } } diff --git a/extensions/windows-event-log/tests/MetadataWalkerTests.cpp b/extensions/windows-event-log/tests/MetadataWalkerTests.cpp index 4dec8a544..796a8c252 100644 --- a/extensions/windows-event-log/tests/MetadataWalkerTests.cpp +++ b/extensions/windows-event-log/tests/MetadataWalkerTests.cpp @@ -95,6 +95,21 @@ TEST_CASE("MetadataWalker updates the Sid in the XML if both update_xml and reso } } + +TEST_CASE("MetadataWalker updates the Security/UserId attribute", "[updateXmlMetadata][userid]") { + std::string xml = readFile("resources/userid.xml"); + + SECTION("No resolution") { + REQUIRE(updateXmlMetadata(xml, nullptr, nullptr, false, true) == formatXml(xml)); + } + + SECTION("Resolve nobody") { + std::string nobody = readFile("resources/resolveduserid.xml"); + auto regex = utils::Regex("(.*Sid)|UserID"); + REQUIRE(updateXmlMetadata(xml, nullptr, nullptr, true, true, ®ex) == formatXml(nobody)); + } +} + TEST_CASE("MetadataWalker works even when there is no Data block", "[updateXmlMetadata]") { std::string xml = readFile("resources/nodata.xml"); diff --git a/extensions/windows-event-log/tests/resources/invalidxml.xml b/extensions/windows-event-log/tests/resources/invalidxml.xml index dbcba62f9..f30f8f5ec 100644 --- a/extensions/windows-event-log/tests/resources/invalidxml.xml +++ b/extensions/windows-event-log/tests/resources/invalidxml.xml @@ -14,4 +14,4 @@ <Execution ProcessID="840" ThreadID="11544" /> <Channel>Security</Channel> <Computer>TestComputer</Computer> - <Security /> >>>>> \ No newline at end of file + <Security /> >>>>> diff --git a/extensions/windows-event-log/tests/resources/multiplesids.xml b/extensions/windows-event-log/tests/resources/multiplesids.xml index b5c35b56c..8afdeaffd 100644 --- a/extensions/windows-event-log/tests/resources/multiplesids.xml +++ b/extensions/windows-event-log/tests/resources/multiplesids.xml @@ -21,4 +21,4 @@ <Data Name="PrivilegeList">SeAssignPrimaryTokenPrivilege SeTcbPrivilege SeSecurityPrivilege SeTakeOwnershipPrivilege SeLoadDriverPrivilege SeBackupPrivilege SeRestorePrivilege SeDebugPrivilege SeAuditPrivilege SeSystemEnvironmentPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege</Data> <Data Name="GroupMembership">%{S-1-0-0} %{S-1-1-0} %{S-1-0}</Data> </EventData> - </Event> \ No newline at end of file + </Event> diff --git a/extensions/windows-event-log/tests/resources/nobodysid.xml b/extensions/windows-event-log/tests/resources/nobodysid.xml index a248989f3..b25e124fa 100644 --- a/extensions/windows-event-log/tests/resources/nobodysid.xml +++ b/extensions/windows-event-log/tests/resources/nobodysid.xml @@ -20,4 +20,4 @@ <Data Name="SubjectUserSid">S-1-0-0</Data> <Data Name="PrivilegeList">SeAssignPrimaryTokenPrivilege SeTcbPrivilege SeSecurityPrivilege SeTakeOwnershipPrivilege SeLoadDriverPrivilege SeBackupPrivilege SeRestorePrivilege SeDebugPrivilege SeAuditPrivilege SeSystemEnvironmentPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege</Data> </EventData> - </Event> \ No newline at end of file + </Event> diff --git a/extensions/windows-event-log/tests/resources/nodata.xml b/extensions/windows-event-log/tests/resources/nodata.xml index 790580baa..d3484fe08 100644 --- a/extensions/windows-event-log/tests/resources/nodata.xml +++ b/extensions/windows-event-log/tests/resources/nodata.xml @@ -16,4 +16,4 @@ <Computer>TestComputer</Computer> <Security /> </System> - </Event> \ No newline at end of file + </Event> diff --git a/extensions/windows-event-log/tests/resources/withsids.xml b/extensions/windows-event-log/tests/resources/resolveduserid.xml similarity index 96% copy from extensions/windows-event-log/tests/resources/withsids.xml copy to extensions/windows-event-log/tests/resources/resolveduserid.xml index 29d33230d..2f626ba4f 100644 --- a/extensions/windows-event-log/tests/resources/withsids.xml +++ b/extensions/windows-event-log/tests/resources/resolveduserid.xml @@ -14,10 +14,10 @@ <Execution ProcessID="840" ThreadID="11544" /> <Channel>Security</Channel> <Computer>TestComputer</Computer> - <Security /> + <Security UserID="Nobody"/> </System> <EventData> <Data Name="SubjectUserSid">Nobody</Data> <Data Name="PrivilegeList">SeAssignPrimaryTokenPrivilege SeTcbPrivilege SeSecurityPrivilege SeTakeOwnershipPrivilege SeLoadDriverPrivilege SeBackupPrivilege SeRestorePrivilege SeDebugPrivilege SeAuditPrivilege SeSystemEnvironmentPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege</Data> </EventData> - </Event> \ No newline at end of file + </Event> diff --git a/extensions/windows-event-log/tests/resources/unknownsid.xml b/extensions/windows-event-log/tests/resources/unknownsid.xml index 169944ed9..02b16da05 100644 --- a/extensions/windows-event-log/tests/resources/unknownsid.xml +++ b/extensions/windows-event-log/tests/resources/unknownsid.xml @@ -20,4 +20,4 @@ <Data Name="SubjectUserSid">S-1-8-6-5-3-0-9</Data> <Data Name="PrivilegeList">SeAssignPrimaryTokenPrivilege SeTcbPrivilege SeSecurityPrivilege SeTakeOwnershipPrivilege SeLoadDriverPrivilege SeBackupPrivilege SeRestorePrivilege SeDebugPrivilege SeAuditPrivilege SeSystemEnvironmentPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege</Data> </EventData> - </Event> \ No newline at end of file + </Event> diff --git a/extensions/windows-event-log/tests/resources/nobodysid.xml b/extensions/windows-event-log/tests/resources/userid.xml similarity index 96% copy from extensions/windows-event-log/tests/resources/nobodysid.xml copy to extensions/windows-event-log/tests/resources/userid.xml index a248989f3..06a03257d 100644 --- a/extensions/windows-event-log/tests/resources/nobodysid.xml +++ b/extensions/windows-event-log/tests/resources/userid.xml @@ -14,10 +14,10 @@ <Execution ProcessID="840" ThreadID="11544" /> <Channel>Security</Channel> <Computer>TestComputer</Computer> - <Security /> + <Security UserID="S-1-0-0"/> </System> <EventData> <Data Name="SubjectUserSid">S-1-0-0</Data> <Data Name="PrivilegeList">SeAssignPrimaryTokenPrivilege SeTcbPrivilege SeSecurityPrivilege SeTakeOwnershipPrivilege SeLoadDriverPrivilege SeBackupPrivilege SeRestorePrivilege SeDebugPrivilege SeAuditPrivilege SeSystemEnvironmentPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege</Data> </EventData> - </Event> \ No newline at end of file + </Event> diff --git a/extensions/windows-event-log/tests/resources/withsids.xml b/extensions/windows-event-log/tests/resources/withsids.xml index 29d33230d..88babbd5d 100644 --- a/extensions/windows-event-log/tests/resources/withsids.xml +++ b/extensions/windows-event-log/tests/resources/withsids.xml @@ -20,4 +20,4 @@ <Data Name="SubjectUserSid">Nobody</Data> <Data Name="PrivilegeList">SeAssignPrimaryTokenPrivilege SeTcbPrivilege SeSecurityPrivilege SeTakeOwnershipPrivilege SeLoadDriverPrivilege SeBackupPrivilege SeRestorePrivilege SeDebugPrivilege SeAuditPrivilege SeSystemEnvironmentPrivilege SeImpersonatePrivilege SeDelegateSessionUserImpersonatePrivilege</Data> </EventData> - </Event> \ No newline at end of file + </Event> diff --git a/extensions/windows-event-log/wel/JSONUtils.cpp b/extensions/windows-event-log/wel/JSONUtils.cpp index 0f2913d62..107d47571 100644 --- a/extensions/windows-event-log/wel/JSONUtils.cpp +++ b/extensions/windows-event-log/wel/JSONUtils.cpp @@ -154,6 +154,12 @@ rapidjson::Document toJSONImpl(const pugi::xml_node& root, bool flatten) { system.AddMember("Channel", rapidjson::StringRef(system_xml.child("Channel").text().get()), doc.GetAllocator()); system.AddMember("Computer", rapidjson::StringRef(system_xml.child("Computer").text().get()), doc.GetAllocator()); + + { + auto security_xml = system_xml.child("Security"); + auto& security = flatten ? doc : system.AddMember("Security", rapidjson::kObjectType, doc.GetAllocator())["Security"]; + security.AddMember("UserID", rapidjson::StringRef(security_xml.attribute("UserID").value()), doc.GetAllocator()); + } } { diff --git a/extensions/windows-event-log/wel/MetadataWalker.cpp b/extensions/windows-event-log/wel/MetadataWalker.cpp index 2181db17c..11c2fc75c 100644 --- a/extensions/windows-event-log/wel/MetadataWalker.cpp +++ b/extensions/windows-event-log/wel/MetadataWalker.cpp @@ -33,20 +33,25 @@ namespace org::apache::nifi::minifi::wel { bool MetadataWalker::for_each(pugi::xml_node &node) { // don't shortcut resolution here so that we can log attributes. + const auto idUpdate = [&](const std::string &input) { + if (resolve_) { + auto resolved = user_id_to_username_fn_(input); + replaced_identifiers_[input] = resolved; + return resolved; + } + + replaced_identifiers_[input] = input; + return input; + }; + for (pugi::xml_attribute attr : node.attributes()) { + if (regex_ && utils::regexMatch(attr.name(), *regex_)) { + updateAttributeValue(attr, attr.name(), idUpdate); + } + } + const std::string node_name = node.name(); if (node_name == "Data") { for (pugi::xml_attribute attr : node.attributes()) { - const auto idUpdate = [&](const std::string &input) { - if (resolve_) { - auto resolved = user_id_to_username_fn_(input); - replaced_identifiers_[input] = resolved; - return resolved; - } - - replaced_identifiers_[input] = input; - return input; - }; - if (regex_ && utils::regexMatch(attr.name(), *regex_)) { updateText(node, attr.name(), idUpdate); } @@ -158,9 +163,11 @@ std::string MetadataWalker::to_string(const wchar_t* pChar) { return std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(pChar); } -void MetadataWalker::updateText(pugi::xml_node &node, const std::string &field_name, std::function<std::string(const std::string &)> &&fn) { +template<typename Fn> +requires std::is_convertible_v<std::invoke_result_t<Fn, std::string>, std::string> +void MetadataWalker::updateText(pugi::xml_node &node, const std::string &field_name, Fn &&fn) { std::string previous_value = node.text().get(); - auto new_field_value = fn(previous_value); + auto new_field_value = std::invoke(std::forward<Fn>(fn), previous_value); if (new_field_value != previous_value) { metadata_[field_name] = new_field_value; if (update_xml_) { @@ -171,4 +178,19 @@ void MetadataWalker::updateText(pugi::xml_node &node, const std::string &field_n } } +template<typename Fn> +requires std::is_convertible_v<std::invoke_result_t<Fn, std::string>, std::string> +void MetadataWalker::updateAttributeValue(pugi::xml_attribute &attr, const std::string &field_name, Fn &&fn) { + std::string previous_value = attr.value(); + auto new_field_value = std::invoke(std::forward<Fn>(fn), previous_value); + if (new_field_value != previous_value) { + metadata_[field_name] = new_field_value; + if (update_xml_) { + attr.set_value(new_field_value.c_str()); + } else { + fields_values_[field_name] = new_field_value; + } + } +} + } // namespace org::apache::nifi::minifi::wel diff --git a/extensions/windows-event-log/wel/MetadataWalker.h b/extensions/windows-event-log/wel/MetadataWalker.h index a2d949338..869e254f1 100644 --- a/extensions/windows-event-log/wel/MetadataWalker.h +++ b/extensions/windows-event-log/wel/MetadataWalker.h @@ -87,7 +87,12 @@ class MetadataWalker : public pugi::xml_tree_walker { /** * Updates text within the XML representation */ - void updateText(pugi::xml_node &node, const std::string &field_name, std::function<std::string(const std::string &)> &&fn); + template<typename Fn> + requires std::is_convertible_v<std::invoke_result_t<Fn, std::string>, std::string> + void updateText(pugi::xml_node &node, const std::string &field_name, Fn &&fn); + template<typename Fn> + requires std::is_convertible_v<std::invoke_result_t<Fn, std::string>, std::string> + void updateAttributeValue(pugi::xml_attribute &node, const std::string &field_name, Fn &&fn); const WindowsEventLogMetadata& windows_event_log_metadata_; const std::string log_name_;
