logstash-codec-cef 4.1.0-java → 4.1.2-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -1
- data/lib/logstash/codecs/cef.rb +10 -9
- data/logstash-codec-cef.gemspec +1 -2
- data/spec/codecs/cef_spec.rb +36 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4970c9754e3a998c7768dfd91127908d00754c2d
|
4
|
+
data.tar.gz: c89d21a60488b04b8f305346b35715bf398b22b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ddba453c75fec89baf0c374663721f20df6edfa054f1ff8b904e75cd95da4db92d1d6bd20771de5d1f6ba8d4bae1e7a5f15068cc250568a718265129a5b9802
|
7
|
+
data.tar.gz: e1132893ea01846719b888fe1f83c0d79bd1f7c6a1600ccbd6c6f6aa996915069b8eeb6f4bfae90aeb66d7f3f7281fef031bba8df4d161a98685eb6dab143923
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
+
## 4.1.2
|
2
|
+
- added mapping for outcome = eventOutcome from CEF whitepaper (ref:p26/39)
|
3
|
+
|
4
|
+
## 4.1.1
|
5
|
+
- changed rt from receiptTime to deviceReceiptTime (ref:p27/39)
|
6
|
+
- changed tokenizer to include additional fields (ad.fieldname)
|
7
|
+
|
1
8
|
## 4.1.0
|
2
9
|
- Add `delimiter` setting. This allows the decoder to be used with inputs like the TCP input where event delimiters are used.
|
3
10
|
|
4
11
|
## 4.0.0
|
5
|
-
- Implements the dictionary translation for abbreviated CEF field names from chapter Chapter 2: ArcSight Extension Dictionary
|
12
|
+
- Implements the dictionary translation for abbreviated CEF field names from chapter Chapter 2: ArcSight Extension Dictionary page 3 of 39 [CEF specification](https://protect724.hp.com/docs/DOC-1072).
|
6
13
|
- add `_cefparsefailure` tag on failed decode
|
7
14
|
|
8
15
|
## 3.0.0
|
data/lib/logstash/codecs/cef.rb
CHANGED
@@ -53,7 +53,7 @@ class LogStash::Codecs::CEF < LogStash::Codecs::Base
|
|
53
53
|
# Fields to be included in CEV extension part as key/value pairs
|
54
54
|
config :fields, :validate => :array, :default => []
|
55
55
|
|
56
|
-
# Set this flag if you want to have both v1 and v2 fields indexed at the same time. Note that this option will increase
|
56
|
+
# Set this flag if you want to have both v1 and v2 fields indexed at the same time. Note that this option will increase
|
57
57
|
# the index size and data stored in outputs like Elasticsearch
|
58
58
|
# This option is available to ease transition to new schema
|
59
59
|
config :deprecated_v1_fields, :validate => :boolean, :deprecated => "This setting is being deprecated"
|
@@ -66,7 +66,7 @@ class LogStash::Codecs::CEF < LogStash::Codecs::Base
|
|
66
66
|
# input {
|
67
67
|
# tcp {
|
68
68
|
# codec => cef { delimiter => "\r\n" }
|
69
|
-
# # ...
|
69
|
+
# # ...
|
70
70
|
# }
|
71
71
|
# }
|
72
72
|
#
|
@@ -79,7 +79,7 @@ class LogStash::Codecs::CEF < LogStash::Codecs::Base
|
|
79
79
|
HEADER_FIELDS = ['cefVersion','deviceVendor','deviceProduct','deviceVersion','deviceEventClassId','name','severity']
|
80
80
|
|
81
81
|
# Translating and flattening the CEF extensions with known field names as documented in the Common Event Format whitepaper
|
82
|
-
MAPPINGS = { "act" => "deviceAction", "app" => "applicationProtocol", "c6a1" => "deviceCustomIPv6Address1", "c6a1Label" => "deviceCustomIPv6Address1Label", "c6a2" => "deviceCustomIPv6Address2", "c6a2Label" => "deviceCustomIPv6Address2Label", "c6a3" => "deviceCustomIPv6Address3", "c6a3Label" => "deviceCustomIPv6Address3Label", "c6a4" => "deviceCustomIPv6Address4", "c6a4Label" => "deviceCustomIPv6Address4Label", "cat" => "deviceEventCategory", "cfp1" => "deviceCustomFloatingPoint1", "cfp1Label" => "deviceCustomFloatingPoint1Label", "cfp2" => "deviceCustomFloatingPoint2", "cfp2Label" => "deviceCustomFloatingPoint2", "cfp3" => "deviceCustomFloatingPoint3", "cfp3Label" => "deviceCustomFloatingPoint4Label", "cfp4" => "deviceCustomFloatingPoint4", "cfp4Label" => "deviceCustomFloatingPoint4Label", "cn1" => "deviceCustomNumber1", "cn1Label" => "deviceCustomNumber1Label", "cn2" => "deviceCustomNumber2", "cn2Label" => "deviceCustomNumber2Label", "cn3" => "deviceCustomNumber3", "cn3Label" => "deviceCustomNumber3Label", "cnt" => "baseEventCount", "cs1" => "deviceCustomString1", "cs1Label" => "deviceCustomString1Label", "cs2" => "deviceCustomString2", "cs2Label" => "deviceCustomString2Label", "cs3" => "deviceCustomString3", "cs3Label" => "deviceCustomString3Label", "cs4" => "deviceCustomString4", "cs4Label" => "deviceCustomString4Label", "cs5" => "deviceCustomString5", "cs5Label" => "deviceCustomString5Label", "cs6" => "deviceCustomString6", "cs6Label" => "deviceCustomString6Label", "dhost" => "destinationHostName", "dmac" => "destinationMacAddress", "dntdom" => "destinationNTDomain", "dpid" => "destinationProcessId", "dpriv" => "destinationUserPrivileges", "dproc" => "destinationProcessName", "dpt" => "destinationPort", "dst" => "destinationAddress", "duid" => "destinationUserId", "duser" => "destinationUserName", "dvc" => "deviceAddress", "dvchost" => "deviceHostName", "dvcpid" => "deviceProcessId", "end" => "endTime", "fname" => "fileName", "fsize" => "fileSize", "in" => "bytesIn", "msg" => "message", "out" => "bytesOut", "proto" => "transportProtocol", "request" => "requestUrl", "rt" => "
|
82
|
+
MAPPINGS = { "act" => "deviceAction", "app" => "applicationProtocol", "c6a1" => "deviceCustomIPv6Address1", "c6a1Label" => "deviceCustomIPv6Address1Label", "c6a2" => "deviceCustomIPv6Address2", "c6a2Label" => "deviceCustomIPv6Address2Label", "c6a3" => "deviceCustomIPv6Address3", "c6a3Label" => "deviceCustomIPv6Address3Label", "c6a4" => "deviceCustomIPv6Address4", "c6a4Label" => "deviceCustomIPv6Address4Label", "cat" => "deviceEventCategory", "cfp1" => "deviceCustomFloatingPoint1", "cfp1Label" => "deviceCustomFloatingPoint1Label", "cfp2" => "deviceCustomFloatingPoint2", "cfp2Label" => "deviceCustomFloatingPoint2", "cfp3" => "deviceCustomFloatingPoint3", "cfp3Label" => "deviceCustomFloatingPoint4Label", "cfp4" => "deviceCustomFloatingPoint4", "cfp4Label" => "deviceCustomFloatingPoint4Label", "cn1" => "deviceCustomNumber1", "cn1Label" => "deviceCustomNumber1Label", "cn2" => "deviceCustomNumber2", "cn2Label" => "deviceCustomNumber2Label", "cn3" => "deviceCustomNumber3", "cn3Label" => "deviceCustomNumber3Label", "cnt" => "baseEventCount", "cs1" => "deviceCustomString1", "cs1Label" => "deviceCustomString1Label", "cs2" => "deviceCustomString2", "cs2Label" => "deviceCustomString2Label", "cs3" => "deviceCustomString3", "cs3Label" => "deviceCustomString3Label", "cs4" => "deviceCustomString4", "cs4Label" => "deviceCustomString4Label", "cs5" => "deviceCustomString5", "cs5Label" => "deviceCustomString5Label", "cs6" => "deviceCustomString6", "cs6Label" => "deviceCustomString6Label", "dhost" => "destinationHostName", "dmac" => "destinationMacAddress", "dntdom" => "destinationNTDomain", "dpid" => "destinationProcessId", "dpriv" => "destinationUserPrivileges", "dproc" => "destinationProcessName", "dpt" => "destinationPort", "dst" => "destinationAddress", "duid" => "destinationUserId", "duser" => "destinationUserName", "dvc" => "deviceAddress", "dvchost" => "deviceHostName", "dvcpid" => "deviceProcessId", "end" => "endTime", "fname" => "fileName", "fsize" => "fileSize", "in" => "bytesIn", "msg" => "message", "out" => "bytesOut", "outcome" => "eventOutcome", "proto" => "transportProtocol", "request" => "requestUrl", "rt" => "deviceReceiptTime", "shost" => "sourceHostName", "smac" => "sourceMacAddress", "sntdom" => "sourceNtDomain", "spid" => "sourceProcessId", "spriv" => "sourceUserPrivileges", "sproc" => "sourceProcessName", "spt" => "sourcePort", "src" => "sourceAddress", "start" => "startTime", "suid" => "sourceUserId", "suser" => "sourceUserName", "ahost" => "agentHost", "art" => "agentReceiptTime", "at" => "agentType", "aid" => "agentId", "_cefVer" => "cefVersion", "agt" => "agentAddress", "av" => "agentVersion", "atz" => "agentTimeZone", "dtz" => "destinationTimeZone", "slong" => "sourceLongitude", "slat" => "sourceLatitude", "dlong" => "destinationLongitude", "dlat" => "destinationLatitude", "catdt" => "categoryDeviceType", "mrt" => "managerReceiptTime" }
|
83
83
|
|
84
84
|
DEPRECATED_HEADER_FIELDS = ['cef_version','cef_vendor','cef_product','cef_device_version','cef_sigid','cef_name','cef_severity']
|
85
85
|
|
@@ -160,11 +160,12 @@ class LogStash::Codecs::CEF < LogStash::Codecs::Base
|
|
160
160
|
|
161
161
|
# Insert custom delimiter to separate key-value pairs, to which some values will contain special characters
|
162
162
|
# This separator '|^^^' os tested to be unique
|
163
|
-
message = message.gsub((
|
163
|
+
message = message.gsub((/(?:(\s+(\w+\=)))/),'|^^^\2')
|
164
164
|
|
165
|
-
#
|
166
|
-
#
|
167
|
-
|
165
|
+
# Appropriately tokenizing the additional fields when ArcSight connectors are sending events using "COMPLETE" mode processing.
|
166
|
+
# If these fields are NOT needed, then set the ArcSight processing mode for this destination to "FASTER" or "FASTEST"
|
167
|
+
# Refer to ArcSight's SmartConnector user configuration guide
|
168
|
+
message = message.gsub((/(\s+(\w+\.[^\s]\w+[^\|\s\.\=]+\=))/),'|^^^\2')
|
168
169
|
message = message.split('|^^^')
|
169
170
|
|
170
171
|
# Replaces the '=' with '***' to avoid conflict with strings with HTML content namely key-value pairs where the values contain HTML strings
|
@@ -301,7 +302,7 @@ class LogStash::Codecs::CEF < LogStash::Codecs::Base
|
|
301
302
|
rescue TypeError, ArgumentError
|
302
303
|
false
|
303
304
|
end
|
304
|
-
|
305
|
+
|
305
306
|
def handle_v1_fields(event, split_data)
|
306
307
|
# Store header fields
|
307
308
|
DEPRECATED_HEADER_FIELDS.each_with_index do |field_name, index|
|
@@ -339,6 +340,6 @@ class LogStash::Codecs::CEF < LogStash::Codecs::Base
|
|
339
340
|
event.set('cef_ext', extensions)
|
340
341
|
end
|
341
342
|
|
342
|
-
end
|
343
|
+
end
|
343
344
|
|
344
345
|
end
|
data/logstash-codec-cef.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-codec-cef'
|
4
|
-
s.version = '4.1.
|
4
|
+
s.version = '4.1.2'
|
5
5
|
s.platform = 'java'
|
6
6
|
s.licenses = ['Apache License (2.0)']
|
7
7
|
s.summary = "CEF codec to parse and encode CEF formated logs"
|
@@ -25,4 +25,3 @@ Gem::Specification.new do |s|
|
|
25
25
|
|
26
26
|
s.add_development_dependency 'logstash-devutils'
|
27
27
|
end
|
28
|
-
|
data/spec/codecs/cef_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe LogStash::Codecs::CEF do
|
|
14
14
|
|
15
15
|
let(:results) { [] }
|
16
16
|
|
17
|
-
context "with delimiter set" do
|
17
|
+
context "with delimiter set" do
|
18
18
|
# '\r\n' in single quotes to simulate the real input from a config
|
19
19
|
# containing \r\n as 4-character sequence in the config:
|
20
20
|
#
|
@@ -344,7 +344,7 @@ describe LogStash::Codecs::CEF do
|
|
344
344
|
insist { e.get('severity') } == "10"
|
345
345
|
end
|
346
346
|
|
347
|
-
context "with delimiter set" do
|
347
|
+
context "with delimiter set" do
|
348
348
|
# '\r\n' in single quotes to simulate the real input from a config
|
349
349
|
# containing \r\n as 4-character sequence in the config:
|
350
350
|
#
|
@@ -494,19 +494,37 @@ describe LogStash::Codecs::CEF do
|
|
494
494
|
end
|
495
495
|
end
|
496
496
|
|
497
|
-
let (:
|
498
|
-
it "should
|
499
|
-
subject.decode(
|
497
|
+
let (:preserve_additional_fields_with_dot_notations) {'CEF:0|security|threatmanager|1.0|100|trojan successfully stopped|10|src=10.0.0.192 additional.dotfieldName=new_value ad.Authentification=MICROSOFT_AUTHENTICATION_PACKAGE_V1_0 ad.Error_,Code=3221225578 dst=12.121.122.82 ad.field[0]=field0 ad.name[1]=new_name'}
|
498
|
+
it "should keep ad.fields" do
|
499
|
+
subject.decode(preserve_additional_fields_with_dot_notations) do |e|
|
500
500
|
validate(e)
|
501
501
|
insist { e.get("sourceAddress") } == "10.0.0.192"
|
502
502
|
insist { e.get("destinationAddress") } == "12.121.122.82"
|
503
|
-
insist { e.get("ad.field[0]") } ==
|
504
|
-
insist { e.get("ad.name[1]") } ==
|
503
|
+
insist { e.get("ad.field[0]") } == "field0"
|
504
|
+
insist { e.get("ad.name[1]") } == "new_name"
|
505
|
+
insist { e.get("ad.Authentification") } == "MICROSOFT_AUTHENTICATION_PACKAGE_V1_0"
|
506
|
+
insist { e.get("ad.Error_,Code") } == "3221225578"
|
507
|
+
insist { e.get("additional.dotfieldName") } == "new_value"
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
let (:preserve_random_values_key_value_pairs_alongside_with_additional_fields) {'CEF:0|security|threatmanager|1.0|100|trojan successfully stopped|10|src=10.0.0.192 cs4=401 random.user Admin 0 23041A10181C0000 23041810181C0000 /CN\=random.user/OU\=User Login End-Entity /CN\=TEST/OU\=Login CA TEST 34 additional.dotfieldName=new_value ad.Authentification=MICROSOFT_AUTHENTICATION_PACKAGE_V1_0 ad.Error_,Code=3221225578 dst=12.121.122.82 ad.field[0]=field0 ad.name[1]=new_name'}
|
512
|
+
it "should correctly parse random values even with additional fields in message" do
|
513
|
+
subject.decode(preserve_random_values_key_value_pairs_alongside_with_additional_fields) do |e|
|
514
|
+
validate(e)
|
515
|
+
insist { e.get("sourceAddress") } == "10.0.0.192"
|
516
|
+
insist { e.get("destinationAddress") } == "12.121.122.82"
|
517
|
+
insist { e.get("ad.field[0]") } == "field0"
|
518
|
+
insist { e.get("ad.name[1]") } == "new_name"
|
519
|
+
insist { e.get("ad.Authentification") } == "MICROSOFT_AUTHENTICATION_PACKAGE_V1_0"
|
520
|
+
insist { e.get("ad.Error_,Code") } == "3221225578"
|
521
|
+
insist { e.get("additional.dotfieldName") } == "new_value"
|
522
|
+
insist { e.get("deviceCustomString4") } == "401 random.user Admin 0 23041A10181C0000 23041810181C0000 /CN\=random.user/OU\=User Login End-Entity /CN\=TEST/OU\=Login CA TEST 34"
|
505
523
|
end
|
506
524
|
end
|
507
525
|
|
508
526
|
let (:preserve_unmatched_key_mappings) {'CEF:0|security|threatmanager|1.0|100|trojan successfully stopped|10|src=10.0.0.192 dst=12.121.122.82 new_key_by_device=new_values here'}
|
509
|
-
it "should
|
527
|
+
it "should preserve unmatched key mappings" do
|
510
528
|
subject.decode(preserve_unmatched_key_mappings) do |e|
|
511
529
|
validate(e)
|
512
530
|
insist { e.get("sourceAddress") } == "10.0.0.192"
|
@@ -515,7 +533,7 @@ describe LogStash::Codecs::CEF do
|
|
515
533
|
end
|
516
534
|
end
|
517
535
|
|
518
|
-
let (:translate_abbreviated_cef_fields) {'CEF:0|security|threatmanager|1.0|100|trojan successfully stopped|10|src=10.0.0.192 dst=12.121.122.82 proto=TCP shost=source.host.name dhost=destination.host.name spt=11024 dpt=9200'}
|
536
|
+
let (:translate_abbreviated_cef_fields) {'CEF:0|security|threatmanager|1.0|100|trojan successfully stopped|10|src=10.0.0.192 dst=12.121.122.82 proto=TCP shost=source.host.name dhost=destination.host.name spt=11024 dpt=9200 outcome=Success'}
|
519
537
|
it "should translate most known abbreviated CEF field names" do
|
520
538
|
subject.decode(translate_abbreviated_cef_fields) do |e|
|
521
539
|
validate(e)
|
@@ -526,6 +544,7 @@ describe LogStash::Codecs::CEF do
|
|
526
544
|
insist { e.get("destinationHostName") } == "destination.host.name"
|
527
545
|
insist { e.get("sourcePort") } == "11024"
|
528
546
|
insist { e.get("destinationPort") } == "9200"
|
547
|
+
insist { e.get("eventOutcome") } == "Success"
|
529
548
|
end
|
530
549
|
end
|
531
550
|
|
@@ -537,7 +556,7 @@ describe LogStash::Codecs::CEF do
|
|
537
556
|
end
|
538
557
|
end
|
539
558
|
end
|
540
|
-
|
559
|
+
|
541
560
|
context "decode with deprecated version option" do
|
542
561
|
let (:message) { "CEF:0|security|threatmanager|1.0|100|trojan successfully stopped|10|src=10.0.0.192 dst=12.121.122.82 spt=1232" }
|
543
562
|
let(:options) {
|
@@ -545,10 +564,10 @@ describe LogStash::Codecs::CEF do
|
|
545
564
|
"deprecated_v1_fields" => true
|
546
565
|
}
|
547
566
|
}
|
548
|
-
|
567
|
+
|
549
568
|
subject(:codec) { LogStash::Codecs::CEF.new(options) }
|
550
|
-
|
551
|
-
def validate(e)
|
569
|
+
|
570
|
+
def validate(e)
|
552
571
|
insist { e.is_a?(LogStash::Event) }
|
553
572
|
insist { e.get('cef_version') } == "0"
|
554
573
|
insist { e.get('cef_device_version') } == "1.0"
|
@@ -590,7 +609,7 @@ describe LogStash::Codecs::CEF do
|
|
590
609
|
subject.decode(no_ext) do |e|
|
591
610
|
validate(e)
|
592
611
|
insist { e.get("cef_ext") } == nil
|
593
|
-
end
|
612
|
+
end
|
594
613
|
end
|
595
614
|
|
596
615
|
let (:missing_headers) { "CEF:0|||1.0|100|trojan successfully stopped|10|src=10.0.0.192 dst=12.121.122.82 spt=1232" }
|
@@ -601,14 +620,14 @@ describe LogStash::Codecs::CEF do
|
|
601
620
|
insist { e.get("cef_product") } == ""
|
602
621
|
insist { e.get("deviceVendor") } == ""
|
603
622
|
insist { e.get("deviceProduct") } == ""
|
604
|
-
end
|
623
|
+
end
|
605
624
|
end
|
606
625
|
|
607
626
|
let (:leading_whitespace) { "CEF:0|security|threatmanager|1.0|100|trojan successfully stopped|10| src=10.0.0.192 dst=12.121.122.82 spt=1232" }
|
608
627
|
it "should strip leading whitespace from the message" do
|
609
628
|
subject.decode(leading_whitespace) do |e|
|
610
629
|
validate(e)
|
611
|
-
end
|
630
|
+
end
|
612
631
|
end
|
613
632
|
|
614
633
|
let (:escaped_pipes) { 'CEF:0|security|threatmanager|1.0|100|trojan successfully stopped|10|moo=this\|has an escaped pipe' }
|
@@ -616,7 +635,7 @@ describe LogStash::Codecs::CEF do
|
|
616
635
|
subject.decode(escaped_pipes) do |e|
|
617
636
|
ext = e.get('cef_ext')
|
618
637
|
insist { ext['moo'] } == 'this\|has an escaped pipe'
|
619
|
-
end
|
638
|
+
end
|
620
639
|
end
|
621
640
|
|
622
641
|
let (:pipes_in_message) {'CEF:0|security|threatmanager|1.0|100|trojan successfully stopped|10|moo=this|has an pipe'}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-codec-cef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.2
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|