logstash-filter-threats_classifier 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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