metasploit_data_models 0.17.1-java → 0.17.2-java
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 +4 -4
- data/.travis.yml +4 -0
- data/Gemfile +2 -0
- data/app/models/mdm/host.rb +24 -0
- data/app/models/mdm/service.rb +9 -0
- data/app/models/metasploit_data_models/search/visitor/attribute.rb +13 -0
- data/app/models/metasploit_data_models/search/visitor/includes.rb +28 -0
- data/app/models/metasploit_data_models/search/visitor/joins.rb +47 -0
- data/app/models/metasploit_data_models/search/visitor/method.rb +13 -0
- data/app/models/metasploit_data_models/search/visitor/relation.rb +87 -0
- data/app/models/metasploit_data_models/search/visitor/where.rb +65 -0
- data/config/locales/en.yml +7 -0
- data/lib/metasploit_data_models.rb +1 -0
- data/lib/metasploit_data_models/search.rb +6 -0
- data/lib/metasploit_data_models/search/visitor.rb +8 -0
- data/lib/metasploit_data_models/version.rb +1 -1
- data/metasploit_data_models.gemspec +1 -0
- data/spec/app/models/metasploit_data_models/search/visitor/attribute_spec.rb +74 -0
- data/spec/app/models/metasploit_data_models/search/visitor/includes_spec.rb +124 -0
- data/spec/app/models/metasploit_data_models/search/visitor/joins_spec.rb +292 -0
- data/spec/app/models/metasploit_data_models/search/visitor/method_spec.rb +33 -0
- data/spec/app/models/metasploit_data_models/search/visitor/relation_spec.rb +253 -0
- data/spec/app/models/metasploit_data_models/search/visitor/where_spec.rb +147 -0
- data/spec/dummy/config/initializers/active_record_migrations.rb +4 -0
- data/spec/factories/mdm/services.rb +5 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_children.rb +38 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_metasploit_model_search_operation_base.rb +26 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/relation/visit/matching_record.rb +37 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/relation/visit/matching_record/with_metasploit_model_search_opeator_deprecated_platform.rb +31 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/relation/visit/matching_record/with_metasploit_model_search_operator_deprecated_authority.rb +78 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_equality.rb +34 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_metasploit_model_search_group_base.rb +50 -0
- metadata +59 -2
@@ -0,0 +1,253 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MetasploitDataModels::Search::Visitor::Relation do
|
4
|
+
subject(:visitor) do
|
5
|
+
described_class.new(
|
6
|
+
:query => query
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:formatted) do
|
11
|
+
# needs to be a valid operation so that query is valid
|
12
|
+
"name:\"#{value}\""
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:query) do
|
16
|
+
Metasploit::Model::Search::Query.new(
|
17
|
+
:formatted => formatted,
|
18
|
+
:klass => Mdm::Host
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:value) {
|
23
|
+
FactoryGirl.generate :mdm_host_name
|
24
|
+
}
|
25
|
+
|
26
|
+
context 'validations' do
|
27
|
+
context 'query' do
|
28
|
+
it { should validate_presence_of(:query) }
|
29
|
+
|
30
|
+
context 'valid' do
|
31
|
+
let(:error) do
|
32
|
+
I18n.translate('errors.messages.invalid')
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:errors) do
|
36
|
+
visitor.errors[:query]
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with query' do
|
40
|
+
let(:query) do
|
41
|
+
double('Query')
|
42
|
+
end
|
43
|
+
|
44
|
+
before(:each) do
|
45
|
+
query.stub(:valid? => query)
|
46
|
+
|
47
|
+
visitor.valid?
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'with valid' do
|
51
|
+
let(:valid) do
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should not record error' do
|
56
|
+
errors.should_not include(error)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'without valid' do
|
61
|
+
let(:valid) do
|
62
|
+
false
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should record error' do
|
66
|
+
errors.should_not include(error)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'without query' do
|
72
|
+
let(:query) do
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should not record error' do
|
77
|
+
errors.should_not include(error)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context '#visit' do
|
85
|
+
subject(:visit) do
|
86
|
+
visitor.visit
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'MetasploitDataModels::Search::Visitor::Includes' do
|
90
|
+
subject(:includes_visitor) do
|
91
|
+
visitor.visitor_by_relation_method[:includes]
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should visit Metasploit::Model::Search::Query#tree' do
|
95
|
+
includes_visitor.should_receive(:visit).with(query.tree)
|
96
|
+
|
97
|
+
visit
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should pass visited to ActiveRecord::Relation#includes' do
|
101
|
+
visited = double('Visited')
|
102
|
+
includes_visitor.stub(:visit).with(query.tree).and_return(visited)
|
103
|
+
|
104
|
+
ActiveRecord::Relation.any_instance.should_receive(:includes).with(visited).and_return(query.klass.scoped)
|
105
|
+
|
106
|
+
visit
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'MetasploitDataModels::Search::Visitor::Joins' do
|
111
|
+
subject(:joins_visitor) do
|
112
|
+
visitor.visitor_by_relation_method[:joins]
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should visit Metasploit::Model::Search::Query#tree' do
|
116
|
+
joins_visitor.should_receive(:visit).with(query.tree)
|
117
|
+
|
118
|
+
visit
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should pass visited to ActiveRecord::Relation#joins' do
|
122
|
+
visited = double('Visited')
|
123
|
+
joins_visitor.stub(:visit).with(query.tree).and_return(visited)
|
124
|
+
|
125
|
+
ActiveRecord::Relation.any_instance.should_receive(:joins).with(visited).and_return(query.klass.scoped)
|
126
|
+
|
127
|
+
visit
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'MetasploitDataModels::Search::Visitor::Where' do
|
132
|
+
subject(:where_visitor) do
|
133
|
+
visitor.visitor_by_relation_method[:where]
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should visit Metasploit::Model::Search::Query#tree' do
|
137
|
+
where_visitor.should_receive(:visit).with(query.tree)
|
138
|
+
|
139
|
+
visit
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should pass visited to ActiveRecord::Relation#includes' do
|
143
|
+
visited = double('Visited')
|
144
|
+
where_visitor.stub(:visit).with(query.tree).and_return(visited)
|
145
|
+
|
146
|
+
ActiveRecord::Relation.any_instance.should_receive(:where).with(visited).and_return(query.klass.scoped)
|
147
|
+
|
148
|
+
visit
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'matching record' do
|
153
|
+
context 'with Mdm::Host' do
|
154
|
+
#
|
155
|
+
# lets
|
156
|
+
#
|
157
|
+
# Don't use factories to prevent prefix aliasing when sequences go from 1 to 10 or 10 to 100
|
158
|
+
#
|
159
|
+
|
160
|
+
let(:matching_record_name) {
|
161
|
+
'mdm_host_name_a'
|
162
|
+
}
|
163
|
+
|
164
|
+
let(:matching_service_name) {
|
165
|
+
'mdm_service_name_a'
|
166
|
+
}
|
167
|
+
|
168
|
+
let(:non_matching_record_name) {
|
169
|
+
'mdm_host_name_b'
|
170
|
+
}
|
171
|
+
|
172
|
+
let(:non_matching_service_name) {
|
173
|
+
'mdm_service_name_b'
|
174
|
+
}
|
175
|
+
|
176
|
+
#
|
177
|
+
# let!s
|
178
|
+
#
|
179
|
+
|
180
|
+
let!(:matching_record) do
|
181
|
+
FactoryGirl.build(
|
182
|
+
:mdm_host,
|
183
|
+
name: matching_record_name
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
let!(:matching_service) do
|
188
|
+
FactoryGirl.create(
|
189
|
+
:mdm_service,
|
190
|
+
host: matching_record,
|
191
|
+
name: matching_service_name
|
192
|
+
)
|
193
|
+
end
|
194
|
+
|
195
|
+
let!(:non_matching_record) do
|
196
|
+
FactoryGirl.build(
|
197
|
+
:mdm_host,
|
198
|
+
name: non_matching_record_name
|
199
|
+
)
|
200
|
+
end
|
201
|
+
|
202
|
+
let!(:non_matching_service) do
|
203
|
+
FactoryGirl.create(
|
204
|
+
:mdm_service,
|
205
|
+
host: non_matching_record,
|
206
|
+
name: non_matching_service_name
|
207
|
+
)
|
208
|
+
end
|
209
|
+
|
210
|
+
it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
|
211
|
+
:attribute => :name
|
212
|
+
|
213
|
+
it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
|
214
|
+
association: :services,
|
215
|
+
attribute: :name
|
216
|
+
|
217
|
+
context 'with all operators' do
|
218
|
+
let(:formatted) {
|
219
|
+
%Q{name:"#{matching_record_name}" services.name:"#{matching_service_name}"}
|
220
|
+
}
|
221
|
+
|
222
|
+
it 'should find only matching record' do
|
223
|
+
if visit.to_a != [matching_record]
|
224
|
+
true
|
225
|
+
end
|
226
|
+
|
227
|
+
expect(visit).to match_array([matching_record])
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context '#visitor_by_relation_method' do
|
235
|
+
subject(:visitor_by_relation_method) do
|
236
|
+
visitor.visitor_by_relation_method
|
237
|
+
end
|
238
|
+
|
239
|
+
its([:joins]) { should be_a MetasploitDataModels::Search::Visitor::Joins }
|
240
|
+
its([:includes]) { should be_a MetasploitDataModels::Search::Visitor::Includes }
|
241
|
+
its([:where]) { should be_a MetasploitDataModels::Search::Visitor::Where }
|
242
|
+
end
|
243
|
+
|
244
|
+
context 'visitor_class_by_relation_method' do
|
245
|
+
subject(:visitor_class_by_relation_method) do
|
246
|
+
described_class.visitor_class_by_relation_method
|
247
|
+
end
|
248
|
+
|
249
|
+
its([:joins]) { should == MetasploitDataModels::Search::Visitor::Joins }
|
250
|
+
its([:includes]) { should == MetasploitDataModels::Search::Visitor::Includes }
|
251
|
+
its([:where]) { should == MetasploitDataModels::Search::Visitor::Where }
|
252
|
+
end
|
253
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MetasploitDataModels::Search::Visitor::Where do
|
4
|
+
subject(:visitor) do
|
5
|
+
described_class.new
|
6
|
+
end
|
7
|
+
|
8
|
+
context '#attribute_visitor' do
|
9
|
+
subject(:attribute_visitor) do
|
10
|
+
visitor.attribute_visitor
|
11
|
+
end
|
12
|
+
|
13
|
+
it { should be_a MetasploitDataModels::Search::Visitor::Attribute }
|
14
|
+
end
|
15
|
+
|
16
|
+
context '#method_visitor' do
|
17
|
+
subject(:method_visitor) do
|
18
|
+
visitor.method_visitor
|
19
|
+
end
|
20
|
+
|
21
|
+
it { should be_a MetasploitDataModels::Search::Visitor::Method }
|
22
|
+
end
|
23
|
+
|
24
|
+
context '#visit' do
|
25
|
+
subject(:visit) do
|
26
|
+
visitor.visit(node)
|
27
|
+
end
|
28
|
+
|
29
|
+
arel_class_by_group_class = {
|
30
|
+
Metasploit::Model::Search::Group::Intersection => Arel::Nodes::And,
|
31
|
+
Metasploit::Model::Search::Group::Union => Arel::Nodes::Or
|
32
|
+
}
|
33
|
+
|
34
|
+
arel_class_by_group_class.each do |group_class, arel_class|
|
35
|
+
context "with #{group_class}" do
|
36
|
+
it_should_behave_like 'MetasploitDataModels::Search::Visitor::Where#visit with Metasploit::Model::Search::Group::Base',
|
37
|
+
:arel_class => arel_class do
|
38
|
+
let(:node_class) do
|
39
|
+
group_class
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
equality_operation_classes = [
|
46
|
+
Metasploit::Model::Search::Operation::Boolean,
|
47
|
+
Metasploit::Model::Search::Operation::Date,
|
48
|
+
Metasploit::Model::Search::Operation::Integer,
|
49
|
+
Metasploit::Model::Search::Operation::Set::Integer,
|
50
|
+
Metasploit::Model::Search::Operation::Set::String
|
51
|
+
]
|
52
|
+
|
53
|
+
equality_operation_classes.each do |operation_class|
|
54
|
+
context "with #{operation_class}" do
|
55
|
+
it_should_behave_like 'MetasploitDataModels::Search::Visitor::Where#visit with equality operation' do
|
56
|
+
let(:node_class) do
|
57
|
+
operation_class
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'with Metasploit::Model::Search::Operation::String' do
|
64
|
+
let(:node) do
|
65
|
+
Metasploit::Model::Search::Operation::String.new(
|
66
|
+
:operator => operator,
|
67
|
+
:value => value
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
let(:operator) do
|
72
|
+
Metasploit::Model::Search::Operator::Attribute.new(
|
73
|
+
:klass => Mdm::Host,
|
74
|
+
:attribute => :name
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
let(:value) do
|
79
|
+
'metasploitable'
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should visit operation.operator with attribute_visitor' do
|
83
|
+
visitor.attribute_visitor.should_receive(:visit).with(operator).and_call_original
|
84
|
+
|
85
|
+
visit
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should call matches on Arel::Attributes::Attribute from attribute_visitor' do
|
89
|
+
attribute = double('Visited Operator')
|
90
|
+
visitor.attribute_visitor.stub(:visit).with(operator).and_return(attribute)
|
91
|
+
|
92
|
+
attribute.should_receive(:matches).with("%#{value}%")
|
93
|
+
|
94
|
+
visit
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'with Metasploit::Model::Search::Query#tree' do
|
99
|
+
let(:node) do
|
100
|
+
query.tree
|
101
|
+
end
|
102
|
+
|
103
|
+
let(:query) do
|
104
|
+
Metasploit::Model::Search::Query.new(
|
105
|
+
:formatted => formatted,
|
106
|
+
:klass => klass
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'with Metasploit::model::Search::Query#klass' do
|
111
|
+
context 'with Mdm::Host' do
|
112
|
+
let(:klass) {
|
113
|
+
Mdm::Host
|
114
|
+
}
|
115
|
+
|
116
|
+
context 'with name' do
|
117
|
+
let(:name) do
|
118
|
+
FactoryGirl.generate :mdm_host_name
|
119
|
+
end
|
120
|
+
|
121
|
+
let(:formatted) do
|
122
|
+
"name:\"#{name}\""
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should match module_instances.name with ILIKE' do
|
126
|
+
visit.to_sql.should == "\"hosts\".\"name\" ILIKE '%#{name}%'"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'with services.name' do
|
131
|
+
let(:name) do
|
132
|
+
FactoryGirl.generate :mdm_service_name
|
133
|
+
end
|
134
|
+
|
135
|
+
let(:formatted) do
|
136
|
+
"services.name:\"#{name}\""
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should match module_actions.name with ILIKE' do
|
140
|
+
visit.to_sql.should == "\"services\".\"name\" ILIKE '%#{name}%'"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -8,6 +8,7 @@ FactoryGirl.define do
|
|
8
8
|
#
|
9
9
|
# Attributes
|
10
10
|
#
|
11
|
+
name { generate :mdm_service_name }
|
11
12
|
port 4567
|
12
13
|
proto 'snmp'
|
13
14
|
state 'open'
|
@@ -19,6 +20,10 @@ FactoryGirl.define do
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
23
|
+
sequence(:mdm_service_name) { |n|
|
24
|
+
"mdm_service_name#{n}"
|
25
|
+
}
|
26
|
+
|
22
27
|
port_bits = 16
|
23
28
|
port_limit = 1 << port_bits
|
24
29
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
shared_examples_for 'MetasploitDataModels::Search::Visitor::Includes#visit with #children' do
|
2
|
+
let(:children) do
|
3
|
+
2.times.collect { |n|
|
4
|
+
double("Child #{n}")
|
5
|
+
}
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:node) do
|
9
|
+
node_class.new(
|
10
|
+
:children => children
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should visit each child' do
|
15
|
+
# needed for call to visit subject
|
16
|
+
visitor.should_receive(:visit).with(node).and_call_original
|
17
|
+
|
18
|
+
children.each do |child|
|
19
|
+
visitor.should_receive(:visit).with(child).and_return([])
|
20
|
+
end
|
21
|
+
|
22
|
+
visit
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should return Array of all child visits' do
|
26
|
+
child_visits = []
|
27
|
+
|
28
|
+
visitor.should_receive(:visit).with(node).and_call_original
|
29
|
+
|
30
|
+
children.each_with_index do |child, i|
|
31
|
+
child_visit = ["Visited Child #{i}"]
|
32
|
+
visitor.stub(:visit).with(child).and_return(child_visit)
|
33
|
+
child_visits.concat(child_visit)
|
34
|
+
end
|
35
|
+
|
36
|
+
visit.should == child_visits
|
37
|
+
end
|
38
|
+
end
|