blob: fee896a27bfc34b0c7e54c69db6f305389d72260 [file]
/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <strsafe.h>
#include <map>
#include <functional>
#include <regex>
#include <string>
#include <utility>
#include <vector>
#include "MetadataWalker.h"
#include "XMLString.h"
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 (sid_matcher_(attr.name())) {
updateAttributeValue(attr, attr.name(), idUpdate);
}
}
const std::string node_name = node.name();
if (node_name == "Data") {
for (pugi::xml_attribute attr : node.attributes()) {
if (sid_matcher_(attr.name())) {
updateText(node, attr.name(), idUpdate);
}
if (sid_matcher_(attr.value())) {
updateText(node, attr.value(), idUpdate);
}
}
if (resolve_) {
std::string nodeText = node.text().get();
std::vector<std::string> ids = getIdentifiers(nodeText);
for (const auto &id : ids) {
auto resolved = user_id_to_username_fn_(id);
std::string replacement = "%{" + id + "}";
replaced_identifiers_[id] = resolved;
replaced_identifiers_[replacement] = resolved;
nodeText = utils::string::replaceAll(nodeText, replacement, resolved);
}
node.text().set(nodeText.c_str());
}
} else if (node_name == "TimeCreated") {
metadata_["TimeCreated"] = node.attribute("SystemTime").value();
} else if (node_name == "EventRecordID") {
metadata_["EventRecordID"] = node.text().get();
} else if (node_name == "Provider") {
metadata_["Provider"] = node.attribute("Name").value();
} else if (node_name == "EventID") {
metadata_["EventID"] = node.text().get();
} else {
static std::map<std::string, EVT_FORMAT_MESSAGE_FLAGS> formatFlagMap = {
{"Channel", EvtFormatMessageChannel}, {"Keywords", EvtFormatMessageKeyword}, {"Level", EvtFormatMessageLevel},
{"Opcode", EvtFormatMessageOpcode}, {"Task", EvtFormatMessageTask}
};
auto it = formatFlagMap.find(node_name);
if (it != formatFlagMap.end()) {
std::function<std::string(const std::string &)> updateFunc = [&](const std::string &input) -> std::string {
if (resolve_) {
auto resolved = windows_event_log_metadata_.getEventData(it->second, input);
if (!resolved.empty()) {
return resolved;
}
}
return input;
};
updateText(node, node.name(), std::move(updateFunc));
} else {
// no conversion is required here, so let the node fall through
}
}
return true;
}
std::vector<std::string> MetadataWalker::getIdentifiers(const std::string &text) {
auto pos = text.find("%{");
std::vector<std::string> found_strings;
while (pos != std::string::npos) {
auto next_pos = text.find('}', pos);
if (next_pos != std::string::npos) {
auto potential_identifier = text.substr(pos + 2, next_pos - (pos + 2));
std::smatch match;
if (potential_identifier.find("S-") != std::string::npos) {
found_strings.push_back(potential_identifier);
}
}
pos = text.find("%{", pos + 2);
}
return found_strings;
}
std::string MetadataWalker::getMetadata(Metadata metadata) const {
static constexpr auto get_from_map = [](const std::map<std::string, std::string>& map, const std::string& field) {
auto it = map.find(field);
if (it != std::end(map)) {
return it->second;
}
return std::string{"N/A"};
};
switch (metadata) {
case Metadata::LOG_NAME:
return log_name_;
case Metadata::SOURCE:
return get_from_map(metadata_, "Provider");
case Metadata::TIME_CREATED:
return windows_event_log_metadata_.getEventTimestamp();
case Metadata::EVENTID:
return get_from_map(metadata_, "EventID");
case Metadata::EVENT_RECORDID:
return get_from_map(metadata_, "EventRecordID");
case Metadata::OPCODE:
return get_from_map(metadata_, "Opcode");
case Metadata::TASK_CATEGORY:
return get_from_map(metadata_, "Task");
case Metadata::LEVEL:
return get_from_map(metadata_, "Level");
case Metadata::KEYWORDS:
return get_from_map(metadata_, "Keywords");
case Metadata::EVENT_TYPE:
return std::to_string(windows_event_log_metadata_.getEventTypeIndex());
case Metadata::COMPUTER:
return WindowsEventLogMetadata::getComputerName();
case Metadata::USER:
break;
}
return "N/A";
}
std::map<std::string, std::string> MetadataWalker::getFieldValues() const {
return fields_values_;
}
std::map<std::string, std::string> MetadataWalker::getIdentifiers() const {
return replaced_identifiers_;
}
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 = std::invoke(std::forward<Fn>(fn), previous_value);
if (new_field_value != previous_value) {
metadata_[field_name] = new_field_value;
if (update_xml_) {
node.text().set(new_field_value.c_str());
} else {
fields_values_[field_name] = new_field_value;
}
}
}
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