logstash-codec-cef 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/CONTRIBUTORS +1 -0
- data/lib/logstash/codecs/cef.rb +145 -14
- data/logstash-codec-cef.gemspec +2 -2
- data/spec/codecs/cef_spec.rb +295 -1
- metadata +14 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d9084e0831538c85ddcabe642a00db46b22e08d
|
4
|
+
data.tar.gz: 9de28cadc061797c5b65b0107ef46ccf1b2868a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7a357ac86677710e8da105eabe837498595a58d4e75867447f85e0e0a8fe1144d60735a8edd1ca3c2484624c1d3aeb2fa9a5b82b686044a4b16b44ca6aeeb4f
|
7
|
+
data.tar.gz: bdb89985dd333aa2e1fa82eba3fdc22026a8d1e06404d2ba74b54f05b2ec1e142a7610971fe1473463735133e5dbdacd17e3b0762ae97a293087fd058b1bd329
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## 2.1.0
|
2
|
+
- Implements `encode` with escaping according to the [CEF specification](https://protect724.hp.com/docs/DOC-1072).
|
3
|
+
- Config option `sev` is deprecated, use `severity` instead.
|
4
|
+
|
1
5
|
## 2.0.0
|
2
6
|
- Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
|
3
7
|
instead of using Thread.raise on the plugins' threads. Ref: https://github.com/elastic/logstash/pull/3895
|
data/CONTRIBUTORS
CHANGED
@@ -11,6 +11,7 @@ Contributors:
|
|
11
11
|
* Pete Fritchman (fetep)
|
12
12
|
* Pier-Hugues Pellerin (ph)
|
13
13
|
* Karl Stoney (Stono)
|
14
|
+
* Lucas Bremgartner (breml)
|
14
15
|
|
15
16
|
Note: If you've sent us patches, bug reports, or otherwise contributed to
|
16
17
|
Logstash, and you aren't on the list above and want to be, please let us know
|
data/lib/logstash/codecs/cef.rb
CHANGED
@@ -1,12 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require "logstash/codecs/base"
|
3
|
+
require "json"
|
2
4
|
|
3
5
|
class LogStash::Codecs::CEF < LogStash::Codecs::Base
|
6
|
+
# Implementation of a Logstash codec for the ArcSight Common Event Format (CEF)
|
7
|
+
# Based on Revision 20 of Implementing ArcSight CEF, dated from June 05, 2013
|
8
|
+
# https://protect724.hp.com/servlet/JiveServlet/downloadBody/1072-102-6-4697/CommonEventFormat.pdf
|
4
9
|
config_name "cef"
|
10
|
+
|
11
|
+
# Device vendor field in CEF header. The new value can include `%{foo}` strings
|
12
|
+
# to help you build a new value from other parts of the event.
|
13
|
+
config :vendor, :validate => :string, :default => "Elasticsearch"
|
14
|
+
|
15
|
+
# Device product field in CEF header. The new value can include `%{foo}` strings
|
16
|
+
# to help you build a new value from other parts of the event.
|
17
|
+
config :product, :validate => :string, :default => "Logstash"
|
18
|
+
|
19
|
+
# Device version field in CEF header. The new value can include `%{foo}` strings
|
20
|
+
# to help you build a new value from other parts of the event.
|
21
|
+
config :version, :validate => :string, :default => "1.0"
|
22
|
+
|
23
|
+
# Signature ID field in CEF header. The new value can include `%{foo}` strings
|
24
|
+
# to help you build a new value from other parts of the event.
|
5
25
|
config :signature, :validate => :string, :default => "Logstash"
|
26
|
+
|
27
|
+
# Name field in CEF header. The new value can include `%{foo}` strings
|
28
|
+
# to help you build a new value from other parts of the event.
|
6
29
|
config :name, :validate => :string, :default => "Logstash"
|
7
|
-
config :sev, :validate => :number, :default => 6
|
8
30
|
|
9
|
-
|
31
|
+
# Deprecated severity field for CEF header. The new value can include `%{foo}` strings
|
32
|
+
# to help you build a new value from other parts of the event.
|
33
|
+
#
|
34
|
+
# This field is used only if :severity is unchanged set to the default value.
|
35
|
+
#
|
36
|
+
# Defined as field of type string to allow sprintf. The value will be validated
|
37
|
+
# to be an integer in the range from 0 to 10 (including).
|
38
|
+
# All invalid values will be mapped to the default of 6.
|
39
|
+
config :sev, :validate => :string, :default => "6", :deprecated => "This setting is being deprecated, use :severity instead."
|
40
|
+
|
41
|
+
# Severity field in CEF header. The new value can include `%{foo}` strings
|
42
|
+
# to help you build a new value from other parts of the event.
|
43
|
+
#
|
44
|
+
# Defined as field of type string to allow sprintf. The value will be validated
|
45
|
+
# to be an integer in the range from 0 to 10 (including).
|
46
|
+
# All invalid values will be mapped to the default of 6.
|
47
|
+
config :severity, :validate => :string, :default => "6"
|
48
|
+
|
49
|
+
# Fields to be included in CEV extension part as key/value pairs
|
50
|
+
config :fields, :validate => :array, :default => []
|
10
51
|
|
11
52
|
public
|
12
53
|
def initialize(params={})
|
@@ -57,28 +98,118 @@ class LogStash::Codecs::CEF < LogStash::Codecs::Base
|
|
57
98
|
end
|
58
99
|
|
59
100
|
public
|
60
|
-
def encode(
|
101
|
+
def encode(event)
|
61
102
|
# "CEF:0|Elasticsearch|Logstash|1.0|Signature|Name|Sev|"
|
62
103
|
|
63
|
-
|
104
|
+
vendor = sanitize_header_field(event.sprintf(@vendor))
|
105
|
+
vendor = self.class.get_config["vendor"][:default] if vendor == ""
|
106
|
+
|
107
|
+
product = sanitize_header_field(event.sprintf(@product))
|
108
|
+
product = self.class.get_config["product"][:default] if product == ""
|
109
|
+
|
110
|
+
version = sanitize_header_field(event.sprintf(@version))
|
111
|
+
version = self.class.get_config["version"][:default] if version == ""
|
112
|
+
|
113
|
+
signature = sanitize_header_field(event.sprintf(@signature))
|
114
|
+
signature = self.class.get_config["signature"][:default] if signature == ""
|
115
|
+
|
116
|
+
name = sanitize_header_field(event.sprintf(@name))
|
117
|
+
name = self.class.get_config["name"][:default] if name == ""
|
118
|
+
|
119
|
+
# :sev is deprecated and therefore only considered if :severity equals the default setting or is invalid
|
120
|
+
severity = sanitize_severity(event, @severity)
|
121
|
+
if severity == self.class.get_config["severity"][:default]
|
122
|
+
# Use deprecated setting sev
|
123
|
+
severity = sanitize_severity(event, @sev)
|
124
|
+
end
|
64
125
|
|
65
|
-
# Signature, Name, and Sev should be set in the config, with ref to fields
|
66
126
|
# Should also probably set the fields sent
|
67
|
-
header = ["CEF:0",
|
68
|
-
values = @fields.map {|
|
69
|
-
|
70
|
-
@on_event.call(
|
127
|
+
header = ["CEF:0", vendor, product, version, signature, name, severity].join("|")
|
128
|
+
values = @fields.map {|fieldname| get_value(fieldname, event)}.compact.join(" ")
|
129
|
+
|
130
|
+
@on_event.call(event, "#{header}|#{values}\n")
|
71
131
|
end
|
72
132
|
|
73
133
|
private
|
74
|
-
|
75
|
-
|
134
|
+
|
135
|
+
# Escape pipes and backslashes in the header. Equal signs are ok.
|
136
|
+
# Newlines are forbidden.
|
137
|
+
def sanitize_header_field(value)
|
138
|
+
output = ""
|
139
|
+
|
140
|
+
value = value.to_s.gsub(/\r\n/, "\n")
|
141
|
+
|
142
|
+
value.each_char{|c|
|
143
|
+
case c
|
144
|
+
when "\\", "|"
|
145
|
+
output += "\\" + c
|
146
|
+
when "\n", "\r"
|
147
|
+
output += " "
|
148
|
+
else
|
149
|
+
output += c
|
150
|
+
end
|
151
|
+
}
|
152
|
+
|
153
|
+
return output
|
154
|
+
end
|
155
|
+
|
156
|
+
# Keys must be made up of a single word, with no spaces
|
157
|
+
# must be alphanumeric
|
158
|
+
def sanitize_extension_key(value)
|
159
|
+
value = value.to_s.gsub(/[^a-zA-Z0-9]/, "")
|
160
|
+
return value
|
161
|
+
end
|
162
|
+
|
163
|
+
# Escape equal signs in the extensions. Canonicalize newlines.
|
164
|
+
# CEF spec leaves it up to us to choose \r or \n for newline.
|
165
|
+
# We choose \n as the default.
|
166
|
+
def sanitize_extension_val(value)
|
167
|
+
output = ""
|
168
|
+
|
169
|
+
value = value.to_s.gsub(/\r\n/, "\n")
|
170
|
+
|
171
|
+
value.each_char{|c|
|
172
|
+
case c
|
173
|
+
when "\\", "="
|
174
|
+
output += "\\" + c
|
175
|
+
when "\n", "\r"
|
176
|
+
output += "\\n"
|
177
|
+
else
|
178
|
+
output += c
|
179
|
+
end
|
180
|
+
}
|
181
|
+
|
182
|
+
return output
|
183
|
+
end
|
184
|
+
|
185
|
+
def get_value(fieldname, event)
|
186
|
+
val = event[fieldname]
|
187
|
+
|
188
|
+
return nil if val.nil?
|
189
|
+
|
76
190
|
case val
|
77
|
-
when Hash
|
78
|
-
return
|
191
|
+
when Array, Hash
|
192
|
+
return "#{sanitize_extension_key(fieldname)}=#{sanitize_extension_val(val.to_json)}"
|
193
|
+
when LogStash::Timestamp
|
194
|
+
return "#{sanitize_extension_key(fieldname)}=#{val.to_s}"
|
79
195
|
else
|
80
|
-
return
|
196
|
+
return "#{sanitize_extension_key(fieldname)}=#{sanitize_extension_val(val)}"
|
81
197
|
end
|
82
198
|
end
|
83
199
|
|
200
|
+
def sanitize_severity(event, severity)
|
201
|
+
severity = sanitize_header_field(event.sprintf(severity)).strip
|
202
|
+
severity = self.class.get_config["severity"][:default] unless valid_severity?(severity)
|
203
|
+
severity = severity.to_i.to_s
|
204
|
+
end
|
205
|
+
|
206
|
+
def valid_severity?(sev)
|
207
|
+
f = Float(sev)
|
208
|
+
# check if it's an integer or a float with no remainder
|
209
|
+
# and if the value is between 0 and 10 (inclusive)
|
210
|
+
(f % 1 == 0) && f.between?(0,10)
|
211
|
+
rescue TypeError, ArgumentError
|
212
|
+
false
|
213
|
+
end
|
214
|
+
|
84
215
|
end
|
data/logstash-codec-cef.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-codec-cef'
|
4
|
-
s.version = '2.0
|
4
|
+
s.version = '2.1.0'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
|
-
s.summary = "CEF codec to parse CEF formated logs"
|
6
|
+
s.summary = "CEF codec to parse and encode CEF formated logs"
|
7
7
|
s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
|
8
8
|
s.authors = ["Elastic"]
|
9
9
|
s.email = 'info@elastic.co'
|
data/spec/codecs/cef_spec.rb
CHANGED
@@ -10,7 +10,301 @@ describe LogStash::Codecs::CEF do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
context "#encode" do
|
13
|
-
|
13
|
+
subject(:codec) { LogStash::Codecs::CEF.new }
|
14
|
+
|
15
|
+
let(:results) { [] }
|
16
|
+
|
17
|
+
it "should not fail if fields is nil" do
|
18
|
+
codec.on_event{|data, newdata| results << newdata}
|
19
|
+
event = LogStash::Event.new("foo" => "bar")
|
20
|
+
codec.encode(event)
|
21
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|$/m)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should assert all header fields are present" do
|
25
|
+
codec.on_event{|data, newdata| results << newdata}
|
26
|
+
codec.fields = []
|
27
|
+
event = LogStash::Event.new("foo" => "bar")
|
28
|
+
codec.encode(event)
|
29
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|$/m)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should use default values for empty header fields" do
|
33
|
+
codec.on_event{|data, newdata| results << newdata}
|
34
|
+
codec.vendor = ""
|
35
|
+
codec.product = ""
|
36
|
+
codec.version = ""
|
37
|
+
codec.signature = ""
|
38
|
+
codec.name = ""
|
39
|
+
codec.severity = ""
|
40
|
+
codec.fields = []
|
41
|
+
event = LogStash::Event.new("foo" => "bar")
|
42
|
+
codec.encode(event)
|
43
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|$/m)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should use configured values for header fields" do
|
47
|
+
codec.on_event{|data, newdata| results << newdata}
|
48
|
+
codec.vendor = "vendor"
|
49
|
+
codec.product = "product"
|
50
|
+
codec.version = "2.0"
|
51
|
+
codec.signature = "signature"
|
52
|
+
codec.name = "name"
|
53
|
+
codec.severity = "1"
|
54
|
+
codec.fields = []
|
55
|
+
event = LogStash::Event.new("foo" => "bar")
|
56
|
+
codec.encode(event)
|
57
|
+
expect(results.first).to match(/^CEF:0\|vendor\|product\|2.0\|signature\|name\|1\|$/m)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should use sprintf for header fields" do
|
61
|
+
codec.on_event{|data, newdata| results << newdata}
|
62
|
+
codec.vendor = "%{vendor}"
|
63
|
+
codec.product = "%{product}"
|
64
|
+
codec.version = "%{version}"
|
65
|
+
codec.signature = "%{signature}"
|
66
|
+
codec.name = "%{name}"
|
67
|
+
codec.severity = "%{severity}"
|
68
|
+
codec.fields = []
|
69
|
+
event = LogStash::Event.new("vendor" => "vendor", "product" => "product", "version" => "2.0", "signature" => "signature", "name" => "name", "severity" => "1")
|
70
|
+
codec.encode(event)
|
71
|
+
expect(results.first).to match(/^CEF:0\|vendor\|product\|2.0\|signature\|name\|1\|$/m)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should use default, if severity is not numeric" do
|
75
|
+
codec.on_event{|data, newdata| results << newdata}
|
76
|
+
codec.severity = "foo"
|
77
|
+
codec.fields = []
|
78
|
+
event = LogStash::Event.new("foo" => "bar")
|
79
|
+
codec.encode(event)
|
80
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|$/m)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should use default, if severity is > 10" do
|
84
|
+
codec.on_event{|data, newdata| results << newdata}
|
85
|
+
codec.severity = "11"
|
86
|
+
codec.fields = []
|
87
|
+
event = LogStash::Event.new("foo" => "bar")
|
88
|
+
codec.encode(event)
|
89
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|$/m)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should use default, if severity is < 0" do
|
93
|
+
codec.on_event{|data, newdata| results << newdata}
|
94
|
+
codec.severity = "-1"
|
95
|
+
codec.fields = []
|
96
|
+
event = LogStash::Event.new("foo" => "bar")
|
97
|
+
codec.encode(event)
|
98
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|$/m)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should use default, if severity is float with decimal part" do
|
102
|
+
codec.on_event{|data, newdata| results << newdata}
|
103
|
+
codec.severity = "5.4"
|
104
|
+
codec.fields = []
|
105
|
+
event = LogStash::Event.new("foo" => "bar")
|
106
|
+
codec.encode(event)
|
107
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|$/m)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should append fields as key/value pairs in cef extension part" do
|
111
|
+
codec.on_event{|data, newdata| results << newdata}
|
112
|
+
codec.fields = [ "foo", "bar" ]
|
113
|
+
event = LogStash::Event.new("foo" => "foo value", "bar" => "bar value")
|
114
|
+
codec.encode(event)
|
115
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|foo=foo value bar=bar value$/m)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should ignore fields in fields if not present in event" do
|
119
|
+
codec.on_event{|data, newdata| results << newdata}
|
120
|
+
codec.fields = [ "foo", "bar", "baz" ]
|
121
|
+
event = LogStash::Event.new("foo" => "foo value", "baz" => "baz value")
|
122
|
+
codec.encode(event)
|
123
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|foo=foo value baz=baz value$/m)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should sanitize header fields" do
|
127
|
+
codec.on_event{|data, newdata| results << newdata}
|
128
|
+
codec.vendor = "ven\ndor"
|
129
|
+
codec.product = "pro|duct"
|
130
|
+
codec.version = "ver\\sion"
|
131
|
+
codec.signature = "sig\r\nnature"
|
132
|
+
codec.name = "na\rme"
|
133
|
+
codec.severity = "4\n"
|
134
|
+
codec.fields = []
|
135
|
+
event = LogStash::Event.new("foo" => "bar")
|
136
|
+
codec.encode(event)
|
137
|
+
expect(results.first).to match(/^CEF:0\|ven dor\|pro\\\|duct\|ver\\\\sion\|sig nature\|na me\|4\|$/m)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should sanitize extension keys" do
|
141
|
+
codec.on_event{|data, newdata| results << newdata}
|
142
|
+
codec.fields = [ "f o\no", "@b-a_r" ]
|
143
|
+
event = LogStash::Event.new("f o\no" => "foo value", "@b-a_r" => "bar value")
|
144
|
+
codec.encode(event)
|
145
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|foo=foo value bar=bar value$/m)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should sanitize extension values" do
|
149
|
+
codec.on_event{|data, newdata| results << newdata}
|
150
|
+
codec.fields = [ "foo", "bar", "baz" ]
|
151
|
+
event = LogStash::Event.new("foo" => "foo\\value\n", "bar" => "bar=value\r")
|
152
|
+
codec.encode(event)
|
153
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|foo=foo\\\\value\\n bar=bar\\=value\\n$/m)
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should encode a hash value" do
|
157
|
+
codec.on_event{|data, newdata| results << newdata}
|
158
|
+
codec.fields = [ "foo" ]
|
159
|
+
event = LogStash::Event.new("foo" => { "bar" => "bar value", "baz" => "baz value" })
|
160
|
+
codec.encode(event)
|
161
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|foo=\{\"bar\":\"bar value\",\"baz\":\"baz value\"\}$/m)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should encode an array value" do
|
165
|
+
codec.on_event{|data, newdata| results << newdata}
|
166
|
+
codec.fields = [ "foo" ]
|
167
|
+
event = LogStash::Event.new("foo" => [ "bar", "baz" ])
|
168
|
+
codec.encode(event)
|
169
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|foo=\[\"bar\",\"baz\"\]$/m)
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should encode a hash in an array value" do
|
173
|
+
codec.on_event{|data, newdata| results << newdata}
|
174
|
+
codec.fields = [ "foo" ]
|
175
|
+
event = LogStash::Event.new("foo" => [ { "bar" => "bar value" }, "baz" ])
|
176
|
+
codec.encode(event)
|
177
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|foo=\[\{\"bar\":\"bar value\"\},\"baz\"\]$/m)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should encode a LogStash::Timestamp" do
|
181
|
+
codec.on_event{|data, newdata| results << newdata}
|
182
|
+
codec.fields = [ "foo" ]
|
183
|
+
event = LogStash::Event.new("foo" => LogStash::Timestamp.new)
|
184
|
+
codec.encode(event)
|
185
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|foo=[0-9TZ.:-]+$/m)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should use severity (instead of depricated sev), if severity is set)" do
|
189
|
+
codec.on_event{|data, newdata| results << newdata}
|
190
|
+
codec.sev = "4"
|
191
|
+
codec.severity = "5"
|
192
|
+
codec.fields = []
|
193
|
+
event = LogStash::Event.new("foo" => "bar")
|
194
|
+
codec.encode(event)
|
195
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|5\|$/m)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should use deprecated sev, if severity is not set (equals default value)" do
|
199
|
+
codec.on_event{|data, newdata| results << newdata}
|
200
|
+
codec.sev = "4"
|
201
|
+
codec.fields = []
|
202
|
+
event = LogStash::Event.new("foo" => "bar")
|
203
|
+
codec.encode(event)
|
204
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|4\|$/m)
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should use deprecated sev, if severity is explicitly set to default value)" do
|
208
|
+
codec.on_event{|data, newdata| results << newdata}
|
209
|
+
codec.sev = "4"
|
210
|
+
codec.severity = "6"
|
211
|
+
codec.fields = []
|
212
|
+
event = LogStash::Event.new("foo" => "bar")
|
213
|
+
codec.encode(event)
|
214
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|4\|$/m)
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should use deprecated sev, if severity is invalid" do
|
218
|
+
codec.on_event{|data, newdata| results << newdata}
|
219
|
+
codec.sev = "4"
|
220
|
+
codec.severity = ""
|
221
|
+
codec.fields = []
|
222
|
+
event = LogStash::Event.new("foo" => "bar")
|
223
|
+
codec.encode(event)
|
224
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|4\|$/m)
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should use default value, if severity is not set and sev is invalid" do
|
228
|
+
codec.on_event{|data, newdata| results << newdata}
|
229
|
+
codec.sev = ""
|
230
|
+
codec.fields = []
|
231
|
+
event = LogStash::Event.new("foo" => "bar")
|
232
|
+
codec.encode(event)
|
233
|
+
expect(results.first).to match(/^CEF:0\|Elasticsearch\|Logstash\|1.0\|Logstash\|Logstash\|6\|$/m)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context "sanitize header field" do
|
238
|
+
subject(:codec) { LogStash::Codecs::CEF.new }
|
239
|
+
|
240
|
+
it "should sanitize" do
|
241
|
+
expect(codec.send(:sanitize_header_field, "foo")).to be == "foo"
|
242
|
+
expect(codec.send(:sanitize_header_field, "foo\nbar")).to be == "foo bar"
|
243
|
+
expect(codec.send(:sanitize_header_field, "foo\rbar")).to be == "foo bar"
|
244
|
+
expect(codec.send(:sanitize_header_field, "foo\r\nbar")).to be == "foo bar"
|
245
|
+
expect(codec.send(:sanitize_header_field, "foo\r\nbar\r\nbaz")).to be == "foo bar baz"
|
246
|
+
expect(codec.send(:sanitize_header_field, "foo\\bar")).to be == "foo\\\\bar"
|
247
|
+
expect(codec.send(:sanitize_header_field, "foo|bar")).to be == "foo\\|bar"
|
248
|
+
expect(codec.send(:sanitize_header_field, "foo=bar")).to be == "foo=bar"
|
249
|
+
expect(codec.send(:sanitize_header_field, 123)).to be == "123" # Input value is a Fixnum
|
250
|
+
expect(codec.send(:sanitize_header_field, 123.123)).to be == "123.123" # Input value is a Float
|
251
|
+
expect(codec.send(:sanitize_header_field, [])).to be == "[]" # Input value is an Array
|
252
|
+
expect(codec.send(:sanitize_header_field, {})).to be == "{}" # Input value is a Hash
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context "sanitize extension key" do
|
257
|
+
subject(:codec) { LogStash::Codecs::CEF.new }
|
258
|
+
|
259
|
+
it "should sanitize" do
|
260
|
+
expect(codec.send(:sanitize_extension_key, " foo ")).to be == "foo"
|
261
|
+
expect(codec.send(:sanitize_extension_key, " FOO 123 ")).to be == "FOO123"
|
262
|
+
expect(codec.send(:sanitize_extension_key, "foo\nbar\rbaz")).to be == "foobarbaz"
|
263
|
+
expect(codec.send(:sanitize_extension_key, "Foo_Bar\r\nBaz")).to be == "FooBarBaz"
|
264
|
+
expect(codec.send(:sanitize_extension_key, "foo-@bar=baz")).to be == "foobarbaz"
|
265
|
+
expect(codec.send(:sanitize_extension_key, "[foo]|bar.baz")).to be == "foobarbaz"
|
266
|
+
expect(codec.send(:sanitize_extension_key, 123)).to be == "123" # Input value is a Fixnum
|
267
|
+
expect(codec.send(:sanitize_extension_key, 123.123)).to be == "123123" # Input value is a Float, "." is not allowed and therefore removed
|
268
|
+
expect(codec.send(:sanitize_extension_key, [])).to be == "" # Input value is an Array, "[" and "]" are not allowed and therefore removed
|
269
|
+
expect(codec.send(:sanitize_extension_key, {})).to be == "" # Input value is a Hash, "{" and "}" are not allowed and therefore removed
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
context "sanitize extension value" do
|
274
|
+
subject(:codec) { LogStash::Codecs::CEF.new }
|
275
|
+
|
276
|
+
it "should sanitize" do
|
277
|
+
expect(codec.send(:sanitize_extension_val, "foo")).to be == "foo"
|
278
|
+
expect(codec.send(:sanitize_extension_val, "foo\nbar")).to be == "foo\\nbar"
|
279
|
+
expect(codec.send(:sanitize_extension_val, "foo\rbar")).to be == "foo\\nbar"
|
280
|
+
expect(codec.send(:sanitize_extension_val, "foo\r\nbar")).to be == "foo\\nbar"
|
281
|
+
expect(codec.send(:sanitize_extension_val, "foo\r\nbar\r\nbaz")).to be == "foo\\nbar\\nbaz"
|
282
|
+
expect(codec.send(:sanitize_extension_val, "foo\\bar")).to be == "foo\\\\bar"
|
283
|
+
expect(codec.send(:sanitize_extension_val, "foo|bar")).to be == "foo|bar"
|
284
|
+
expect(codec.send(:sanitize_extension_val, "foo=bar")).to be == "foo\\=bar"
|
285
|
+
expect(codec.send(:sanitize_extension_val, 123)).to be == "123" # Input value is a Fixnum
|
286
|
+
expect(codec.send(:sanitize_extension_val, 123.123)).to be == "123.123" # Input value is a Float
|
287
|
+
expect(codec.send(:sanitize_extension_val, [])).to be == "[]" # Input value is an Array
|
288
|
+
expect(codec.send(:sanitize_extension_val, {})).to be == "{}" # Input value is a Hash
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
context "valid_severity?" do
|
293
|
+
subject(:codec) { LogStash::Codecs::CEF.new }
|
294
|
+
|
295
|
+
it "should validate severity" do
|
296
|
+
expect(codec.send(:valid_severity?, nil)).to be == false
|
297
|
+
expect(codec.send(:valid_severity?, "")).to be == false
|
298
|
+
expect(codec.send(:valid_severity?, "foo")).to be == false
|
299
|
+
expect(codec.send(:valid_severity?, "1.5")).to be == false
|
300
|
+
expect(codec.send(:valid_severity?, "-1")).to be == false
|
301
|
+
expect(codec.send(:valid_severity?, "11")).to be == false
|
302
|
+
expect(codec.send(:valid_severity?, "0")).to be == true
|
303
|
+
expect(codec.send(:valid_severity?, "10")).to be == true
|
304
|
+
expect(codec.send(:valid_severity?, "1.0")).to be == true
|
305
|
+
expect(codec.send(:valid_severity?, 1)).to be == true
|
306
|
+
expect(codec.send(:valid_severity?, 1.0)).to be == true
|
307
|
+
end
|
14
308
|
end
|
15
309
|
|
16
310
|
context "#decode" do
|
metadata
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-codec-cef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
|
15
|
-
version_requirements: !ruby/object:Gem::Requirement
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
16
15
|
requirements:
|
17
16
|
- - '>='
|
18
17
|
- !ruby/object:Gem::Version
|
@@ -20,7 +19,10 @@ dependencies:
|
|
20
19
|
- - <
|
21
20
|
- !ruby/object:Gem::Version
|
22
21
|
version: 3.0.0
|
23
|
-
|
22
|
+
name: logstash-core
|
23
|
+
prerelease: false
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
26
|
requirements:
|
25
27
|
- - '>='
|
26
28
|
- !ruby/object:Gem::Version
|
@@ -28,22 +30,20 @@ dependencies:
|
|
28
30
|
- - <
|
29
31
|
- !ruby/object:Gem::Version
|
30
32
|
version: 3.0.0
|
31
|
-
prerelease: false
|
32
|
-
type: :runtime
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
|
35
|
-
version_requirements: !ruby/object:Gem::Requirement
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
36
35
|
requirements:
|
37
36
|
- - '>='
|
38
37
|
- !ruby/object:Gem::Version
|
39
38
|
version: '0'
|
40
|
-
|
39
|
+
name: logstash-devutils
|
40
|
+
prerelease: false
|
41
|
+
type: :development
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
43
|
requirements:
|
42
44
|
- - '>='
|
43
45
|
- !ruby/object:Gem::Version
|
44
46
|
version: '0'
|
45
|
-
prerelease: false
|
46
|
-
type: :development
|
47
47
|
description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
|
48
48
|
email: info@elastic.co
|
49
49
|
executables: []
|
@@ -81,9 +81,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
81
|
version: '0'
|
82
82
|
requirements: []
|
83
83
|
rubyforge_project:
|
84
|
-
rubygems_version: 2.4.
|
84
|
+
rubygems_version: 2.4.5
|
85
85
|
signing_key:
|
86
86
|
specification_version: 4
|
87
|
-
summary: CEF codec to parse CEF formated logs
|
87
|
+
summary: CEF codec to parse and encode CEF formated logs
|
88
88
|
test_files:
|
89
89
|
- spec/codecs/cef_spec.rb
|