metasploit_data_models 0.15.2 → 0.16.0

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.
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
data/Gemfile CHANGED
@@ -24,4 +24,6 @@ group :test do
24
24
  # need rspec-rails >= 2.12.0 as 2.12.0 adds support for redefining named subject in nested context that uses the
25
25
  # named subject from the outer context without causing a stack overflow.
26
26
  gem 'rspec-rails', '>= 2.12.0'
27
+ # used for building markup for webpage factories
28
+ gem 'builder'
27
29
  end
@@ -2,7 +2,6 @@ class Mdm::Client < ActiveRecord::Base
2
2
  #
3
3
  # Relations
4
4
  #
5
- belongs_to :campaign, :class_name => 'Mdm::Campaign'
6
5
  belongs_to :host, :class_name => 'Mdm::Host'
7
6
 
8
7
  ActiveSupport.run_load_hooks(:mdm_client, self)
@@ -60,7 +60,7 @@ class Mdm::Cred < ActiveRecord::Base
60
60
  when "ssh_pubkey"
61
61
  matches = self.ssh_public_keys
62
62
  else
63
- false
63
+ return false
64
64
  end
65
65
  matches.include?(self) and matches.include?(other_cred)
66
66
  end
@@ -5,7 +5,6 @@ class Mdm::ExploitedHost < ActiveRecord::Base
5
5
 
6
6
  belongs_to :host, :class_name => 'Mdm::Host'
7
7
  belongs_to :service, :class_name => 'Mdm::Service'
8
- belongs_to :workspace, :class_name => 'Mdm::Workspace'
9
8
 
10
9
  ActiveSupport.run_load_hooks(:mdm_exploited_host, self)
11
10
  end
@@ -17,7 +17,8 @@ class Mdm::Listener < ActiveRecord::Base
17
17
  #
18
18
 
19
19
  validates :address, :ip_format => true, :presence => true
20
- validates :port, :presence => true
20
+ validates :port, :presence => true, :numericality => { :only_integer => true }, :inclusion => {:in => 1..65535}
21
+
21
22
 
22
23
  ActiveSupport.run_load_hooks(:mdm_listener, self)
23
24
  end
@@ -9,10 +9,10 @@ class Mdm::NexposeConsole < ActiveRecord::Base
9
9
  # Validations
10
10
  #
11
11
 
12
- validates :address, :presence => true
12
+ validates :address, :ip_format => true, :presence => true
13
13
  validates :name, :presence => true
14
14
  validates :password, :presence => true
15
- validates :port, :inclusion => {:in => 1..65535}
15
+ validates :port, :numericality => { :only_integer => true }, :inclusion => {:in => 1..65535}
16
16
  validates :username, :presence => true
17
17
 
18
18
  ActiveSupport.run_load_hooks(:mdm_nexpose_console, self)
@@ -123,7 +123,11 @@ class Mdm::Session < ActiveRecord::Base
123
123
  # @return [true] if {#platform} is some version of Windows and {#stype} is `'shell'`.
124
124
  # @return [false] otherwise.
125
125
  def upgradeable?
126
- (self.platform =~ /win/ and self.stype == 'shell')
126
+ if (self.platform =~ /win/i and self.stype == 'shell')
127
+ return true
128
+ else
129
+ return false
130
+ end
127
131
  end
128
132
 
129
133
  private
@@ -18,7 +18,6 @@ class Mdm::Workspace < ActiveRecord::Base
18
18
  has_many :creds, :through => :services, :class_name => 'Mdm::Cred'
19
19
  has_many :events, :class_name => 'Mdm::Event'
20
20
  has_many :hosts, :dependent => :destroy, :class_name => 'Mdm::Host'
21
- has_many :imported_creds, :dependent => :destroy, :class_name => 'Mdm::ImportedCred'
22
21
  has_many :listeners, :dependent => :destroy, :class_name => 'Mdm::Listener'
23
22
  has_many :notes, :class_name => 'Mdm::Note'
24
23
  belongs_to :owner, :class_name => 'Mdm::User', :foreign_key => 'owner_id'
@@ -0,0 +1,9 @@
1
+ class RemoveCampaignIdFromClients < ActiveRecord::Migration
2
+ def up
3
+ remove_column :clients, :campaign_id
4
+ end
5
+
6
+ def down
7
+ remove_column :clients, :campaign_id, :integer
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ class DropTableImportedCreds < ActiveRecord::Migration
2
+ def up
3
+ drop_table :imported_creds
4
+ end
5
+
6
+ def down
7
+ create_table :imported_creds do |t|
8
+ t.integer :workspace_id, :null => false, :default => 1
9
+ t.string :user, :limit => 512
10
+ t.string :pass, :limit => 512
11
+ t.string :ptype, :limit => 16, :default => "password"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ class MakingHostTagsARealArModel < ActiveRecord::Migration
2
+ def change
3
+ add_column :hosts_tags, :id, :primary_key
4
+ end
5
+
6
+ end
@@ -742,11 +742,11 @@ module Mdm::Host::OperatingSystemNormalization
742
742
  case data[:os]
743
743
  when /Windows/
744
744
  ret.update(parse_windows_os_str(data[:os]))
745
- when /Linux ([^[:space:]]*) ([^[:space:]]*) .* (\(.*\))/
745
+ when /Linux (\d+\.\d+\.\d+\S*)\s* \((\w*)\)/
746
746
  ret[:os_name] = "Linux"
747
- ret[:name] = $1
748
- ret[:os_sp] = $2
749
- ret[:arch] = get_arch_from_string($3)
747
+ ret[:name] = data[:name]
748
+ ret[:os_sp] = $1
749
+ ret[:arch] = get_arch_from_string($2)
750
750
  else
751
751
  ret[:os_name] = data[:os]
752
752
  end
@@ -4,5 +4,5 @@ module MetasploitDataModels
4
4
  # metasploit-framework/data/sql/migrate to db/migrate in this project, not all models have specs that verify the
5
5
  # migrations (with have_db_column and have_db_index) and certain models may not be shared between metasploit-framework
6
6
  # and pro, so models may be removed in the future. Because of the unstable API the version should remain below 1.0.0
7
- VERSION = '0.15.2'
7
+ VERSION = '0.16.0'
8
8
  end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::Client do
4
+
5
+ context 'associations' do
6
+ it { should belong_to(:host).class_name('Mdm::Host') }
7
+ end
8
+
9
+ context '#destroy' do
10
+ it 'should successfully destroy the object' do
11
+ client = FactoryGirl.create(:mdm_client, :ua_string => 'user-agent')
12
+ expect {
13
+ client.destroy
14
+ }.to_not raise_error
15
+ expect {
16
+ client.reload
17
+ }.to raise_error(ActiveRecord::RecordNotFound)
18
+ end
19
+ end
20
+
21
+ context 'factory' do
22
+ it 'should be valid' do
23
+ client = FactoryGirl.build(:mdm_client)
24
+ client.should be_valid
25
+ end
26
+ end
27
+
28
+ context 'database' do
29
+ context 'columns' do
30
+ it { should have_db_column(:host_id).of_type(:integer)}
31
+ it { should have_db_column(:ua_string).of_type(:string).with_options(:null => false) }
32
+ it { should have_db_column(:ua_name).of_type(:string) }
33
+ it { should have_db_column(:ua_ver).of_type(:string) }
34
+ end
35
+
36
+ context 'timestamps' do
37
+ it { should have_db_column(:created_at).of_type(:datetime) }
38
+ it { should have_db_column(:updated_at).of_type(:datetime) }
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -8,6 +8,217 @@ describe Mdm::Cred do
8
8
  it { should belong_to(:service).class_name('Mdm::Service') }
9
9
  end
10
10
 
11
+ context 'database' do
12
+ context 'timestamps' do
13
+ it { should have_db_column(:created_at).of_type(:datetime) }
14
+ it { should have_db_column(:updated_at).of_type(:datetime) }
15
+ end
11
16
 
17
+ context 'columns' do
18
+ it { should have_db_column(:service_id).of_type(:integer).with_options(:null => false) }
19
+ it { should have_db_column(:user).of_type(:string) }
20
+ it { should have_db_column(:pass).of_type(:string) }
21
+ it { should have_db_column(:active).of_type(:boolean).with_options(:default => true) }
22
+ it { should have_db_column(:proof).of_type(:string) }
23
+ it { should have_db_column(:ptype).of_type(:string) }
24
+ it { should have_db_column(:source_id).of_type(:integer) }
25
+ it { should have_db_column(:source_type).of_type(:string) }
26
+ end
27
+ end
28
+
29
+ context '#destroy' do
30
+ it 'should successfully destroy the object and all dependent objects' do
31
+ cred = FactoryGirl.create(:mdm_cred)
32
+ task_cred = FactoryGirl.create(:mdm_task_cred, :cred => cred)
33
+ expect {
34
+ cred.destroy
35
+ }.to_not raise_error
36
+ expect {
37
+ cred.reload
38
+ }.to raise_error(ActiveRecord::RecordNotFound)
39
+ expect {
40
+ task_cred.reload
41
+ }.to raise_error(ActiveRecord::RecordNotFound)
42
+ end
43
+ end
44
+
45
+ context 'callbacks' do
46
+ context 'after_create' do
47
+ it 'should increment cred_count on the host' do
48
+ host = FactoryGirl.create(:mdm_host)
49
+ svc = FactoryGirl.create(:mdm_service, :host => host)
50
+ expect {
51
+ FactoryGirl.create(:mdm_cred, :service => svc)
52
+ }.to change{ Mdm::Host.find(host.id).cred_count}.by(1)
53
+ end
54
+ end
55
+
56
+ context 'after_destroy' do
57
+ it 'should decrement cred_count on the host' do
58
+ host = FactoryGirl.create(:mdm_host)
59
+ svc = FactoryGirl.create(:mdm_service, :host => host)
60
+ cred =FactoryGirl.create(:mdm_cred, :service => svc)
61
+ expect {
62
+ cred.destroy
63
+ }.to change{ Mdm::Host.find(host.id).cred_count}.by(-1)
64
+ end
65
+ end
66
+ end
67
+
68
+ context 'constants' do
69
+ it 'should define the key_id regex' do
70
+ described_class::KEY_ID_REGEX.should == /([0-9a-fA-F:]{47})/
71
+ end
72
+
73
+ it 'should define ptypes to humanize' do
74
+ described_class::PTYPES.should == {
75
+ 'read/write password' => 'password_rw',
76
+ 'read-only password' => 'password_ro',
77
+ 'SMB hash' => 'smb_hash',
78
+ 'SSH private key' => 'ssh_key',
79
+ 'SSH public key' => 'ssh_pubkey'
80
+ }
81
+ end
82
+ end
83
+
84
+ context 'methods' do
85
+ before(:all) do
86
+ Mdm::Workspace.any_instance.stub(:valid_ip_or_range? => true)
87
+ workspace = FactoryGirl.create(:mdm_workspace)
88
+ host = FactoryGirl.create(:mdm_host, :workspace => workspace)
89
+ @svc1 = FactoryGirl.create(:mdm_service, :host => host)
90
+ @svc2 = FactoryGirl.create(:mdm_service, :host => host)
91
+ @cred1 = FactoryGirl.create(:mdm_cred, :service => @svc1, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_key', :proof => "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a")
92
+ @pubkey = FactoryGirl.create(:mdm_cred, :service => @svc1, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_pubkey', :proof => "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a")
93
+ end
94
+
95
+ context '#ptype_human' do
96
+ it "should return 'read/write password' for 'password_rw'" do
97
+ cred = FactoryGirl.build(:mdm_cred, :user => 'msfadmin', :pass => 'msfadmin', :ptype => 'password_rw')
98
+ cred.ptype_human.should == 'read/write password'
99
+ end
100
+
101
+ it "should return 'read-only password' for 'password_ro'" do
102
+ cred = FactoryGirl.build(:mdm_cred, :user => 'msfadmin', :pass => 'msfadmin', :ptype => 'password_ro')
103
+ cred.ptype_human.should == 'read-only password'
104
+ end
105
+
106
+ it "should return 'SMB Hash' for 'smb_hash'" do
107
+ cred = FactoryGirl.build(:mdm_cred, :user => 'msfadmin', :pass => 'msfadmin', :ptype => 'smb_hash')
108
+ cred.ptype_human.should == 'SMB hash'
109
+ end
110
+
111
+ it "should return 'SSH private key' for 'ssh_key'" do
112
+ cred = FactoryGirl.build(:mdm_cred, :user => 'msfadmin', :pass => 'msfadmin', :ptype => 'ssh_key')
113
+ cred.ptype_human.should == 'SSH private key'
114
+ end
115
+
116
+ it "should return 'SSH public key' for 'ssh_pubkey'" do
117
+ cred = FactoryGirl.build(:mdm_cred, :user => 'msfadmin', :pass => 'msfadmin', :ptype => 'ssh_pubkey')
118
+ cred.ptype_human.should == 'SSH public key'
119
+ end
120
+ end
121
+
122
+ context '#ssh_key_id' do
123
+ it 'should return nil if not an ssh_key' do
124
+ cred = FactoryGirl.build(:mdm_cred, :user => 'msfadmin', :pass => 'msfadmin', :ptype => 'password_rw')
125
+ cred.ssh_key_id.should == nil
126
+ end
127
+
128
+ it 'should return nil if proof does not contain the key id' do
129
+ cred = FactoryGirl.build(:mdm_cred, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_key', :proof => "no key here")
130
+ cred.ssh_key_id.should == nil
131
+ end
132
+
133
+ it 'should return the key id for an ssh_key' do
134
+ cred = FactoryGirl.build(:mdm_cred, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_key', :proof => "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a")
135
+ cred.ssh_key_id.should == '57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a'
136
+ end
137
+
138
+ end
139
+
140
+ context '#ssh_key_matches?' do
141
+ it 'should return true if the ssh_keys match' do
142
+ cred2 = FactoryGirl.create(:mdm_cred, :service => @svc2, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_key', :proof => "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a")
143
+ cred2.ssh_key_matches?(@cred1).should == true
144
+ end
145
+
146
+ it 'should return false if passed something other than a cred' do
147
+ @cred1.ssh_key_matches?(@svc1).should == false
148
+ end
149
+
150
+ it 'should return false if the ptypes do not match' do
151
+ cred2 = FactoryGirl.create(:mdm_cred, :service => @svc2, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_pubkey', :proof => "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a")
152
+ cred2.ssh_key_matches?(@cred1).should == false
153
+ end
154
+
155
+ it 'should return false if the key ids do not match' do
156
+ cred2 = FactoryGirl.create(:mdm_cred, :service => @svc2, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_pubkey', :proof => "KEY=66:d4:22:6e:88:d6:74:A1:44:3e:d6:d5:AA:89:73:8b")
157
+ cred2.ssh_key_matches?(@cred1).should == false
158
+ end
159
+
160
+ it 'should behave the same for public keys as private keys' do
161
+ pubkey2 = FactoryGirl.create(:mdm_cred, :service => @svc1, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_pubkey', :proof => "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a")
162
+ pubkey3 = FactoryGirl.create(:mdm_cred, :service => @svc1, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_pubkey', :proof => "KEY=66:d4:22:6e:88:d6:74:A1:44:3e:d6:d5:AA:89:73:8b")
163
+ pubkey2.ssh_key_matches?(@pubkey).should == true
164
+ pubkey2.ssh_key_matches?(pubkey3).should == false
165
+ end
166
+
167
+ it 'should always return false for non ssh key creds' do
168
+ cred2 = FactoryGirl.create(:mdm_cred, :service => @svc2, :ptype => 'password', :user => 'msfadmin', :pass => 'msfadmin' )
169
+ cred3 = FactoryGirl.create(:mdm_cred, :service => @svc2, :ptype => 'password', :user => 'msfadmin', :pass => 'msfadmin' )
170
+ cred2.ssh_key_matches?(cred3).should == false
171
+ end
172
+ end
173
+
174
+ context '#ssh_keys' do
175
+ before(:all) do
176
+ @cred2 = FactoryGirl.create(:mdm_cred, :service => @svc2, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_key', :proof => "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a")
177
+ end
178
+ it 'should return all ssh private keys with a matching id' do
179
+ @cred2.ssh_keys.should include(@cred1)
180
+ end
181
+
182
+ it 'should return all ssh public keys with a matching id' do
183
+ @cred2.ssh_keys.should include(@pubkey)
184
+ end
185
+ end
186
+
187
+ context '#ssh_private_keys' do
188
+ before(:all) do
189
+ @cred2 = FactoryGirl.create(:mdm_cred, :service => @svc2, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_key', :proof => "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a")
190
+ end
191
+
192
+ it 'should return ssh private keys with matching ids' do
193
+ @cred2.ssh_private_keys.should include(@cred1)
194
+ end
195
+
196
+ it 'should not return ssh public keys with matching ids' do
197
+ @cred2.ssh_private_keys.should_not include(@pubkey)
198
+ end
199
+ end
200
+
201
+ context '#ssh_public_keys' do
202
+ before(:all) do
203
+ @cred2 = FactoryGirl.create(:mdm_cred, :service => @svc2, :user => 'msfadmin', :pass => '/path/to/keyfile', :ptype => 'ssh_key', :proof => "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a")
204
+ end
205
+
206
+ it 'should not return ssh private keys with matching ids' do
207
+ @cred2.ssh_public_keys.should_not include(@cred1)
208
+ end
209
+
210
+ it 'should return ssh public keys with matching ids' do
211
+ @cred2.ssh_public_keys.should include(@pubkey)
212
+ end
213
+ end
214
+
215
+ end
216
+
217
+ context 'factory' do
218
+ it 'should be valid' do
219
+ cred = FactoryGirl.build(:mdm_cred)
220
+ cred.should be_valid
221
+ end
222
+ end
12
223
 
13
224
  end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::Event do
4
+
5
+ context 'associations' do
6
+ it { should belong_to(:host).class_name('Mdm::Host') }
7
+ it { should belong_to(:workspace).class_name('Mdm::Workspace') }
8
+ end
9
+
10
+ context 'database' do
11
+ context 'timestamps' do
12
+ it { should have_db_column(:created_at).of_type(:datetime) }
13
+ it { should have_db_column(:updated_at).of_type(:datetime) }
14
+ end
15
+
16
+ context 'columns' do
17
+ it { should have_db_column(:workspace_id).of_type(:integer) }
18
+ it { should have_db_column(:host_id).of_type(:integer) }
19
+ it { should have_db_column(:name).of_type(:string) }
20
+ it { should have_db_column(:critical).of_type(:boolean) }
21
+ it { should have_db_column(:seen).of_type(:boolean) }
22
+ it { should have_db_column(:username).of_type(:string) }
23
+ it { should have_db_column(:info).of_type(:text) }
24
+ end
25
+ end
26
+
27
+ context '#destroy' do
28
+ it 'should successfully destroy the object and all dependent objects' do
29
+ event = FactoryGirl.create(:mdm_event)
30
+ expect {
31
+ event.destroy
32
+ }.to_not raise_error
33
+ expect {
34
+ event.reload
35
+ }.to raise_error(ActiveRecord::RecordNotFound)
36
+
37
+ end
38
+ end
39
+
40
+ context 'scopes' do
41
+ context 'flagged' do
42
+ it 'should exclude non-critical events' do
43
+ flagged_event = FactoryGirl.create(:mdm_event, :name => 'flagme', :critical => true, :seen => false)
44
+ non_critical_event = FactoryGirl.create(:mdm_event, :name => 'dontflagmebro', :critical => false, :seen => false)
45
+ flagged_set = Mdm::Event.flagged
46
+ flagged_set.should include(flagged_event)
47
+ flagged_set.should_not include(non_critical_event)
48
+ end
49
+
50
+ it 'should exclude seen events' do
51
+ flagged_event = FactoryGirl.create(:mdm_event, :name => 'flagme', :critical => true, :seen => false)
52
+ non_critical_event = FactoryGirl.create(:mdm_event, :name => 'dontflagmebro', :critical => false, :seen => true)
53
+ flagged_set = Mdm::Event.flagged
54
+ flagged_set.should include(flagged_event)
55
+ flagged_set.should_not include(non_critical_event)
56
+ end
57
+ end
58
+
59
+ context 'module_run' do
60
+ it 'should only return module_run events' do
61
+ flagged_event = FactoryGirl.create(:mdm_event, :name => 'module_run')
62
+ non_critical_event = FactoryGirl.create(:mdm_event, :name => 'dontflagmebro')
63
+ flagged_set = Mdm::Event.module_run
64
+ flagged_set.should include(flagged_event)
65
+ flagged_set.should_not include(non_critical_event)
66
+ end
67
+ end
68
+ end
69
+
70
+ context 'validations' do
71
+ it 'should require name' do
72
+ unnamed_event = FactoryGirl.build(:mdm_event, :name => nil)
73
+ unnamed_event.should_not be_valid
74
+ unnamed_event.errors[:name].should include("can't be blank")
75
+ end
76
+ end
77
+
78
+ context 'factory' do
79
+ it 'should be valid' do
80
+ event = FactoryGirl.build(:mdm_event)
81
+ event.should be_valid
82
+ end
83
+ end
84
+
85
+ end