metasploit_data_models 0.16.4 → 0.16.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,20 +3,98 @@
3
3
  class EnforceAddressUniquenessInWorkspaceInHosts < ActiveRecord::Migration
4
4
  TABLE_NAME = :hosts
5
5
 
6
+ # maps Table -> Association Column for models that "belong to" a Host
7
+ HOST_ASSOCIATION_MAP = {
8
+ 'clients' => 'host_id',
9
+ 'events' => 'host_id',
10
+ 'exploit_attempts' => 'host_id',
11
+ 'exploited_hosts' => 'host_id',
12
+ 'host_details' => 'host_id',
13
+ 'hosts_tags' => 'host_id',
14
+ 'loots' => 'host_id',
15
+ 'notes' => 'host_id',
16
+ 'sessions' => 'host_id',
17
+ 'services' => 'host_id',
18
+ 'vulns' => 'host_id'
19
+ }
20
+
21
+ # Historically there a few scenarios where a user could end up with Hosts
22
+ # in the same workspace with the same IP. Primarily, if you run a Nexpose Scan
23
+ # and a Discover scan simultaneously, AR does not know about these separate
24
+ # transactions, so the Hosts will be valid when added and the user will end up
25
+ # (when transaction completes) with two hosts with the same IP in the same workspace.
26
+ #
27
+ # Since we are adding a DB uniq constraint here, this migration could fail if the user
28
+ # has hit aforementioned scenarios. So we try to "merge" any hosts with the same
29
+ # address in the same workspace before adding the DB constraint, to prevent the
30
+ # migration from simply failing.
31
+ #
32
+ # Note: We can't rely on AR directly here (or in any migration), since we have no
33
+ # idea what version of the code the user has checked out. So we fall back to SQL :(
34
+ def find_and_merge_duplicate_hosts!
35
+ # find all duplicate addresses within the same workspace currently in the db
36
+ dupe_addresses_and_workspaces = ActiveRecord::Base.connection.execute(%Q{
37
+ SELECT workspace_id, address, count_addr
38
+ FROM (
39
+ SELECT workspace_id, address, COUNT(address) AS count_addr
40
+ FROM hosts
41
+ GROUP BY address, workspace_id
42
+ ) X
43
+ WHERE count_addr > 1
44
+ })
45
+
46
+ if dupe_addresses_and_workspaces.present? and
47
+ not dupe_addresses_and_workspaces.num_tuples.zero?
48
+ puts "Duplicate hosts in workspace found. Merging host references."
49
+ # iterate through the duped IPs
50
+ dupe_addresses_and_workspaces.each do |result|
51
+ # so its come to this
52
+ address = ActiveRecord::Base.connection.quote(result['address'])
53
+ workspace_id = result['workspace_id'].to_i
54
+ # look up the duplicate Host table entries to find all IDs of the duped Hosts
55
+ hosts = ActiveRecord::Base.connection.execute(%Q|
56
+ SELECT id
57
+ FROM hosts
58
+ WHERE address=#{address} AND workspace_id=#{workspace_id}
59
+ ORDER BY id DESC
60
+ |)
61
+ # grab and quote the ID for each result row
62
+ hosts = hosts.map { |h| h["id"].to_i }
63
+ # grab every Host entry besides the first one
64
+ first_host_id = hosts.first
65
+ dupe_host_ids = hosts[1..-1]
66
+ # update associations to these duplicate Hosts
67
+ HOST_ASSOCIATION_MAP.each do |table, column|
68
+ ActiveRecord::Base.connection.execute(%Q|
69
+ UPDATE #{table} SET #{column}=#{first_host_id}
70
+ WHERE #{column} IN (#{dupe_host_ids.join(',')})
71
+ |)
72
+ end
73
+ # destroy the duplicate host rows
74
+ ActiveRecord::Base.connection.execute(%Q|
75
+ DELETE FROM hosts WHERE id IN (#{dupe_host_ids.join(',')})
76
+ |)
77
+ end
78
+
79
+ # At this point all duped hosts in the same workspace should be merged.
80
+ # You could end up with duplicate services, but hey its better than just
81
+ # dropping all data about the old Host.
82
+ end
83
+ end
84
+
6
85
  # Restores old index on address
7
86
  def down
8
87
  change_table TABLE_NAME do |t|
9
88
  t.remove_index [:workspace_id, :address]
10
-
11
89
  t.index :address
12
90
  end
13
91
  end
14
92
 
15
93
  # Make index on address scope to workspace_id and be unique
16
94
  def up
95
+ find_and_merge_duplicate_hosts!
17
96
  change_table TABLE_NAME do |t|
18
97
  t.remove_index :address
19
-
20
98
  t.index [:workspace_id, :address], :unique => true
21
99
  end
22
100
  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.16.4'
7
+ VERSION = '0.16.5'
8
8
  end
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metasploit_data_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.4
4
+ version: 0.16.5
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Samuel Huckins
@@ -11,11 +12,12 @@ authors:
11
12
  autorequire:
12
13
  bindir: bin
13
14
  cert_chain: []
14
- date: 2013-07-05 00:00:00.000000000 Z
15
+ date: 2013-07-16 00:00:00.000000000 Z
15
16
  dependencies:
16
17
  - !ruby/object:Gem::Dependency
17
18
  name: rake
18
19
  requirement: !ruby/object:Gem::Requirement
20
+ none: false
19
21
  requirements:
20
22
  - - ! '>='
21
23
  - !ruby/object:Gem::Version
@@ -23,6 +25,7 @@ dependencies:
23
25
  type: :development
24
26
  prerelease: false
25
27
  version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
26
29
  requirements:
27
30
  - - ! '>='
28
31
  - !ruby/object:Gem::Version
@@ -30,6 +33,7 @@ dependencies:
30
33
  - !ruby/object:Gem::Dependency
31
34
  name: yard
32
35
  requirement: !ruby/object:Gem::Requirement
36
+ none: false
33
37
  requirements:
34
38
  - - ! '>='
35
39
  - !ruby/object:Gem::Version
@@ -37,6 +41,7 @@ dependencies:
37
41
  type: :development
38
42
  prerelease: false
39
43
  version_requirements: !ruby/object:Gem::Requirement
44
+ none: false
40
45
  requirements:
41
46
  - - ! '>='
42
47
  - !ruby/object:Gem::Version
@@ -44,6 +49,7 @@ dependencies:
44
49
  - !ruby/object:Gem::Dependency
45
50
  name: pry
46
51
  requirement: !ruby/object:Gem::Requirement
52
+ none: false
47
53
  requirements:
48
54
  - - ! '>='
49
55
  - !ruby/object:Gem::Version
@@ -51,6 +57,7 @@ dependencies:
51
57
  type: :development
52
58
  prerelease: false
53
59
  version_requirements: !ruby/object:Gem::Requirement
60
+ none: false
54
61
  requirements:
55
62
  - - ! '>='
56
63
  - !ruby/object:Gem::Version
@@ -58,6 +65,7 @@ dependencies:
58
65
  - !ruby/object:Gem::Dependency
59
66
  name: activerecord
60
67
  requirement: !ruby/object:Gem::Requirement
68
+ none: false
61
69
  requirements:
62
70
  - - ! '>='
63
71
  - !ruby/object:Gem::Version
@@ -65,6 +73,7 @@ dependencies:
65
73
  type: :runtime
66
74
  prerelease: false
67
75
  version_requirements: !ruby/object:Gem::Requirement
76
+ none: false
68
77
  requirements:
69
78
  - - ! '>='
70
79
  - !ruby/object:Gem::Version
@@ -72,6 +81,7 @@ dependencies:
72
81
  - !ruby/object:Gem::Dependency
73
82
  name: activesupport
74
83
  requirement: !ruby/object:Gem::Requirement
84
+ none: false
75
85
  requirements:
76
86
  - - ! '>='
77
87
  - !ruby/object:Gem::Version
@@ -79,6 +89,7 @@ dependencies:
79
89
  type: :runtime
80
90
  prerelease: false
81
91
  version_requirements: !ruby/object:Gem::Requirement
92
+ none: false
82
93
  requirements:
83
94
  - - ! '>='
84
95
  - !ruby/object:Gem::Version
@@ -86,6 +97,7 @@ dependencies:
86
97
  - !ruby/object:Gem::Dependency
87
98
  name: redcarpet
88
99
  requirement: !ruby/object:Gem::Requirement
100
+ none: false
89
101
  requirements:
90
102
  - - ! '>='
91
103
  - !ruby/object:Gem::Version
@@ -93,6 +105,7 @@ dependencies:
93
105
  type: :development
94
106
  prerelease: false
95
107
  version_requirements: !ruby/object:Gem::Requirement
108
+ none: false
96
109
  requirements:
97
110
  - - ! '>='
98
111
  - !ruby/object:Gem::Version
@@ -100,6 +113,7 @@ dependencies:
100
113
  - !ruby/object:Gem::Dependency
101
114
  name: pg
102
115
  requirement: !ruby/object:Gem::Requirement
116
+ none: false
103
117
  requirements:
104
118
  - - ! '>='
105
119
  - !ruby/object:Gem::Version
@@ -107,6 +121,7 @@ dependencies:
107
121
  type: :runtime
108
122
  prerelease: false
109
123
  version_requirements: !ruby/object:Gem::Requirement
124
+ none: false
110
125
  requirements:
111
126
  - - ! '>='
112
127
  - !ruby/object:Gem::Version
@@ -437,26 +452,33 @@ files:
437
452
  - spec/support/shared/examples/mdm/module/detail/supports_stance_with_mtype.rb
438
453
  homepage: ''
439
454
  licenses: []
440
- metadata: {}
441
455
  post_install_message:
442
456
  rdoc_options: []
443
457
  require_paths:
444
458
  - lib
445
459
  required_ruby_version: !ruby/object:Gem::Requirement
460
+ none: false
446
461
  requirements:
447
462
  - - ! '>='
448
463
  - !ruby/object:Gem::Version
449
464
  version: '0'
465
+ segments:
466
+ - 0
467
+ hash: -1502167183498467311
450
468
  required_rubygems_version: !ruby/object:Gem::Requirement
469
+ none: false
451
470
  requirements:
452
471
  - - ! '>='
453
472
  - !ruby/object:Gem::Version
454
473
  version: '0'
474
+ segments:
475
+ - 0
476
+ hash: -1502167183498467311
455
477
  requirements: []
456
478
  rubyforge_project:
457
- rubygems_version: 2.0.3
479
+ rubygems_version: 1.8.25
458
480
  signing_key:
459
- specification_version: 4
481
+ specification_version: 3
460
482
  summary: Database code for MSF and Metasploit Pro
461
483
  test_files:
462
484
  - spec/app/models/mdm/client_spec.rb
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZDhiOTE4MWQ2Y2YzMDQ4YzYyODE4MWQyNTg0ODNlY2Q1ZTg5NTIyOA==
5
- data.tar.gz: !binary |-
6
- MTc2ZTEyYjJiYjc4OTFiZWMzZWZmMTZjYjFjMTBhN2QxZjcyNDM1Mg==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MDNiODM5MzVlNzljMTM4NTFmYjk1ZmIyMmZjMWU2NTBmMjI4ZDc1NDU1M2I0
10
- MDBmY2I1NDM3ZmQ0NzIxNTIzZmNkMzMxN2MxZmI1MzM5ZDNiZTQwMjIyYmZm
11
- YWNiZTA5MTdmNmE4NGU0MDUwOTk3MGQ2MDgwOTY5OWQ5YmUzZDc=
12
- data.tar.gz: !binary |-
13
- N2YzNGQxMDM1NTNiNDg4YTg0M2YwZjMxY2VmY2NlOGI1ZDBlM2EwN2U1YzZi
14
- NzQ0NGYzMGIzYmRhN2JlOTg1NzA4ODRkMjI3MDU4NDk5OTg0YzI1YjVhYzdl
15
- NmMyNjIzNWViOGNkNjA2YWQxZWJhMWYwNzNiNjg1MDA3MzRhYmM=