logstash-codec-cef 2.0.3 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|