Skip to content

Commit

Permalink
Merge pull request #2 from EncoreTechnologies/feature/field-delimiter…
Browse files Browse the repository at this point in the history
…s-as-parameters

Feature/field delimiters as parameters
  • Loading branch information
BlakeHensleyy authored Jul 31, 2024
2 parents ca48d40 + 6cacc88 commit e357918
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 21 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ Fluentd Input plugin for the Windows Event Log using newer Windows Event Logging
|`<storage>` | Setting for `storage` plugin for recording read position like `in_tail`'s `pos_file`.|
|`<parse>` | Setting for `parser` plugin for parsing raw XML EventLog records. |
|`parse_description`| (option) parse `description` field and set parsed result into the record. `Description` and `EventData` fields are removed|
|`description_key_delimiter`| (option) (Only applicable if parse_description is true) Change the character placed between the parent_key and key. Set the value to "" for no delimiter. Defaults to `.` .|
|`description_word_delimiter`| (option) (Only applicable if parse_description is true) Change the character placed between each word of the key. Set the value to "" for no delimiter. Defaults to `_` .|
|`downcase_description_keys`| (option) (Only applicable if parse_description is true) Specify whether to downcase the keys that are parsed from the Description. Defaults to `true`.|
|`read_from_head` | **Deprecated** (option) Start to read the entries from the oldest, not from when fluentd is started. Defaults to `false`.|
|`read_existing_events` | (option) Read the entries which already exist before fluentd is started. Defaults to `false`.|
|`render_as_xml` | (option) Render Windows EventLog as XML or Ruby Hash object directly. Defaults to `false`.|
Expand Down Expand Up @@ -276,4 +279,4 @@ If your `description` doesn't follow this format, the parsed result is only `des
### Copyright
Copyright(C) 2014- @okahashi117
### License
Apache License, Version 2.0
Apache License, Version 2.0
Binary file added fluent-plugin-windows-eventlog-0.9.0.gem
Binary file not shown.
2 changes: 1 addition & 1 deletion fluent-plugin-winevtlog.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
spec.homepage = "https://github.com/EncoreTechnologies/fluent-plugin-windows-eventlog"
spec.license = "Apache-2.0"

spec.files = `git ls-files -z`.split("\x0")
spec.files = Dir["lib/**/*.rb", "bin/*", "README*", "LICENSE", "CHANGELOG*", "spec/**/*"]
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
Expand Down
28 changes: 10 additions & 18 deletions lib/fluent/plugin/in_windows_eventlog2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ReconnectError < Fluent::UnrecoverableError; end
"Level" => ["Level", :string],
"Task" => ["Task", :string],
"Opcode" => ["Opcode", :string],
"EventType" => ["Keywords", :string], # Edited
"Keywords" => ["Keywords", :string],
"TimeCreated" => ["TimeCreated", :string],
"EventRecordID" => ["EventRecordID", :string],
"ActivityID" => ["ActivityID", :string],
Expand All @@ -40,6 +40,9 @@ class ReconnectError < Fluent::UnrecoverableError; end
config_param :read_from_head, :bool, default: false, deprecated: "Use `read_existing_events' instead."
config_param :read_existing_events, :bool, default: false
config_param :parse_description, :bool, default: false
config_param :description_key_delimiter, :string, default: "."
config_param :description_word_delimiter, :string, default: "_"
config_param :downcase_description_keys, :bool, default: true
config_param :render_as_xml, :bool, default: false
config_param :rate_limit, :integer, default: Winevt::EventLog::Subscribe::RATE_INFINITE
config_param :preserve_qualifiers_on_hash, :bool, default: false
Expand Down Expand Up @@ -360,24 +363,12 @@ def on_notify_hash(ch, subscribe)
RECORD_DELIMITER = "\r\n\t".freeze
FIELD_DELIMITER = "\t\t".freeze
NONE_FIELD_DELIMITER = "\t".freeze
SYSMON_DELIMITER = "\r\n".freeze


def parse_desc(record)
desc = record.delete("Description".freeze)
providername = record["ProviderName"]
return if desc.nil?
elems = desc.split(GROUP_DELIMITER)
elem2 = desc.split(SYSMON_DELIMITER)

if providername == "Microsoft-Windows-Sysmon"
elem2.each { |x| # Loop through each line of Sysmon event description, parsing the field name from the field value.
key, value = x.split(":", 2)
parent_key = "#{to_key(key)}"
record[parent_key] = value
}
end

elems = desc.split(GROUP_DELIMITER)
record['DescriptionTitle'] = elems.shift
previous_key = nil
elems.each { |elem|
Expand All @@ -401,7 +392,7 @@ def parse_desc(record)
elsif parent_key.nil?
record[to_key(key)] = value
else
k = "#{parent_key}#{to_key(key)}" #Edited to remove "." between words
k = "#{parent_key}#{@description_key_delimiter}#{to_key(key)}"
record[k] = value
end
end
Expand All @@ -412,10 +403,11 @@ def parse_desc(record)
}
end

def to_key(key) #Edited to remove key.downcase and '_' to camelcase
key.gsub!(' '.freeze, ''.freeze)
def to_key(key)
key.downcase! if @downcase_description_keys
key.gsub!(' '.freeze, @description_word_delimiter)
key
end
####
end
end
end
32 changes: 31 additions & 1 deletion test/plugin/test_in_windows_eventlog2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,36 @@ def test_parse_desc
assert_equal(expected, h)
end

def test_parse_desc_camelcase
d = create_driver(config_element("ROOT", "", {"tag" => "fluent.eventlog",
"parse_description" => true,
"description_key_delimiter" => "",
"description_word_delimiter" => "",
"downcase_description_keys" => false
}, [
config_element("storage", "", {
'@type' => 'local',
'persistent' => false
}),
]))
desc =<<-DESC
A user's local group membership was enumerated.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-X-Y-XX-WWWWWW-VVVV\r\n\tAccount Name:\t\tAdministrator\r\n\tAccount Domain:\t\tDESKTOP-FLUENTTEST\r\n\tLogon ID:\t\t0x3185B1\r\n\r\nUser:\r\n\tSecurity ID:\t\tS-X-Y-XX-WWWWWW-VVVV\r\n\tAccount Name:\t\tAdministrator\r\n\tAccount Domain:\t\tDESKTOP-FLUENTTEST\r\n\r\nProcess Information:\r\n\tProcess ID:\t\t0x50b8\r\n\tProcess Name:\t\tC:\\msys64\\usr\\bin\\make.exe
DESC
h = {"Description" => desc}
expected = {"DescriptionTitle" => "A user's local group membership was enumerated.",
"SubjectSecurityID" => "S-X-Y-XX-WWWWWW-VVVV",
"SubjectAccountName" => "Administrator",
"SubjectAccountDomain" => "DESKTOP-FLUENTTEST",
"SubjectLogonID" => "0x3185B1",
"UserSecurityID" => "S-X-Y-XX-WWWWWW-VVVV",
"UserAccountName" => "Administrator",
"UserAccountDomain" => "DESKTOP-FLUENTTEST",
"ProcessInformationProcessID" => "0x50b8",
"ProcessInformationProcessName" => "C:\\msys64\\usr\\bin\\make.exe"}
d.instance.parse_desc(h)
assert_equal(expected, h)
end

def test_parse_privileges_description
d = create_driver
desc = ["Special privileges assigned to new logon.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-X-Y-ZZ\r\n\t",
Expand Down Expand Up @@ -616,4 +646,4 @@ def test_write_with_winevt_xml_parser_without_qualifiers
assert_true(record.has_key?("EventData"))
assert_false(record.has_key?("Qualifiers"))
end
end
end

0 comments on commit e357918

Please sign in to comment.