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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b07e21611300d4682e481db32cb96f37e5f8b659
4
- data.tar.gz: 52ca214b4b2e0623bf45902113d02f1986cbb235
3
+ metadata.gz: 8d9084e0831538c85ddcabe642a00db46b22e08d
4
+ data.tar.gz: 9de28cadc061797c5b65b0107ef46ccf1b2868a0
5
5
  SHA512:
6
- metadata.gz: 77353440739c5fda71c5cc410457a37ab40f5d5a00ceb48d690f11ea605a44741b4b38b75bffa23badb42b05316cd2fb9d721da3c4d117e582d6f7c333629884
7
- data.tar.gz: 927f654424f3f19ca954fd465573b7c26170e2195f562c52338a3e737a788078c6ea7b71bd67644ea83001c00824ea63de9e1b9f1c8210d21ea07e8d7c4bfc3e
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
@@ -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
- config :fields, :validate => :array
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(data)
101
+ def encode(event)
61
102
  # "CEF:0|Elasticsearch|Logstash|1.0|Signature|Name|Sev|"
62
103
 
63
- # TODO: Need to check that fields are set!
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", "Elasticsearch", "Logstash", "1.0", @signature, @name, @sev].join("|")
68
- values = @fields.map {|name| get_value(name, data)}.join(" ")
69
- # values = values.map {|k,v| "#{k}=#{v}"}.join(" ")
70
- @on_event.call(header + " " + values + "\n")
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
- def get_value(name, event)
75
- val = event[name]
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 name + "=" + val.to_json
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 name + "=" + val
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
@@ -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.3'
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'
@@ -10,7 +10,301 @@ describe LogStash::Codecs::CEF do
10
10
  end
11
11
 
12
12
  context "#encode" do
13
- it "should assert all header fields are present"
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.3
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: 2015-11-19 00:00:00.000000000 Z
11
+ date: 2016-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: logstash-core
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
- requirement: !ruby/object:Gem::Requirement
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
- name: logstash-devutils
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
- requirement: !ruby/object:Gem::Requirement
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.8
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