fluent-plugin-parser-winevt_xml 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +14 -14
- data/.travis.yml +16 -16
- data/Gemfile +4 -4
- data/LICENSE +201 -201
- data/README.md +56 -46
- data/Rakefile +10 -10
- data/appveyor.yml +24 -24
- data/fluent-plugin-parser-winevt_xml.gemspec +25 -25
- data/lib/fluent/plugin/parser_winevt_sax.rb +27 -21
- data/lib/fluent/plugin/parser_winevt_xml.rb +63 -38
- data/lib/fluent/plugin/winevt_sax_document.rb +73 -50
- data/test/data/eventlog-with-qualifiers.xml +1 -0
- data/test/data/eventlog.xml +1 -1
- data/test/helper.rb +24 -24
- data/test/plugin/test_parser_winevt_sax.rb +79 -43
- data/test/plugin/test_parser_winevt_xml.rb +80 -43
- metadata +6 -3
data/README.md
CHANGED
@@ -1,46 +1,56 @@
|
|
1
|
-
# fluent-plugin-parser-winevt_xml
|
2
|
-
|
3
|
-
[![Build status](https://ci.appveyor.com/api/projects/status/eb0capv0q70u381f/branch/master?svg=true)](https://ci.appveyor.com/project/fluent/fluent-plugin-parser-winevt-xml/branch/master)
|
4
|
-
[![Build Status](https://travis-ci.org/fluent/fluent-plugin-parser-winevt_xml.svg?branch=master)](https://travis-ci.org/fluent/fluent-plugin-parser-winevt_xml)
|
5
|
-
|
6
|
-
## Component
|
7
|
-
|
8
|
-
### Fluentd Parser plugin for XML rendered Windows EventLogs
|
9
|
-
|
10
|
-
[Fluentd](https://www.fluentd.org/) plugin to parse XML rendered Windows Event Logs.
|
11
|
-
|
12
|
-
### Installation
|
13
|
-
|
14
|
-
```
|
15
|
-
gem install fluent-plugin-parser-winevt_xml
|
16
|
-
```
|
17
|
-
|
18
|
-
## Configuration
|
19
|
-
|
20
|
-
### parser_winevt_xml
|
21
|
-
|
22
|
-
```aconf
|
23
|
-
<parse>
|
24
|
-
@type winevt_xml
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
1
|
+
# fluent-plugin-parser-winevt_xml
|
2
|
+
|
3
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/eb0capv0q70u381f/branch/master?svg=true)](https://ci.appveyor.com/project/fluent/fluent-plugin-parser-winevt-xml/branch/master)
|
4
|
+
[![Build Status](https://travis-ci.org/fluent/fluent-plugin-parser-winevt_xml.svg?branch=master)](https://travis-ci.org/fluent/fluent-plugin-parser-winevt_xml)
|
5
|
+
|
6
|
+
## Component
|
7
|
+
|
8
|
+
### Fluentd Parser plugin for XML rendered Windows EventLogs
|
9
|
+
|
10
|
+
[Fluentd](https://www.fluentd.org/) plugin to parse XML rendered Windows Event Logs.
|
11
|
+
|
12
|
+
### Installation
|
13
|
+
|
14
|
+
```
|
15
|
+
gem install fluent-plugin-parser-winevt_xml
|
16
|
+
```
|
17
|
+
|
18
|
+
## Configuration
|
19
|
+
|
20
|
+
### parser_winevt_xml
|
21
|
+
|
22
|
+
```aconf
|
23
|
+
<parse>
|
24
|
+
@type winevt_xml
|
25
|
+
preserve_qualifiers true
|
26
|
+
</parse>
|
27
|
+
```
|
28
|
+
|
29
|
+
#### preserve_qualifiers
|
30
|
+
|
31
|
+
Preserve Qualifiers key instead of calculating actual EventID with Qualifiers. Default is `true`.
|
32
|
+
|
33
|
+
### parser_winevt_sax
|
34
|
+
|
35
|
+
This plugin is a bit faster than `winevt_xml`.
|
36
|
+
|
37
|
+
```aconf
|
38
|
+
<parse>
|
39
|
+
@type winevt_sax
|
40
|
+
preserve_qualifiers true
|
41
|
+
</parse>
|
42
|
+
```
|
43
|
+
|
44
|
+
#### preserve_qualifiers
|
45
|
+
|
46
|
+
Preserve Qualifiers key instead of calculating actual EventID with Qualifiers. Default is `true`.
|
47
|
+
|
48
|
+
## Copyright
|
49
|
+
|
50
|
+
### Copyright
|
51
|
+
|
52
|
+
Copyright(C) 2019- Hiroshi Hatake, Masahiro Nakagawa
|
53
|
+
|
54
|
+
### License
|
55
|
+
|
56
|
+
Apache License, Version 2.0
|
data/Rakefile
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
require "rake/testtask"
|
3
|
-
|
4
|
-
Rake::TestTask.new(:test) do |test|
|
5
|
-
test.libs << 'lib' << 'test'
|
6
|
-
test.pattern = 'test/**/test_*.rb'
|
7
|
-
test.verbose = true
|
8
|
-
end
|
9
|
-
|
10
|
-
task default: :test
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
Rake::TestTask.new(:test) do |test|
|
5
|
+
test.libs << 'lib' << 'test'
|
6
|
+
test.pattern = 'test/**/test_*.rb'
|
7
|
+
test.verbose = true
|
8
|
+
end
|
9
|
+
|
10
|
+
task default: :test
|
data/appveyor.yml
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
version: '{build}'
|
2
|
-
|
3
|
-
# init:
|
4
|
-
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
5
|
-
|
6
|
-
install:
|
7
|
-
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
8
|
-
- ruby --version
|
9
|
-
- gem --version
|
10
|
-
- ridk.cmd exec bundle install
|
11
|
-
build: off
|
12
|
-
test_script:
|
13
|
-
- bundle exec rake test
|
14
|
-
# - bundle exec rake test TESTOPTS=-v
|
15
|
-
|
16
|
-
branches:
|
17
|
-
only:
|
18
|
-
- master
|
19
|
-
|
20
|
-
# https://www.appveyor.com/docs/installed-software/#ruby
|
21
|
-
environment:
|
22
|
-
matrix:
|
23
|
-
- ruby_version: "24-x64"
|
24
|
-
- ruby_version: "24"
|
1
|
+
version: '{build}'
|
2
|
+
|
3
|
+
# init:
|
4
|
+
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
5
|
+
|
6
|
+
install:
|
7
|
+
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
8
|
+
- ruby --version
|
9
|
+
- gem --version
|
10
|
+
- ridk.cmd exec bundle install
|
11
|
+
build: off
|
12
|
+
test_script:
|
13
|
+
- bundle exec rake test
|
14
|
+
# - bundle exec rake test TESTOPTS=-v
|
15
|
+
|
16
|
+
branches:
|
17
|
+
only:
|
18
|
+
- master
|
19
|
+
|
20
|
+
# https://www.appveyor.com/docs/installed-software/#ruby
|
21
|
+
environment:
|
22
|
+
matrix:
|
23
|
+
- ruby_version: "24-x64"
|
24
|
+
- ruby_version: "24"
|
@@ -1,25 +1,25 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "fluent-plugin-parser-winevt_xml"
|
7
|
-
spec.version = "0.2.
|
8
|
-
spec.authors = ["Hiroshi Hatake", "Masahiro Nakagawa"]
|
9
|
-
spec.email = ["cosmo0920.oucc@gmail.com", "repeatedly@gmail.com"]
|
10
|
-
spec.summary = %q{Fluentd Parser plugin to parse XML rendered windows event log.}
|
11
|
-
spec.description = %q{Fluentd Parser plugin to parse XML rendered windows event log.}
|
12
|
-
spec.homepage = "https://github.com/fluent/fluent-plugin-parser-winevt_xml"
|
13
|
-
spec.license = "Apache-2.0"
|
14
|
-
|
15
|
-
spec.files = `git ls-files -z`.split("\x0")
|
16
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
-
spec.require_paths = ["lib"]
|
19
|
-
|
20
|
-
spec.add_development_dependency "bundler"
|
21
|
-
spec.add_development_dependency "rake"
|
22
|
-
spec.add_development_dependency "test-unit", "~> 3.2.0"
|
23
|
-
spec.add_runtime_dependency "fluentd", [">= 0.14.12", "< 2"]
|
24
|
-
spec.add_runtime_dependency "nokogiri", "~> 1.10"
|
25
|
-
end
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "fluent-plugin-parser-winevt_xml"
|
7
|
+
spec.version = "0.2.1"
|
8
|
+
spec.authors = ["Hiroshi Hatake", "Masahiro Nakagawa"]
|
9
|
+
spec.email = ["cosmo0920.oucc@gmail.com", "repeatedly@gmail.com"]
|
10
|
+
spec.summary = %q{Fluentd Parser plugin to parse XML rendered windows event log.}
|
11
|
+
spec.description = %q{Fluentd Parser plugin to parse XML rendered windows event log.}
|
12
|
+
spec.homepage = "https://github.com/fluent/fluent-plugin-parser-winevt_xml"
|
13
|
+
spec.license = "Apache-2.0"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
spec.add_development_dependency "test-unit", "~> 3.2.0"
|
23
|
+
spec.add_runtime_dependency "fluentd", [">= 0.14.12", "< 2"]
|
24
|
+
spec.add_runtime_dependency "nokogiri", "~> 1.10"
|
25
|
+
end
|
@@ -1,21 +1,27 @@
|
|
1
|
-
require 'fluent/plugin/parser'
|
2
|
-
require 'fluent/plugin/winevt_sax_document'
|
3
|
-
require 'nokogiri'
|
4
|
-
|
5
|
-
module Fluent::Plugin
|
6
|
-
class WinevtSAXparser < Parser
|
7
|
-
Fluent::Plugin.register_parser('winevt_sax', self)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
1
|
+
require 'fluent/plugin/parser'
|
2
|
+
require 'fluent/plugin/winevt_sax_document'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module Fluent::Plugin
|
6
|
+
class WinevtSAXparser < Parser
|
7
|
+
Fluent::Plugin.register_parser('winevt_sax', self)
|
8
|
+
|
9
|
+
config_param :preserve_qualifiers, :bool, default: true
|
10
|
+
|
11
|
+
def winevt_xml?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def preserve_qualifiers?
|
16
|
+
@preserve_qualifiers
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse(text)
|
20
|
+
evtxml = WinevtXMLDocument.new(@preserve_qualifiers)
|
21
|
+
parser = Nokogiri::XML::SAX::Parser.new(evtxml)
|
22
|
+
parser.parse(text)
|
23
|
+
time = @estimate_current_event ? Fluent::EventTime.now : nil
|
24
|
+
yield time, evtxml.result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,38 +1,63 @@
|
|
1
|
-
require 'fluent/plugin/parser'
|
2
|
-
require 'nokogiri'
|
3
|
-
|
4
|
-
module Fluent::Plugin
|
5
|
-
class WinevtXMLparser < Parser
|
6
|
-
Fluent::Plugin.register_parser('winevt_xml', self)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
1
|
+
require 'fluent/plugin/parser'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module Fluent::Plugin
|
5
|
+
class WinevtXMLparser < Parser
|
6
|
+
Fluent::Plugin.register_parser('winevt_xml', self)
|
7
|
+
|
8
|
+
config_param :preserve_qualifiers, :bool, default: true
|
9
|
+
|
10
|
+
def winevt_xml?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def preserve_qualifiers?
|
15
|
+
@preserve_qualifiers
|
16
|
+
end
|
17
|
+
|
18
|
+
def MAKELONG(low, high)
|
19
|
+
(low & 0xffff) | (high & 0xffff) << 16
|
20
|
+
end
|
21
|
+
|
22
|
+
def event_id(system_elem)
|
23
|
+
return (system_elem/'EventID').text rescue nil if @preserve_qualifiers
|
24
|
+
|
25
|
+
qualifiers = (system_elem/'EventID').attribute("Qualifiers").text rescue nil
|
26
|
+
if qualifiers
|
27
|
+
event_id = (system_elem/'EventID').text
|
28
|
+
event_id = MAKELONG(event_id.to_i, qualifiers.to_i)
|
29
|
+
event_id.to_s
|
30
|
+
else
|
31
|
+
(system_elem/'EventID').text rescue nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse(text)
|
36
|
+
record = {}
|
37
|
+
doc = Nokogiri::XML(text)
|
38
|
+
system_elem = doc/'Event'/'System'
|
39
|
+
record["ProviderName"] = (system_elem/"Provider").attribute("Name").text rescue nil
|
40
|
+
record["ProviderGUID"] = (system_elem/"Provider").attribute("Guid").text rescue nil
|
41
|
+
if @preserve_qualifiers
|
42
|
+
record["Qualifiers"] = (system_elem/'EventID').attribute("Qualifiers").text rescue nil
|
43
|
+
end
|
44
|
+
record["EventID"] = event_id(system_elem)
|
45
|
+
record["Level"] = (system_elem/'Level').text rescue nil
|
46
|
+
record["Task"] = (system_elem/'Task').text rescue nil
|
47
|
+
record["Opcode"] = (system_elem/'Opcode').text rescue nil
|
48
|
+
record["Keywords"] = (system_elem/'Keywords').text rescue nil
|
49
|
+
record["TimeCreated"] = (system_elem/'TimeCreated').attribute("SystemTime").text rescue nil
|
50
|
+
record["EventRecordID"] = (system_elem/'EventRecordID').text rescue nil
|
51
|
+
record["ActivityID"] = (system_elem/'Correlation').attribute('ActivityID').text rescue nil
|
52
|
+
record["RelatedActivityID"] = (system_elem/'Correlation').attribute("RelatedActivityID").text rescue nil
|
53
|
+
record["ThreadID"] = (system_elem/'Execution').attribute("ThreadID").text rescue nil
|
54
|
+
record["ProcessID"] = (system_elem/'Execution').attribute("ProcessID").text rescue nil
|
55
|
+
record["Channel"] = (system_elem/'Channel').text rescue nil
|
56
|
+
record["Computer"] = (system_elem/"Computer").text rescue nil
|
57
|
+
record["UserID"] = (system_elem/'Security').attribute("UserID").text rescue nil
|
58
|
+
record["Version"] = (system_elem/'Version').text rescue nil
|
59
|
+
time = @estimate_current_event ? Fluent::EventTime.now : nil
|
60
|
+
yield time, record
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,50 +1,73 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
|
3
|
-
class WinevtXMLDocument < Nokogiri::XML::SAX::Document
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
@
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
def
|
16
|
-
@
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@result[
|
21
|
-
|
22
|
-
@result[
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
@result[
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
class WinevtXMLDocument < Nokogiri::XML::SAX::Document
|
4
|
+
def initialize(preserve_qualifiers)
|
5
|
+
@stack = []
|
6
|
+
@result = {}
|
7
|
+
@preserve_qualifiers = preserve_qualifiers
|
8
|
+
super()
|
9
|
+
end
|
10
|
+
|
11
|
+
def MAKELONG(low, high)
|
12
|
+
(low & 0xffff) | (high & 0xffff) << 16
|
13
|
+
end
|
14
|
+
|
15
|
+
def event_id
|
16
|
+
if @result.has_key?("Qualifiers")
|
17
|
+
qualifiers = @result.delete("Qualifiers")
|
18
|
+
event_id = @result['EventID']
|
19
|
+
event_id = MAKELONG(event_id.to_i, qualifiers.to_i)
|
20
|
+
@result['EventID'] = event_id.to_s
|
21
|
+
else
|
22
|
+
@result['EventID']
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def result
|
27
|
+
return @result if @preserve_qualifiers
|
28
|
+
|
29
|
+
if @result
|
30
|
+
@result['EventID'] = event_id
|
31
|
+
end
|
32
|
+
@result
|
33
|
+
end
|
34
|
+
|
35
|
+
def start_document
|
36
|
+
end
|
37
|
+
|
38
|
+
def start_element(name, attributes = [])
|
39
|
+
@stack << name
|
40
|
+
|
41
|
+
if name == "Provider"
|
42
|
+
@result["ProviderName"] = attributes[0][1] rescue nil
|
43
|
+
@result["ProviderGUID"] = attributes[1][1] rescue nil
|
44
|
+
elsif name == "EventID"
|
45
|
+
@result["Qualifiers"] = attributes[0][1] rescue nil
|
46
|
+
elsif name == "TimeCreated"
|
47
|
+
@result["TimeCreated"] = attributes[0][1] rescue nil
|
48
|
+
elsif name == "Correlation"
|
49
|
+
@result["ActivityID"] = attributes[0][1] rescue nil
|
50
|
+
@result["RelatedActivityID"] = attributes[1][1] rescue nil
|
51
|
+
elsif name == "Execution"
|
52
|
+
@result["ProcessID"] = attributes[0][1] rescue nil
|
53
|
+
@result["ThreadID"] = attributes[1][1] rescue nil
|
54
|
+
elsif name == "Security"
|
55
|
+
@result["UserID"] = attributes[0][1] rescue nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def characters(string)
|
60
|
+
element = @stack.last
|
61
|
+
|
62
|
+
if /^EventID|Level|Task|Opcode|Keywords|EventRecordID|
|
63
|
+
ActivityID|Channel|Computer|Security|Version$/ === element
|
64
|
+
@result[element] = string
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def end_element(name, attributes = [])
|
69
|
+
end
|
70
|
+
|
71
|
+
def end_document
|
72
|
+
end
|
73
|
+
end
|