logstash-filter-threats_classifier 1.0.4

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.
@@ -0,0 +1,78 @@
1
+ require_relative '../spec_helper'
2
+ require "logstash/filters/classifier"
3
+ require "logstash/filters/local-classifier"
4
+ require "logstash/filters/classification-request"
5
+ require "logstash/filters/center-client"
6
+
7
+ describe LogStash::Filters::Empow::Classifier do
8
+ #empow_user, empow_password, cache_size, ttl, async_local_db, elastic_hosts, elastic_index, elastic_username, elastic_password
9
+ describe "test with mocked classifiers" do
10
+ it "log with no result" do
11
+
12
+ local_classifier = instance_double(LogStash::Filters::Empow::LocalClassifier)
13
+ allow(local_classifier).to receive(:classify).and_return(nil)
14
+ allow(local_classifier).to receive(:close)
15
+
16
+ online_classifer = instance_double(LogStash::Filters::Empow::ClassificationCenterClient)
17
+ allow(online_classifer).to receive(:classify).and_return(nil)
18
+
19
+ req = "request-1"
20
+
21
+ classifier = described_class.new(online_classifer, local_classifier)
22
+
23
+ expect(local_classifier).to receive(:classify).with(req)
24
+
25
+ expect(online_classifer).to receive(:classify)
26
+
27
+ res = classifier.classify(req)
28
+
29
+ sleep 10
30
+
31
+ expect(res).to be_nil
32
+
33
+ classifier.close
34
+ end
35
+
36
+
37
+ it "log w/o results locally, online classification arrives later" do
38
+
39
+ # local_classifier = instance_double(LogStash::Filters::Empow::LocalClassifier)
40
+ # allow(local_classifier).to receive(:classify).and_return(nil)
41
+ # allow(local_classifier).to receive(:close)
42
+
43
+ # online_classifer = instance_double(LogStash::Filters::Empow::ClassificationCenterClient)
44
+ # allow(online_classifer).to receive(:classify).and_return(nil)
45
+
46
+ # req = LogStash::Filters::Empow::ClassificationRequest.new('anti-malware', 'lastline', 'assaf.clicker', nil)
47
+
48
+ # #online_classifer, local_classifier, local_db_cache, async_local_db, online_classifier_threads
49
+ # classifier = described_class.new(online_classifer, local_classifier, nil, true, 1)
50
+
51
+ # expect(local_classifier).to receive(:classify).with(req.get_key_by_term())
52
+ # expect(local_classifier).not_to receive(:classify).with(req.get_key_by_hash())
53
+
54
+ # expect(online_classifer).to receive(:classify)
55
+
56
+ # res = classifier.classify(req)
57
+
58
+ # #allow(Time).to receive(:now).and_return(5555555)
59
+
60
+ # expect(res).to be_nil
61
+
62
+ # sleep 60
63
+
64
+ # i = 20
65
+
66
+ # while i < 0 do
67
+
68
+ # result = classifier.classify(req)
69
+ # p "i: #{i} result: #{result}"
70
+
71
+ # sleep 5
72
+ # i = i - 1
73
+ # end
74
+
75
+ # classifier.close
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,20 @@
1
+ require 'aws-sdk'
2
+ require_relative '../spec_helper'
3
+ require "logstash/filters/cognito-client"
4
+
5
+ describe LogStash::Filters::Empow::CognitoClient do
6
+
7
+ describe "cognito test" do
8
+ skip "test authenticate" do
9
+
10
+ aws_region = 'us-east-2'
11
+ aws_client_id = '8dljcvt4jfif762le0ald6j'
12
+ username = 'bad'
13
+ password = 'request'
14
+
15
+ client = described_class.new(username, password, aws_region, aws_client_id)
16
+
17
+ expect{ client.authenticate }.to raise_error(Aws::CognitoIdentityProvider::Errors::UserNotFoundException)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,101 @@
1
+ require_relative '../spec_helper'
2
+ require "logstash/filters/field-handler"
3
+ require "logstash/event"
4
+
5
+ describe LogStash::Filters::Empow::FieldHandler do
6
+
7
+ let(:handler) { described_class.new("product_type", "product", "term", "is_src_internal", "is_dst_internal") }
8
+
9
+ describe "init" do
10
+ it "src internal field empty" do
11
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1"})
12
+ res = handler.event_to_classification_request(event)
13
+ expect(res).not_to be_nil
14
+ expect(res['is_src_internal']).to be true
15
+ expect(event.get("empow_warnings")).to include("src_internal_wrong_value")
16
+ end
17
+
18
+ it "dst internal field empty" do
19
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1"})
20
+ res = handler.event_to_classification_request(event)
21
+ expect(res.nil?).to be false
22
+ expect(res['is_dst_internal']).to be true
23
+ expect(event.get("empow_warnings")).to include("dst_internal_wrong_value")
24
+ end
25
+
26
+ it "src internal field numeric value" do
27
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1", "is_src_internal" => 1})
28
+ res = handler.event_to_classification_request(event)
29
+ expect(res.nil?).to be false
30
+ expect(res['is_src_internal']).to be true
31
+ expect(event.get("empow_warnings")).not_to include("src_internal_wrong_value")
32
+ end
33
+
34
+ it "src internal field wrong value" do
35
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1"}, "is_src_internal" => 11)
36
+ res = handler.event_to_classification_request(event)
37
+ expect(res.nil?).to be false
38
+ expect(res['is_src_internal']).to be true
39
+ expect(event.get("empow_warnings")).to include("src_internal_wrong_value")
40
+ end
41
+
42
+ it "dst internal field numeric value" do
43
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1", "is_dst_internal" => 1})
44
+ res = handler.event_to_classification_request(event)
45
+ expect(res.nil?).to be false
46
+ expect(res['is_dst_internal']).to be true
47
+ expect(event.get("empow_warnings")).not_to include("dst_internal_wrong_value")
48
+ end
49
+
50
+ it "dst internal field wrong numeric value" do
51
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1"}, "is_dst_internal" => 11)
52
+ res = handler.event_to_classification_request(event)
53
+ expect(res.nil?).to be false
54
+ expect(res['is_dst_internal']).to be true
55
+ expect(event.get("empow_warnings")).to include("dst_internal_wrong_value")
56
+ end
57
+
58
+ it "dst internal field wrong value" do
59
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1"}, "is_dst_internal" => [])
60
+ res = handler.event_to_classification_request(event)
61
+ expect(res.nil?).to be false
62
+ expect(res['is_dst_internal']).to be true
63
+ expect(event.get("empow_warnings")).to include("dst_internal_wrong_value")
64
+ end
65
+
66
+ it "src internal field valid values" do
67
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1", "is_src_internal" => true})
68
+ res = handler.event_to_classification_request(event)
69
+ expect(res.nil?).to be false
70
+ expect(res['is_src_internal']).to be true
71
+ expect(event.get("empow_warnings")).not_to include("src_internal_wrong_value")
72
+
73
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1", "is_src_internal" => false})
74
+ res = handler.event_to_classification_request(event)
75
+ expect(res.nil?).to be false
76
+ expect(res['is_src_internal']).to be false
77
+ expect(event.get("empow_warnings")).not_to include("src_internal_wrong_value")
78
+ end
79
+
80
+ it "dst internal field valid values" do
81
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1", "is_dst_internal" => true})
82
+ res = handler.event_to_classification_request(event)
83
+ expect(res.nil?).to be false
84
+ expect(res['is_dst_internal']).to be true
85
+ expect(event.get("empow_warnings")).not_to include("dst_internal_wrong_value")
86
+
87
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "some_av", "term" => {"signature" => "name1", "is_dst_internal" => false})
88
+ res = handler.event_to_classification_request(event)
89
+ expect(res.nil?).to be false
90
+ expect(res['is_dst_internal']).to be false
91
+ expect(event.get("empow_warnings")).not_to include("dst_internal_wrong_value")
92
+ end
93
+
94
+ it "test nested threat structure" do
95
+ my_handler = described_class.new("product_type", "product", 'threat', "is_src_internal", "is_dst_internal")
96
+ event = LogStash::Event.new("product_type" => "IDS", "product" => "snort", "threat" => {"signature" => "name1"})
97
+ res = my_handler.event_to_classification_request(event)
98
+ expect(res['term']['signature']).to eq('name1')
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,46 @@
1
+ require_relative '../spec_helper'
2
+ require "logstash/filters/local-classifier"
3
+ require "logstash/filters/elastic-db"
4
+ require "logstash/filters/classification-request"
5
+
6
+ describe LogStash::Filters::Empow::LocalClassifier do
7
+
8
+ describe "sync'ed local database as a fallback" do
9
+ it "value isn't in memory, later fetched from local db" do
10
+ local_db = instance_double(LogStash::Filters::Empow::PersistentKeyValueDB)
11
+ allow(local_db).to receive(:query).and_return(nil)
12
+ allow(local_db).to receive(:close)
13
+
14
+ classifier = described_class.new(5, 300, false, local_db)
15
+
16
+ key = LogStash::Filters::Empow::ClassificationRequest.new("product_type", "product", "threat", true, true)
17
+
18
+ expect(classifier.classify(key)).to be_nil
19
+
20
+ allow(local_db).to receive(:query).and_return("intent")
21
+
22
+ # allow backend thread to process the request
23
+ res = nil
24
+
25
+ for i in 1..10 do
26
+ sleep 1
27
+
28
+ res = classifier.classify(key)
29
+
30
+ break if !res.nil?
31
+ end
32
+
33
+ expect(res).to eq("intent")
34
+ end
35
+ end
36
+
37
+ describe "no local database configured" do
38
+ it "value isn't in memory" do
39
+ classifier = described_class.new(5, 300, false, nil)
40
+
41
+ key = "key-1"
42
+
43
+ expect(classifier.classify(key)).to be_nil
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,127 @@
1
+ require_relative '../spec_helper'
2
+ require "logstash/event"
3
+ require "logstash/filters/classifier"
4
+ require "logstash/filters/plugin-logic"
5
+
6
+ describe LogStash::Filters::Empow::PluginLogic do
7
+
8
+ let(:intent_res1) { {"p1" => "s1"} }
9
+ let(:response_body1) { {'response' => intent_res1 } }
10
+ let(:sample_response) { LogStash::Filters::Empow::SuccessfulReponse.new(response_body1) }
11
+
12
+ describe "test classification" do
13
+
14
+ it "event with warm classification" do
15
+ event = LogStash::Event.new("my_product_type" => "ids", "my_product" => "some_av", "my_term" => "name1", "my_hash" => "hash1")
16
+
17
+ field_handler = instance_double(LogStash::Filters::Empow::FieldHandler)
18
+ allow(field_handler).to receive(:event_to_classification_request).and_return("request")
19
+
20
+ classifier = instance_double(LogStash::Filters::Empow::Classifier)
21
+ allow(classifier).to receive(:classify).and_return(sample_response)
22
+
23
+ plugin_logic = described_class.new(classifier, field_handler, 60, 1, ['_timeout'], ['_error'])
24
+
25
+ expect(field_handler).to receive(:event_to_classification_request)
26
+ expect(classifier).to receive(:classify)
27
+
28
+ classified_event = plugin_logic.classify(event)
29
+
30
+ expect(classified_event).to eq(event)
31
+ expect(classified_event.get("empow_intent")).to eq(intent_res1)
32
+ end
33
+
34
+ it "event with cold classification is parked and then unparked only once" do
35
+ event = LogStash::Event.new("my_product_type" => "ids", "my_product" => "some_av", "my_term" => "name1", "my_hash" => "hash1")
36
+
37
+ field_handler = instance_double(LogStash::Filters::Empow::FieldHandler)
38
+ allow(field_handler).to receive(:event_to_classification_request).and_return("request")
39
+ allow(Time).to receive(:now).and_return(10)
40
+
41
+ classifier = instance_double(LogStash::Filters::Empow::Classifier)
42
+ allow(classifier).to receive(:classify).and_return(nil, nil, sample_response)
43
+
44
+ plugin_logic = described_class.new(classifier, field_handler, 60, 1, ['_timeout'], ['_error'])
45
+
46
+ expect(classifier).to receive(:classify)
47
+
48
+ classified_event = plugin_logic.classify(event)
49
+ expect(classified_event).to be_nil
50
+
51
+ allow(Time).to receive(:now).and_return(20)
52
+
53
+ expect(classifier).to receive(:classify)
54
+ flushed_events = plugin_logic.flush
55
+ expect(flushed_events).to be_empty
56
+
57
+ allow(Time).to receive(:now).and_return(30)
58
+ expect(classifier).to receive(:classify)
59
+
60
+ flushed_events = plugin_logic.flush
61
+ expect(flushed_events).not_to be_empty
62
+ end
63
+
64
+ it "event unparked after time expired" do
65
+ event = LogStash::Event.new("my_product_type" => "ids", "my_product" => "some_av", "my_term" => "name1", "my_hash" => "hash1")
66
+
67
+ field_handler = instance_double(LogStash::Filters::Empow::FieldHandler)
68
+ allow(field_handler).to receive(:event_to_classification_request).and_return("request")
69
+ allow(Time).to receive(:now).and_return(10)
70
+
71
+ classifier = instance_double(LogStash::Filters::Empow::Classifier)
72
+ allow(classifier).to receive(:classify).and_return(nil)
73
+
74
+ plugin_logic = described_class.new(classifier, field_handler, 60, 1, ['_timeout'], ['_error'])
75
+
76
+ expect(classifier).to receive(:classify)
77
+
78
+ classified_event = plugin_logic.classify(event)
79
+ expect(classified_event).to be_nil
80
+
81
+ allow(Time).to receive(:now).and_return(20)
82
+
83
+ expect(classifier).to receive(:classify)
84
+ flushed_events = plugin_logic.flush
85
+ expect(flushed_events).to be_empty
86
+
87
+ allow(Time).to receive(:now).and_return(100)
88
+ expect(classifier).to receive(:classify)
89
+
90
+ flushed_events = plugin_logic.flush
91
+ expect(flushed_events).not_to be_empty
92
+
93
+ insist { flushed_events[0].get("tags") }.include?("_timeout")
94
+ end
95
+
96
+ it "too many parked events" do
97
+ event1 = LogStash::Event.new("my_product_type" => "ids", "my_product" => "some_av", "my_term" => "name1", "my_hash" => "hash1")
98
+ event2 = LogStash::Event.new("my_product_type" => "ids", "my_product" => "some_av", "my_term" => "name2", "my_hash" => "hash2")
99
+
100
+ field_handler = instance_double(LogStash::Filters::Empow::FieldHandler)
101
+ allow(field_handler).to receive(:event_to_classification_request).and_return("request")
102
+ allow(Time).to receive(:now).and_return(10)
103
+
104
+ classifier = instance_double(LogStash::Filters::Empow::Classifier)
105
+ allow(classifier).to receive(:classify).and_return(nil)
106
+
107
+ plugin_logic = described_class.new(classifier, field_handler, 60, 1, ['_timeout'], ['_error'])
108
+
109
+ expect(classifier).to receive(:classify)
110
+
111
+ classified_event = plugin_logic.classify(event1)
112
+ expect(classified_event).to be_nil
113
+
114
+ classified_event = plugin_logic.classify(event2)
115
+ expect(classified_event).to eq(event1)
116
+
117
+ allow(Time).to receive(:now).and_return(20)
118
+ flushed_events = plugin_logic.flush
119
+ expect(flushed_events).to be_empty
120
+
121
+ allow(Time).to receive(:now).and_return(100)
122
+ flushed_events = plugin_logic.flush
123
+ expect(flushed_events).not_to be_empty
124
+ expect(flushed_events.length).to eq(1)
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+ require_relative '../spec_helper'
3
+ require "logstash/filters/threats_classifier"
4
+ require "logstash/event"
5
+
6
+ describe LogStash::Filters::Threats_Classifier do
7
+
8
+ before(:each) do
9
+ allow(LogStash::Filters::Empow::LocalClassifier).to receive(:new).and_return(nil)
10
+ allow(LogStash::Filters::Empow::ClassificationCenterClient).to receive(:new).and_return(nil)
11
+ allow(LogStash::Filters::Empow::Classifier).to receive(:new).and_return(nil)
12
+ end
13
+
14
+ describe "config w/o local db and with mocks for online classifier" do
15
+
16
+ it "test empty flush" do
17
+
18
+ plugin_core = instance_double(LogStash::Filters::Empow::PluginLogic)
19
+ allow(LogStash::Filters::Empow::PluginLogic).to receive(:new).and_return(plugin_core)
20
+ allow(plugin_core).to receive(:classify).and_return(nil)
21
+ allow(plugin_core).to receive(:flush).and_return([])
22
+
23
+ empty_config = {}
24
+ subject = described_class.new(empty_config)
25
+ subject.register
26
+
27
+ event = LogStash::Event.new({"data" => "empty"})
28
+
29
+ res = subject.flush({})
30
+
31
+ expect(res).to eq([])
32
+ end
33
+
34
+
35
+ it "2 events filtered w/o an answer on receive, correct event is flushed out" do
36
+
37
+ event = LogStash::Event.new({"data" => 1})
38
+
39
+ plugin_core = instance_double(LogStash::Filters::Empow::PluginLogic)
40
+ allow(LogStash::Filters::Empow::PluginLogic).to receive(:new).and_return(plugin_core)
41
+ allow(plugin_core).to receive(:classify).and_return(nil)
42
+ allow(plugin_core).to receive(:flush).and_return([event])
43
+
44
+ empty_config = {}
45
+ subject = described_class.new(empty_config)
46
+ subject.register
47
+
48
+ expect(plugin_core).to receive(:classify)
49
+
50
+ res = subject.filter(event)
51
+
52
+ expect(res).to be_nil
53
+
54
+ res = subject.flush({})
55
+
56
+ expect(res.length).to eq(1)
57
+ expect(res[0].get("data")).to eq(event.get("data"))
58
+ end
59
+
60
+ it "test answer on filter" do
61
+
62
+ event = LogStash::Event.new({"data" => "empty"})
63
+
64
+ plugin_core = instance_double(LogStash::Filters::Empow::PluginLogic)
65
+ allow(plugin_core).to receive(:classify).and_return(event)
66
+ allow(LogStash::Filters::Empow::PluginLogic).to receive(:new).and_return(plugin_core)
67
+
68
+ empty_config = {}
69
+ subject = described_class.new(empty_config)
70
+ subject.register
71
+
72
+ expect(plugin_core).to receive(:classify)
73
+ expect(subject).to receive(:filter_matched)
74
+
75
+ subject.filter(event)
76
+ end
77
+
78
+ it "test tag on error" do
79
+
80
+ event = instance_double(LogStash::Event)
81
+ allow(event).to receive(:cancel).and_raise("exception")
82
+ allow(event).to receive(:tag)
83
+
84
+ # event = .new({"data" => "empty"})
85
+
86
+ plugin_core = instance_double(LogStash::Filters::Empow::PluginLogic)
87
+ allow(plugin_core).to receive(:classify).and_return(nil)
88
+ allow(LogStash::Filters::Empow::PluginLogic).to receive(:new).and_return(plugin_core)
89
+
90
+ empty_config = {}
91
+ subject = described_class.new(empty_config)
92
+ subject.register
93
+
94
+ expect(plugin_core).to receive(:classify)
95
+ expect(event).to receive(:cancel)
96
+ expect(event).to receive(:tag).with('_empow_classifer_error')
97
+
98
+ res = subject.filter(event)
99
+
100
+ expect(res).to be_nil
101
+ end
102
+ end
103
+ end