metasploit_data_models 0.15.2 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/Gemfile +2 -0
  2. data/app/models/mdm/client.rb +0 -1
  3. data/app/models/mdm/cred.rb +1 -1
  4. data/app/models/mdm/exploited_host.rb +0 -1
  5. data/app/models/mdm/listener.rb +2 -1
  6. data/app/models/mdm/nexpose_console.rb +2 -2
  7. data/app/models/mdm/session.rb +5 -1
  8. data/app/models/mdm/workspace.rb +0 -1
  9. data/db/migrate/20130525015035_remove_campaign_id_from_clients.rb +9 -0
  10. data/db/migrate/20130525212420_drop_table_imported_creds.rb +14 -0
  11. data/db/migrate/20130531144949_making_host_tags_a_real_ar_model.rb +6 -0
  12. data/lib/mdm/host/operating_system_normalization.rb +4 -4
  13. data/lib/metasploit_data_models/version.rb +1 -1
  14. data/spec/app/models/mdm/client_spec.rb +43 -0
  15. data/spec/app/models/mdm/cred_spec.rb +211 -0
  16. data/spec/app/models/mdm/events_spec.rb +85 -0
  17. data/spec/app/models/mdm/exploit_attempt_spec.rb +60 -0
  18. data/spec/app/models/mdm/exploited_host_spec.rb +44 -0
  19. data/spec/app/models/mdm/host_detail_spec.rb +49 -0
  20. data/spec/app/models/mdm/host_spec.rb +468 -0
  21. data/spec/app/models/mdm/host_tag_spec.rb +26 -0
  22. data/spec/app/models/mdm/listener_spec.rb +108 -0
  23. data/spec/app/models/mdm/loot_spec.rb +77 -0
  24. data/spec/app/models/mdm/nexpose_console_spec.rb +128 -0
  25. data/spec/app/models/mdm/note_spec.rb +84 -0
  26. data/spec/app/models/mdm/ref_spec.rb +13 -0
  27. data/spec/app/models/mdm/report_spec.rb +104 -0
  28. data/spec/app/models/mdm/report_template_spec.rb +52 -0
  29. data/spec/app/models/mdm/route_spec.rb +36 -0
  30. data/spec/app/models/mdm/service_spec.rb +70 -15
  31. data/spec/app/models/mdm/session_event_spec.rb +42 -0
  32. data/spec/app/models/mdm/session_spec.rb +114 -0
  33. data/spec/app/models/mdm/tag_spec.rb +104 -0
  34. data/spec/app/models/mdm/task_creds_spec.rb +32 -0
  35. data/spec/app/models/mdm/task_host_spec.rb +33 -0
  36. data/spec/app/models/mdm/task_service_spec.rb +33 -0
  37. data/spec/app/models/mdm/task_spec.rb +59 -5
  38. data/spec/app/models/mdm/user_spec.rb +51 -0
  39. data/spec/app/models/mdm/vuln_attempt_spec.rb +54 -0
  40. data/spec/app/models/mdm/vuln_details_spec.rb +66 -0
  41. data/spec/app/models/mdm/vuln_ref_spec.rb +24 -0
  42. data/spec/app/models/mdm/vuln_spec.rb +25 -0
  43. data/spec/app/models/mdm/web_form_spec.rb +47 -0
  44. data/spec/app/models/mdm/web_page_spec.rb +55 -0
  45. data/spec/app/models/mdm/web_site_spec.rb +86 -0
  46. data/spec/app/models/mdm/web_vuln_spec.rb +12 -0
  47. data/spec/app/models/mdm/workspace_spec.rb +567 -0
  48. data/spec/dummy/db/schema.rb +5 -13
  49. data/spec/factories/mdm/addresses.rb +5 -0
  50. data/spec/factories/mdm/clients.rb +8 -0
  51. data/spec/factories/mdm/events.rb +15 -0
  52. data/spec/factories/mdm/exploit_attempts.rb +8 -0
  53. data/spec/factories/mdm/exploited_hosts.rb +7 -0
  54. data/spec/factories/mdm/fingerprints/nessus_fingerprints.rb +6 -0
  55. data/spec/factories/mdm/fingerprints/nexpose_fingerprints.rb +6 -0
  56. data/spec/factories/mdm/fingerprints/nmap_fingerprints.rb +6 -0
  57. data/spec/factories/mdm/fingerprints/retina_fingerprints.rb +6 -0
  58. data/spec/factories/mdm/fingerprints/session_fingerprints.rb +6 -0
  59. data/spec/factories/mdm/host_details.rb +8 -0
  60. data/spec/factories/mdm/listeners.rb +12 -0
  61. data/spec/factories/mdm/loots.rb +11 -0
  62. data/spec/factories/mdm/nexpose_consoles.rb +15 -0
  63. data/spec/factories/mdm/notes.rb +12 -0
  64. data/spec/factories/mdm/report_templates.rb +8 -0
  65. data/spec/factories/mdm/reports.rb +13 -0
  66. data/spec/factories/mdm/routes.rb +36 -0
  67. data/spec/factories/mdm/session_events.rb +8 -0
  68. data/spec/factories/mdm/sessions.rb +13 -0
  69. data/spec/factories/mdm/vuln_attempts.rb +8 -0
  70. data/spec/factories/mdm/vuln_details.rb +8 -0
  71. data/spec/factories/mdm/web_forms.rb +33 -0
  72. data/spec/factories/mdm/web_pages.rb +64 -0
  73. metadata +95 -5
  74. data/app/models/mdm/imported_cred.rb +0 -10
@@ -18,5 +18,29 @@ describe Mdm::VulnRef do
18
18
  it { should have_db_column(:vuln_id).of_type(:integer) }
19
19
  end
20
20
  end
21
+
22
+ context 'associations' do
23
+ it { should belong_to(:vuln).class_name('Mdm::Vuln') }
24
+ it { should belong_to(:ref).class_name('Mdm::Ref') }
25
+ end
26
+
27
+ context 'factory' do
28
+ it 'should be valid' do
29
+ vuln_ref = FactoryGirl.build(:mdm_vuln_ref)
30
+ vuln_ref.should be_valid
31
+ end
32
+ end
33
+
34
+ context '#destroy' do
35
+ it 'should successfully destroy the object' do
36
+ vuln_ref = FactoryGirl.create(:mdm_vuln_ref)
37
+ expect {
38
+ vuln_ref.destroy
39
+ }.to_not raise_error
40
+ expect {
41
+ vuln_ref.reload
42
+ }.to raise_error(ActiveRecord::RecordNotFound)
43
+ end
44
+ end
21
45
 
22
46
  end
@@ -5,6 +5,31 @@ describe Mdm::Vuln do
5
5
  FactoryGirl.build(:mdm_vuln)
6
6
  end
7
7
 
8
+ context '#destroy' do
9
+ it 'should successfully destroy the object and dependent objects' do
10
+ vuln = FactoryGirl.create(:mdm_vuln)
11
+ vuln_attempt = FactoryGirl.create(:mdm_vuln_attempt, :vuln => vuln)
12
+ vuln_detail = FactoryGirl.create(:mdm_vuln_detail, :vuln => vuln)
13
+ vuln_ref = FactoryGirl.create(:mdm_vuln_ref, :vuln => vuln)
14
+ expect {
15
+ vuln.destroy
16
+ }.to_not raise_error
17
+ expect {
18
+ vuln.reload
19
+ }.to raise_error(ActiveRecord::RecordNotFound)
20
+ expect {
21
+ vuln_attempt.reload
22
+ }.to raise_error(ActiveRecord::RecordNotFound)
23
+ expect {
24
+ vuln_detail.reload
25
+ }.to raise_error(ActiveRecord::RecordNotFound)
26
+ expect {
27
+ vuln_ref.reload
28
+ }.to raise_error(ActiveRecord::RecordNotFound)
29
+ end
30
+ end
31
+
32
+
8
33
  context 'associations' do
9
34
  it { should belong_to(:host).class_name('Mdm::Host') }
10
35
  it { should belong_to(:service).class_name('Mdm::Service') }
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::WebForm do
4
+
5
+ context 'associations' do
6
+ it { should belong_to(:web_site).class_name('Mdm::WebSite') }
7
+ end
8
+
9
+ context 'database' do
10
+
11
+ context 'timestamps'do
12
+ it { should have_db_column(:created_at).of_type(:datetime).with_options(:null => false) }
13
+ it { should have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) }
14
+ end
15
+
16
+ context 'columns' do
17
+ it { should have_db_column(:web_site_id).of_type(:integer).with_options(:null => false) }
18
+ it { should have_db_column(:path).of_type(:text) }
19
+ it { should have_db_column(:method).of_type(:string) }
20
+ it { should have_db_column(:params).of_type(:text) }
21
+ it { should have_db_column(:query).of_type(:text) }
22
+ end
23
+
24
+ context 'indices' do
25
+ it { should have_db_index(:path) }
26
+ end
27
+ end
28
+
29
+ context 'factory' do
30
+ it 'should be valid' do
31
+ web_form = FactoryGirl.build(:mdm_web_form)
32
+ web_form.should be_valid
33
+ end
34
+ end
35
+
36
+ context '#destroy' do
37
+ it 'should successfully destroy the object' do
38
+ web_form = FactoryGirl.create(:mdm_web_form)
39
+ expect {
40
+ web_form.destroy
41
+ }.to_not raise_error
42
+ expect {
43
+ web_form.reload
44
+ }.to raise_error(ActiveRecord::RecordNotFound)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::WebPage do
4
+
5
+ context 'associations' do
6
+ it { should belong_to(:web_site).class_name('Mdm::WebSite') }
7
+ end
8
+
9
+ context 'database' do
10
+
11
+ context 'timestamps'do
12
+ it { should have_db_column(:created_at).of_type(:datetime).with_options(:null => false) }
13
+ it { should have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) }
14
+ it { should have_db_column(:mtime).of_type(:datetime) }
15
+ end
16
+
17
+ context 'columns' do
18
+ it { should have_db_column(:web_site_id).of_type(:integer).with_options(:null => false) }
19
+ it { should have_db_column(:path).of_type(:text) }
20
+ it { should have_db_column(:query).of_type(:text) }
21
+ it { should have_db_column(:code).of_type(:integer).with_options(:null => false) }
22
+ it { should have_db_column(:cookie).of_type(:text) }
23
+ it { should have_db_column(:auth).of_type(:text) }
24
+ it { should have_db_column(:ctype).of_type(:text) }
25
+ it { should have_db_column(:location).of_type(:text) }
26
+ it { should have_db_column(:headers).of_type(:text) }
27
+ it { should have_db_column(:body).of_type(:binary) }
28
+ it { should have_db_column(:request).of_type(:binary) }
29
+ end
30
+
31
+ context 'indices' do
32
+ it { should have_db_index(:path) }
33
+ it { should have_db_index(:query) }
34
+ end
35
+ end
36
+
37
+ context 'factory' do
38
+ it 'should be valid' do
39
+ web_page = FactoryGirl.build(:mdm_web_page)
40
+ web_page.should be_valid
41
+ end
42
+ end
43
+
44
+ context '#destroy' do
45
+ it 'should successfully destroy the object' do
46
+ web_page = FactoryGirl.create(:mdm_web_page)
47
+ expect {
48
+ web_page.destroy
49
+ }.to_not raise_error
50
+ expect {
51
+ web_page.reload
52
+ }.to raise_error(ActiveRecord::RecordNotFound)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::WebSite do
4
+
5
+ context 'factory' do
6
+ it 'should be valid' do
7
+ web_site = FactoryGirl.build(:mdm_web_site)
8
+ web_site.should be_valid
9
+ end
10
+ end
11
+
12
+ context 'database' do
13
+
14
+ context 'timestamps'do
15
+ it { should have_db_column(:created_at).of_type(:datetime).with_options(:null => false) }
16
+ it { should have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) }
17
+ end
18
+
19
+ context 'columns' do
20
+ it { should have_db_column(:service_id).of_type(:integer).with_options(:null => false) }
21
+ it { should have_db_column(:vhost).of_type(:string) }
22
+ it { should have_db_column(:comments).of_type(:text) }
23
+ it { should have_db_column(:options).of_type(:text) }
24
+ end
25
+
26
+ context 'indices' do
27
+ it { should have_db_index(:comments) }
28
+ it { should have_db_index(:options) }
29
+ it { should have_db_index(:vhost) }
30
+ end
31
+ end
32
+
33
+ context '#destroy' do
34
+ it 'should successfully destroy the object' do
35
+ web_site = FactoryGirl.create(:mdm_web_site)
36
+ expect {
37
+ web_site.destroy
38
+ }.to_not raise_error
39
+ expect {
40
+ web_site.reload
41
+ }.to raise_error(ActiveRecord::RecordNotFound)
42
+ end
43
+ end
44
+
45
+ context 'associations' do
46
+ it { should belong_to(:service).class_name('Mdm::Service') }
47
+ it { should have_many(:web_forms).class_name('Mdm::WebForm').dependent(:destroy) }
48
+ it { should have_many(:web_pages).class_name('Mdm::WebPage').dependent(:destroy) }
49
+ it { should have_many(:web_vulns).class_name('Mdm::WebVuln').dependent(:destroy) }
50
+ end
51
+
52
+ context 'methods' do
53
+ context '#form_count' do
54
+ it 'should return an accurate count of associated Webforms' do
55
+ mysite = FactoryGirl.create(:mdm_web_site)
56
+ FactoryGirl.create(:mdm_web_form, :web_site => mysite)
57
+ FactoryGirl.create(:mdm_web_form, :web_site => mysite)
58
+ mysite.form_count.should == 2
59
+ FactoryGirl.create(:mdm_web_form, :web_site => mysite)
60
+ mysite.form_count.should == 3
61
+ end
62
+ end
63
+
64
+ context '#page_count' do
65
+ it 'should return an accurate count of associated Webpages' do
66
+ mysite = FactoryGirl.create(:mdm_web_site)
67
+ FactoryGirl.create(:mdm_web_page, :web_site => mysite)
68
+ FactoryGirl.create(:mdm_web_page, :web_site => mysite)
69
+ mysite.page_count.should == 2
70
+ FactoryGirl.create(:mdm_web_page, :web_site => mysite)
71
+ mysite.page_count.should == 3
72
+ end
73
+ end
74
+
75
+ context '#vuln_count' do
76
+ it 'should return an accurate count of associated Webvulns' do
77
+ mysite = FactoryGirl.create(:mdm_web_site)
78
+ FactoryGirl.create(:mdm_web_vuln, :web_site => mysite)
79
+ FactoryGirl.create(:mdm_web_vuln, :web_site => mysite)
80
+ mysite.vuln_count.should == 2
81
+ FactoryGirl.create(:mdm_web_vuln, :web_site => mysite)
82
+ mysite.vuln_count.should == 3
83
+ end
84
+ end
85
+ end
86
+ end
@@ -44,6 +44,18 @@ describe Mdm::WebVuln do
44
44
  end
45
45
  end
46
46
 
47
+ context '#destroy' do
48
+ it 'should successfully destroy the object' do
49
+ web_vuln = FactoryGirl.create(:mdm_web_vuln)
50
+ expect {
51
+ web_vuln.destroy
52
+ }.to_not raise_error
53
+ expect {
54
+ web_vuln.reload
55
+ }.to raise_error(ActiveRecord::RecordNotFound)
56
+ end
57
+ end
58
+
47
59
  context 'database' do
48
60
  context 'columns' do
49
61
  it { should have_db_column(:blame).of_type(:text) }
@@ -0,0 +1,567 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::Workspace do
4
+ subject(:workspace) do
5
+ FactoryGirl.build(:mdm_workspace)
6
+ end
7
+
8
+ let(:default) do
9
+ 'default'
10
+ end
11
+
12
+ context 'factory' do
13
+ it 'should be valid' do
14
+ workspace = FactoryGirl.build(:mdm_workspace)
15
+ workspace.should be_valid
16
+ end
17
+ end
18
+
19
+ context '#destroy' do
20
+ it 'should successfully destroy the object and dependent objects' do
21
+ workspace = FactoryGirl.create(:mdm_workspace)
22
+ listener = FactoryGirl.create(:mdm_listener, :workspace => workspace)
23
+ report_template = FactoryGirl.create(:mdm_report_template, :workspace => workspace)
24
+ report = FactoryGirl.create(:mdm_report, :workspace => workspace)
25
+ task = FactoryGirl.create(:mdm_task, :workspace => workspace)
26
+
27
+ expect {
28
+ workspace.destroy
29
+ }.to_not raise_error
30
+ expect {
31
+ workspace.reload
32
+ }.to raise_error(ActiveRecord::RecordNotFound)
33
+ expect {
34
+ listener.reload
35
+ }.to raise_error(ActiveRecord::RecordNotFound)
36
+ expect {
37
+ report_template.reload
38
+ }.to raise_error(ActiveRecord::RecordNotFound)
39
+ expect {
40
+ report.reload
41
+ }.to raise_error(ActiveRecord::RecordNotFound)
42
+ expect {
43
+ task.reload
44
+ }.to raise_error(ActiveRecord::RecordNotFound)
45
+ end
46
+ end
47
+
48
+ context 'associations' do
49
+ it { should have_many(:clients).class_name('Mdm::Client').through(:hosts) }
50
+ it { should have_many(:creds).class_name('Mdm::Cred').through(:services) }
51
+ it { should have_many(:events).class_name('Mdm::Event') }
52
+ it { should have_many(:exploited_hosts).class_name('Mdm::ExploitedHost').through(:hosts) }
53
+ it { should have_many(:hosts).class_name('Mdm::Host') }
54
+ it { should have_many(:listeners).class_name('Mdm::Listener').dependent(:destroy) }
55
+ it { should have_many(:loots).class_name('Mdm::Loot').through(:hosts) }
56
+ it { should have_many(:notes).class_name('Mdm::Note') }
57
+ it { should belong_to(:owner).class_name('Mdm::User').with_foreign_key('owner_id') }
58
+ it { should have_many(:report_templates).class_name('Mdm::ReportTemplate').dependent(:destroy) }
59
+ it { should have_many(:reports).class_name('Mdm::Report').dependent(:destroy) }
60
+ it { should have_many(:services).class_name('Mdm::Service').through(:hosts).with_foreign_key('service_id') }
61
+ it { should have_many(:sessions).class_name('Mdm::Session').through(:hosts) }
62
+ it { should have_many(:tasks).class_name('Mdm::Task').dependent(:destroy).order('created_at DESC') }
63
+ it { should have_and_belong_to_many(:users).class_name('Mdm::User') }
64
+ it { should have_many(:vulns).class_name('Mdm::Vuln').through(:hosts) }
65
+ end
66
+
67
+ context 'callbacks' do
68
+ context 'before_save' do
69
+ context '#normalize' do
70
+ it 'should be called' do
71
+ workspace.should_receive(:normalize)
72
+ workspace.run_callbacks(:save, false)
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'columns' do
79
+ it { should have_db_column(:boundary).of_type(:string).with_options(:limit => 4 * (2 ** 10)) }
80
+ it { should have_db_column(:description).of_type(:string).with_options(:limit => 4 * (2 ** 10)) }
81
+ it { should have_db_column(:limit_to_network).of_type(:boolean).with_options(:default => false, :null => false) }
82
+ it { should have_db_column(:name).of_type(:string) }
83
+ it { should have_db_column(:owner_id).of_type(:integer) }
84
+
85
+ context 'timestamps' do
86
+ it { should have_db_column(:created_at).of_type(:datetime).with_options(:null => false) }
87
+ it { should have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) }
88
+ end
89
+ end
90
+
91
+ context 'CONSTANTS' do
92
+ it 'should define the DEFAULT name' do
93
+ described_class::DEFAULT.should == default
94
+ end
95
+ end
96
+
97
+ context 'validations' do
98
+ context 'boundary' do
99
+ let(:boundary) do
100
+ nil
101
+ end
102
+
103
+ let(:error) do
104
+ 'must be a valid IP range'
105
+ end
106
+
107
+ before(:each) do
108
+ workspace.boundary = boundary
109
+ workspace.valid?
110
+ end
111
+
112
+ it 'should validate using #valid_ip_or_range?', :pending => 'https://www.pivotaltracker.com/story/show/43244445' do
113
+ workspace.should_receive(:valid_ip_or_range?).with(boundary).and_return(false)
114
+
115
+ workspace.valid?
116
+ end
117
+
118
+ context 'with valid IP' do
119
+ let(:boundary) do
120
+ '192.168.0.1'
121
+ end
122
+
123
+ it 'should not record an error' do
124
+ workspace.errors[:boundary].should_not include(error)
125
+ end
126
+ end
127
+
128
+ context 'with valid range' do
129
+ let(:boundary) do
130
+ '192.168.0.1/24'
131
+ end
132
+
133
+ it 'should not record an error' do
134
+ workspace.errors[:boundary].should_not include(error)
135
+ end
136
+ end
137
+
138
+ context 'with invalid IP or range' do
139
+ let(:boundary) do
140
+ '192.168'
141
+ end
142
+
143
+ it 'should record error that boundary must be a valid IP range', :pending => 'https://www.pivotaltracker.com/story/show/43171927' do
144
+ workspace.should_not be_valid
145
+ workkspace.errors[:boundary].should include(error)
146
+ end
147
+ end
148
+ end
149
+
150
+ context 'description' do
151
+ it { should ensure_length_of(:description).is_at_most(4 * (2 ** 10)) }
152
+ end
153
+
154
+ context 'name' do
155
+ it { should ensure_length_of(:name).is_at_most(2**8 - 1) }
156
+ it { should validate_presence_of :name }
157
+ it { should validate_uniqueness_of :name }
158
+ end
159
+ end
160
+
161
+ context 'methods' do
162
+ let(:hosts) do
163
+ FactoryGirl.create_list(:mdm_host, 2, :workspace => workspace)
164
+ end
165
+
166
+ let(:other_hosts) do
167
+ FactoryGirl.create_list(:mdm_host, 2, :workspace => other_workspace)
168
+ end
169
+
170
+ let(:other_services) do
171
+ other_hosts.collect do |host|
172
+ FactoryGirl.create(:mdm_service, :host => host)
173
+ end
174
+ end
175
+
176
+ let(:other_web_sites) do
177
+ other_services.collect { |service|
178
+ FactoryGirl.create(:mdm_web_site, :service => service)
179
+ }
180
+ end
181
+
182
+ let(:other_workspace) do
183
+ FactoryGirl.create(:mdm_workspace)
184
+ end
185
+
186
+ let(:services) do
187
+ hosts.collect do |host|
188
+ FactoryGirl.create(:mdm_service, :host => host)
189
+ end
190
+ end
191
+
192
+ let(:web_sites) do
193
+ services.collect { |service|
194
+ FactoryGirl.create(:mdm_web_site, :service => service)
195
+ }
196
+ end
197
+
198
+ context '#creds' do
199
+ #
200
+ # Let!s (let + before(:each))
201
+ #
202
+
203
+ let!(:creds) do
204
+ services.collect do |service|
205
+ FactoryGirl.create(:mdm_cred, :service => service)
206
+ end
207
+ end
208
+
209
+ let!(:other_creds) do
210
+ other_services.collect do |service|
211
+ FactoryGirl.create(:mdm_cred, :service => service)
212
+ end
213
+ end
214
+
215
+ it 'should be an ActiveRecord::Relation', :pending => 'https://www.pivotaltracker.com/story/show/43219917' do
216
+ should be_a ActiveRecord::Relation
217
+ end
218
+
219
+ it 'should include services' do
220
+ # to_a to make query return instances
221
+ found_creds = workspace.creds.to_a
222
+
223
+ found_creds.length.should > 0
224
+ found_cred = found_creds.first
225
+
226
+ end
227
+
228
+ it 'should include hosts' do
229
+ found_creds = workspace.creds.to_a
230
+
231
+ found_creds.length.should > 0
232
+ found_cred = found_creds.first
233
+ service = found_cred.service
234
+ end
235
+
236
+ it 'should return only Mdm::Creds from hosts in workspace' do
237
+ found_creds = workspace.creds
238
+
239
+ found_creds.length.should == creds.length
240
+
241
+ found_creds.all? { |cred|
242
+ cred.service.host.workspace == workspace
243
+ }.should be_true
244
+ end
245
+ end
246
+
247
+ context 'default' do
248
+ context 'with default workspace' do
249
+ before(:each) do
250
+ FactoryGirl.create(
251
+ :mdm_workspace,
252
+ :name => default
253
+ )
254
+ end
255
+
256
+ it 'should not create workspace' do
257
+ workspace = nil
258
+
259
+ expect {
260
+ workspace = described_class.default
261
+ }.to change(Mdm::Workspace, :count).by(0)
262
+
263
+ workspace.should be_default
264
+ end
265
+ end
266
+
267
+ context 'without default workspace' do
268
+ it 'should create workspace' do
269
+ workspace = nil
270
+
271
+ expect {
272
+ workspace = described_class.default
273
+ }.to change(Mdm::Workspace, :count).by(1)
274
+
275
+ workspace.should be_default
276
+ end
277
+ end
278
+ end
279
+
280
+ context '#default?' do
281
+ subject do
282
+ workspace.default?
283
+ end
284
+
285
+ context 'with DEFAULT name' do
286
+ before(:each) do
287
+ workspace.name = default
288
+ end
289
+
290
+ it {
291
+ should be_true
292
+ }
293
+ end
294
+
295
+ context 'without DEFAULT name' do
296
+ it { should be_false }
297
+ end
298
+ end
299
+
300
+ context '#each_cred' do
301
+ it 'should pass each of the #creds to the block' do
302
+ creds = FactoryGirl.create_list(:mdm_cred, 2)
303
+ workspace.stub(:creds => creds)
304
+
305
+ expect { |block|
306
+ workspace.each_cred(&block)
307
+ }.to yield_successive_args(*creds)
308
+ end
309
+ end
310
+
311
+ context '#each_host_tag' do
312
+ it 'should pass each of the #host_tags to the block' do
313
+ tags = FactoryGirl.create_list(:mdm_tag, 2)
314
+ workspace.stub(:host_tags => tags)
315
+
316
+ expect { |block|
317
+ workspace.each_host_tag(&block)
318
+ }.to yield_successive_args(*tags)
319
+ end
320
+ end
321
+
322
+ context '#host_tags' do
323
+ let(:other_tags) do
324
+ FactoryGirl.create_list(
325
+ :mdm_tag,
326
+ 2
327
+ )
328
+ end
329
+
330
+ let(:tags) do
331
+ FactoryGirl.create_list(
332
+ :mdm_tag,
333
+ 2
334
+ )
335
+ end
336
+
337
+ subject(:host_tags) do
338
+ workspace.host_tags
339
+ end
340
+
341
+ #
342
+ # Let!s (let + before(:each))
343
+ #
344
+
345
+ let!(:host_tags) do
346
+ host_tags = []
347
+
348
+ hosts.zip(tags) do |host, tag|
349
+ host_tag = FactoryGirl.create(:mdm_host_tag, :host => host, :tag => tag)
350
+
351
+ host_tags << host_tag
352
+ end
353
+
354
+ host_tags
355
+ end
356
+
357
+ let!(:other_host_tags) do
358
+ host_tags = []
359
+
360
+ other_hosts.zip(other_tags) do |host, tag|
361
+ host_tag = FactoryGirl.create(:mdm_host_tag, :host => host, :tag => tag)
362
+
363
+ host_tags << host_tag
364
+ end
365
+
366
+ host_tags
367
+ end
368
+
369
+ it 'should return an ActiveRecord::Relation', :pending => 'https://www.pivotaltracker.com/story/show/43219917' do
370
+ should be_a ActiveRecord::Relation
371
+ end
372
+
373
+ it 'should include hosts' do
374
+ found_tags = workspace.host_tags.to_a
375
+
376
+ found_tags.length.should > 0
377
+
378
+ tag = found_tags.first
379
+ end
380
+
381
+ it 'should return only Mdm::Tags from hosts in the workspace' do
382
+ found_tags = workspace.host_tags
383
+
384
+ found_tags.length.should == tags.length
385
+
386
+ found_tags.all? { |tag|
387
+ tag.hosts.any? { |host|
388
+ host.workspace == workspace
389
+ }
390
+ }.should be_true
391
+ end
392
+ end
393
+
394
+ context '#normalize' do
395
+ let(:normalize) do
396
+ workspace.send(:normalize)
397
+ end
398
+
399
+ before(:each) do
400
+ workspace.boundary = boundary
401
+ end
402
+
403
+ context 'with boundary' do
404
+ let(:boundary) do
405
+ " #{stripped_boundary} "
406
+ end
407
+
408
+ let(:stripped_boundary) do
409
+ '192.168.0.1'
410
+ end
411
+
412
+ it "should remove spaces" do
413
+ normalize
414
+
415
+ workspace.boundary.should == stripped_boundary
416
+ end
417
+ end
418
+
419
+ context 'without boundary' do
420
+ let(:boundary) do
421
+ nil
422
+ end
423
+
424
+ it 'should not raise error' do
425
+ expect {
426
+ normalize
427
+ }.to_not raise_error
428
+ end
429
+ end
430
+ end
431
+
432
+ context '#web_forms' do
433
+
434
+ subject do
435
+ workspace.web_forms
436
+ end
437
+
438
+ #
439
+ # Let!s (let + before(:each))
440
+ #
441
+
442
+ let!(:other_web_forms) do
443
+ other_web_sites.collect { |web_site|
444
+ FactoryGirl.create(:web_form, :web_site => web_site)
445
+ }
446
+ end
447
+
448
+ let!(:web_forms) do
449
+ web_sites.collect { |web_site|
450
+ FactoryGirl.create(:web_form, :web_site => web_site)
451
+ }
452
+ end
453
+
454
+ it 'should return an ActiveRecord:Relation',
455
+ :pending => 'https://www.pivotaltracker.com/story/show/43219917' do
456
+ should be_a ActiveRecord::Relation
457
+ end
458
+
459
+ it 'should return only Mdm::WebPages from hosts in the workspace' do
460
+ found_web_forms = workspace.web_forms
461
+
462
+ found_web_forms.length.should == web_forms.length
463
+
464
+ found_web_forms.all? { |web_form|
465
+ web_form.web_site.service.host.workspace == workspace
466
+ }.should be_true
467
+ end
468
+ end
469
+
470
+ context '#web_sites' do
471
+ subject do
472
+ workspace.web_sites
473
+ end
474
+
475
+ #
476
+ # Let!s (let + before(:each))
477
+ #
478
+
479
+ before(:each) do
480
+ other_web_sites
481
+ web_sites
482
+ end
483
+
484
+ it 'should return an ActiveRecord:Relation',
485
+ :pending => 'https://www.pivotaltracker.com/story/show/43219917' do
486
+ should be_a ActiveRecord::Relation
487
+ end
488
+
489
+ it 'should return only Mdm::WebVulns from hosts in the workspace' do
490
+ # there are more web sites than those in the workspace
491
+ Mdm::WebSite.count.should > web_sites.count
492
+
493
+ found_web_sites = workspace.web_sites
494
+
495
+ found_web_sites.length.should == web_sites.count
496
+
497
+ found_web_sites.all? { |web_site|
498
+ web_site.service.host.workspace == workspace
499
+ }.should be_true
500
+ end
501
+ end
502
+
503
+ context '#web_vulns' do
504
+ subject do
505
+ workspace.web_vulns
506
+ end
507
+
508
+ #
509
+ # Let!s (let + before(:each))
510
+ #
511
+
512
+ let!(:other_web_vulns) do
513
+ other_web_sites.collect { |web_site|
514
+ FactoryGirl.create(:mdm_web_vuln, :web_site => web_site)
515
+ }
516
+ end
517
+
518
+ let!(:web_vulns) do
519
+ web_sites.collect { |web_site|
520
+ FactoryGirl.create(:mdm_web_vuln, :web_site => web_site)
521
+ }
522
+ end
523
+
524
+ it 'should return an ActiveRecord:Relation',
525
+ :pending => 'https://www.pivotaltracker.com/story/show/43219917' do
526
+ should be_a ActiveRecord::Relation
527
+ end
528
+
529
+ it 'should return only Mdm::WebVulns from hosts in the workspace' do
530
+ Mdm::WebVuln.count.should > web_vulns.length
531
+
532
+ found_web_vulns = workspace.web_vulns
533
+
534
+ found_web_vulns.length.should == web_vulns.length
535
+
536
+ found_web_vulns.all? { |web_vuln|
537
+ web_vuln.web_site.service.host.workspace == workspace
538
+ }.should be_true
539
+
540
+ end
541
+ end
542
+
543
+ context '#web_unique_forms' do
544
+ let(:rejected_address) do
545
+ hosts[1].address
546
+ end
547
+
548
+ let(:selected_address) do
549
+ hosts[0].address
550
+ end
551
+
552
+ it 'should return an ActiveRecord:Relation',
553
+ :pending => 'https://www.pivotaltracker.com/story/show/43219917' do
554
+ should be_a ActiveRecord::Relation
555
+ end
556
+
557
+ it "should reject #unique_web_forms from host addresses that aren't in addresses" do
558
+ web_forms = workspace.web_unique_forms([selected_address])
559
+
560
+ web_forms.all? { |web_form|
561
+ web_form.web_site.service.host.address.should == selected_address
562
+ }.should be_true
563
+ end
564
+ end
565
+ end
566
+
567
+ end