metasploit_data_models 0.18.1 → 0.19.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.
- checksums.yaml +8 -8
- data/app/models/mdm/host.rb +7 -0
- data/app/models/mdm/service.rb +30 -1
- data/app/models/mdm/tag.rb +10 -0
- data/app/models/metasploit_data_models/ip_address/v4/cidr.rb +14 -0
- data/app/models/metasploit_data_models/ip_address/v4/nmap.rb +14 -0
- data/app/models/metasploit_data_models/ip_address/v4/range.rb +12 -0
- data/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list.rb +126 -0
- data/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range.rb +12 -0
- data/app/models/metasploit_data_models/ip_address/v4/segment/single.rb +123 -0
- data/app/models/metasploit_data_models/ip_address/v4/segmented.rb +200 -0
- data/app/models/metasploit_data_models/ip_address/v4/single.rb +53 -0
- data/app/models/metasploit_data_models/search/operation/ip_address.rb +60 -0
- data/app/models/metasploit_data_models/search/operator/ip_address.rb +33 -0
- data/app/models/metasploit_data_models/search/visitor/attribute.rb +1 -0
- data/app/models/metasploit_data_models/search/visitor/includes.rb +1 -0
- data/app/models/metasploit_data_models/search/visitor/joins.rb +1 -0
- data/app/models/metasploit_data_models/search/visitor/where.rb +51 -0
- data/config/locales/en.yml +35 -4
- data/lib/metasploit_data_models/ip_address.rb +5 -0
- data/lib/metasploit_data_models/ip_address/cidr.rb +174 -0
- data/lib/metasploit_data_models/ip_address/range.rb +181 -0
- data/lib/metasploit_data_models/match/child.rb +48 -0
- data/lib/metasploit_data_models/match/parent.rb +103 -0
- data/lib/metasploit_data_models/version.rb +4 -4
- data/metasploit_data_models.gemspec +2 -1
- data/spec/app/models/mdm/cred_spec.rb +164 -31
- data/spec/app/models/mdm/service_spec.rb +33 -44
- data/spec/app/models/metasploit_data_models/ip_address/v4/cidr_spec.rb +121 -0
- data/spec/app/models/metasploit_data_models/ip_address/v4/nmap_spec.rb +151 -0
- data/spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb +300 -0
- data/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb +278 -0
- data/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb +304 -0
- data/spec/app/models/metasploit_data_models/ip_address/v4/segment/segmented_spec.rb +29 -0
- data/spec/app/models/metasploit_data_models/ip_address/v4/segment/single_spec.rb +315 -0
- data/spec/app/models/metasploit_data_models/ip_address/v4/single_spec.rb +183 -0
- data/spec/app/models/metasploit_data_models/search/operation/ip_address_spec.rb +182 -0
- data/spec/app/models/metasploit_data_models/search/operator/ip_address_spec.rb +19 -0
- data/spec/app/models/metasploit_data_models/search/visitor/relation_spec.rb +229 -36
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/db/structure.sql +3011 -0
- data/spec/factories/mdm/services.rb +3 -1
- data/spec/lib/metasploit_data_models/ip_address/cidr_spec.rb +350 -0
- data/spec/lib/metasploit_data_models/ip_address/range_spec.rb +77 -0
- data/spec/lib/metasploit_data_models/match/child_spec.rb +61 -0
- data/spec/lib/metasploit_data_models/match/parent_spec.rb +155 -0
- data/spec/support/matchers/match_regex_exactly.rb +28 -0
- data/spec/support/shared/contexts/rex/text.rb +15 -0
- data/spec/support/shared/examples/metasploit_data_models/search/operation/ipaddress/match.rb +109 -0
- metadata +58 -9
- data/spec/dummy/db/schema.rb +0 -609
@@ -0,0 +1,181 @@
|
|
1
|
+
# Common behavior for ranges under {MetasploitDataModels::IPAddress}, including ranges of addresses and segments.
|
2
|
+
module MetasploitDataModels::IPAddress::Range
|
3
|
+
# so that translations for error messages can be filed under metasploit_data_models/ip_address/range
|
4
|
+
extend ActiveModel::Naming
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
#
|
8
|
+
# CONSTANTS
|
9
|
+
#
|
10
|
+
|
11
|
+
# Separator between the {#begin} and {#end} in the formatted value.
|
12
|
+
SEPARATOR = '-'
|
13
|
+
|
14
|
+
#
|
15
|
+
# Attributes
|
16
|
+
#
|
17
|
+
|
18
|
+
# @!attribute value
|
19
|
+
# The range.
|
20
|
+
#
|
21
|
+
# @return [Range<Object, Objectr>] Range with {ClassMethods#extreme_class} instances for `Range#begin` and
|
22
|
+
# `Range#end`.
|
23
|
+
# @return [String] if `formatted_value` cannot be parsed into a Range.
|
24
|
+
attr_reader :value
|
25
|
+
|
26
|
+
included do
|
27
|
+
include ActiveModel::Validations
|
28
|
+
|
29
|
+
#
|
30
|
+
#
|
31
|
+
# Validations
|
32
|
+
#
|
33
|
+
#
|
34
|
+
|
35
|
+
#
|
36
|
+
# Validation Methods
|
37
|
+
#
|
38
|
+
|
39
|
+
validate :extremes_valid
|
40
|
+
validate :order
|
41
|
+
|
42
|
+
#
|
43
|
+
# Validation Attributes
|
44
|
+
#
|
45
|
+
|
46
|
+
validates :begin,
|
47
|
+
presence: true
|
48
|
+
validates :end,
|
49
|
+
presence: true
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
# Class methods added to the including `Class`.
|
55
|
+
module ClassMethods
|
56
|
+
# @note Call {#extremes} first to set {#extreme_class_name}.
|
57
|
+
#
|
58
|
+
# Regular expression that matches a string exactly when it contains an IP address range with the correct
|
59
|
+
# {#extreme_class}.
|
60
|
+
#
|
61
|
+
# @return [Regexp] {#regexp} pinned with `'\A'` and `'\z'` to the whole `String`.
|
62
|
+
def match_regexp
|
63
|
+
@match_regexp ||= /\A#{regexp}\z/
|
64
|
+
end
|
65
|
+
|
66
|
+
# @note Call {#extremes} first to set {#extreme_class_name}.
|
67
|
+
#
|
68
|
+
# The `Class` for each extreme (`Range#begin` and `Range#end`) of the range.
|
69
|
+
#
|
70
|
+
# @return [Class]
|
71
|
+
def extreme_class
|
72
|
+
@extreme_class ||= extreme_class_name.constantize
|
73
|
+
end
|
74
|
+
|
75
|
+
# The name of {#extreme_class}.
|
76
|
+
#
|
77
|
+
# @return [String] `Class#name` passed to :class_name key when {#extremes} was called.
|
78
|
+
# @return [nil] if {#extremes} has not been called.
|
79
|
+
def extreme_class_name
|
80
|
+
@extreme_class_name
|
81
|
+
end
|
82
|
+
|
83
|
+
# Sets {#extreme_class_name}.
|
84
|
+
#
|
85
|
+
# @example Setting extremes class name
|
86
|
+
# extremes class_name: 'MetasploitDataModels::IPAddress::V4::Single'
|
87
|
+
#
|
88
|
+
# @param options [Hash{Symbol => String}]
|
89
|
+
# @option options [String] :class_name {#extreme_class_name}.
|
90
|
+
# @return [void]
|
91
|
+
def extremes(options={})
|
92
|
+
options.assert_valid_keys(:class_name)
|
93
|
+
|
94
|
+
@extreme_class_name = options.fetch(:class_name)
|
95
|
+
end
|
96
|
+
|
97
|
+
# @note Call {#extremes} first to set {#extreme_class_name}.
|
98
|
+
#
|
99
|
+
# Regular expression match a {SEPARATOR} separated range with {#extreme_class} parseable `Range#begin` and
|
100
|
+
# `Range#end`.
|
101
|
+
#
|
102
|
+
# @return [Regexp]
|
103
|
+
def regexp
|
104
|
+
@regexp ||= /#{extreme_class.regexp}#{SEPARATOR}#{extreme_class.regexp}/
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# Instance Methods
|
110
|
+
#
|
111
|
+
|
112
|
+
# Begin of segment range.
|
113
|
+
#
|
114
|
+
# @return [MetasploitDataModels::IPAddress::V4::NMAP::Segment::Number] if {#value} is a `Range`.
|
115
|
+
# @return [nil] if {#value} is not a `Range`.
|
116
|
+
def begin
|
117
|
+
if value.respond_to? :begin
|
118
|
+
value.begin
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# End of segment range.
|
123
|
+
#
|
124
|
+
# @return [MetasploitDataModels::IPAddress::V4::NMAP::Segment::Number] if {#value} is a `Range`.
|
125
|
+
# @return [nil] if {#value} is not a `Range`.
|
126
|
+
def end
|
127
|
+
if value.respond_to? :end
|
128
|
+
value.end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# This range as a string. Equivalent to the original `formatted_value` passed to {#value}.
|
133
|
+
#
|
134
|
+
# @return [String]
|
135
|
+
def to_s
|
136
|
+
"#{self.begin}#{SEPARATOR}#{self.end}"
|
137
|
+
end
|
138
|
+
|
139
|
+
# Sets {#value} by breaking up the range into its begin and end Integers.
|
140
|
+
#
|
141
|
+
# @param formatted_value [#to_s]
|
142
|
+
# @return [Range<Integer, Integer>] if {SEPARATOR} is used and both extremes are Integers.
|
143
|
+
# @return [#to_s] `formatted_value` if it could not be converted
|
144
|
+
def value=(formatted_value)
|
145
|
+
formatted_extremes = formatted_value.to_s.split(SEPARATOR, 2)
|
146
|
+
|
147
|
+
extremes = formatted_extremes.map { |formatted_extreme|
|
148
|
+
self.class.extreme_class.new(value: formatted_extreme)
|
149
|
+
}
|
150
|
+
|
151
|
+
begin
|
152
|
+
@value = Range.new(*extremes)
|
153
|
+
rescue ArgumentError
|
154
|
+
@value = formatted_value
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
# Validates that {#begin} and {#end} are valid.
|
161
|
+
#
|
162
|
+
# @return [void]
|
163
|
+
def extremes_valid
|
164
|
+
[:begin, :end].each do |extreme_name|
|
165
|
+
extreme_value = send(extreme_name)
|
166
|
+
|
167
|
+
unless extreme_value.respond_to?(:valid?) && extreme_value.valid?
|
168
|
+
errors.add(extreme_name, :invalid)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Validates that {#begin} is `<=` {#end}.
|
174
|
+
#
|
175
|
+
# @return [void]
|
176
|
+
def order
|
177
|
+
if self.begin && self.end && self.begin > self.end
|
178
|
+
errors.add(:value, :order, begin: self.begin, end: self.end)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Adds a {#match match class method} to the extending class. The extending class must define `MATCH_REGEXP`.
|
2
|
+
#
|
3
|
+
# @example Define `match` class method
|
4
|
+
# class MetasploitDataModels::Format
|
5
|
+
# extend MetasploitDataModels::Match::Child
|
6
|
+
#
|
7
|
+
# #
|
8
|
+
# # CONSTANTS
|
9
|
+
# #
|
10
|
+
#
|
11
|
+
# # Regular expression {MetasploitDataModels::Match#match} must match against.
|
12
|
+
# MATCH_REGEXP = /\A...\z/
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# # a `MetasploitDataModels::Format` because `'123'` matches `MetasploitDataModels::Format::MATCH_REGEXP`
|
16
|
+
# instance = MetapsloitDataModels::Format.match('123')
|
17
|
+
# # `nil` because string `'12'` doesn't match `MetasploitDataModels::Format::MATCH_REGEXP`
|
18
|
+
# no_instance = MetasploitDataModels::Format.match('12')
|
19
|
+
#
|
20
|
+
module MetasploitDataModels::Match::Child
|
21
|
+
# Creates a new instance of the extending class if `MATCH_REGEXP`, defined on the extending class, matches
|
22
|
+
# `formatted_value`.
|
23
|
+
#
|
24
|
+
# @param formatted_value [#to_s]
|
25
|
+
def match(formatted_value)
|
26
|
+
instance = nil
|
27
|
+
|
28
|
+
if match_regexp.match(formatted_value)
|
29
|
+
instance = new(value: formatted_value)
|
30
|
+
end
|
31
|
+
|
32
|
+
instance
|
33
|
+
end
|
34
|
+
|
35
|
+
# Regular expression to match against for {#match}.
|
36
|
+
#
|
37
|
+
# @return [Regexp] Defaults to {#regexp} pinned with `\A` and `\z`.
|
38
|
+
def match_regexp
|
39
|
+
@match_regexp ||= /\A#{regexp}\z/
|
40
|
+
end
|
41
|
+
|
42
|
+
# Regular expression to match child as part of {MetasploitDataModels::Match::Parent}.
|
43
|
+
#
|
44
|
+
# @return [Regexp] Default to `REGEXP` from the extending `Class`.
|
45
|
+
def regexp
|
46
|
+
self::REGEXP
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# Uses classes that extend {MetasploitDataModels::Match::Child}
|
2
|
+
#
|
3
|
+
# @example Add match_child to class.
|
4
|
+
# class Parent
|
5
|
+
# include MetasploitDataModels::Match::Parent
|
6
|
+
#
|
7
|
+
# match_children_named %w{FirstChild SecondChild}
|
8
|
+
# end
|
9
|
+
module MetasploitDataModels::Match::Parent
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
# @example Declaring children classes
|
13
|
+
# class FirstChild < Metasploit::Model::Base
|
14
|
+
# extend MetasploitDataModels::Match::Child
|
15
|
+
#
|
16
|
+
# #
|
17
|
+
# # CONSTANTS
|
18
|
+
# #
|
19
|
+
#
|
20
|
+
# # Matches a range.
|
21
|
+
# MATCH_REGEXP = /\A\d+-\d+\z/
|
22
|
+
#
|
23
|
+
# #
|
24
|
+
# # Attributes
|
25
|
+
# #
|
26
|
+
#
|
27
|
+
# # @!attribute value
|
28
|
+
# # The range
|
29
|
+
# #
|
30
|
+
# attr_accessor :value
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# class SecondChild < Metasploit::Model::Base
|
34
|
+
# extend MetasploitDataModels::Match::Child
|
35
|
+
#
|
36
|
+
# #
|
37
|
+
# # CONSTANTS
|
38
|
+
# #
|
39
|
+
#
|
40
|
+
# # Matches a range.
|
41
|
+
# MATCH_REGEXP = /\A\d+\z/
|
42
|
+
#
|
43
|
+
# #
|
44
|
+
# # Attributes
|
45
|
+
# #
|
46
|
+
#
|
47
|
+
# # @!attribute value
|
48
|
+
# # The range
|
49
|
+
# #
|
50
|
+
# attr_accessor :value
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# class Parent
|
54
|
+
# include MetasploitDataModels::Match::Parent
|
55
|
+
#
|
56
|
+
# match_children_named %w{FirstChild SecondChild}
|
57
|
+
# end
|
58
|
+
module ClassMethods
|
59
|
+
# `Class#name` for classes that extend {MetasploitDataModels::Match::Child} and should be tested using `match`.
|
60
|
+
#
|
61
|
+
# @return [Array<String>]
|
62
|
+
def match_child_names
|
63
|
+
@match_child_names ||= []
|
64
|
+
end
|
65
|
+
|
66
|
+
# `Class`es on which to call `match` in {MetasploitDataModels::Match::Parent#match_child}
|
67
|
+
#
|
68
|
+
# @return [Array<String>]
|
69
|
+
def match_children
|
70
|
+
@match_children ||= match_child_names.map(&:constantize)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @note `Class`es named `class_names`
|
74
|
+
# Register the given `class_names` as `Class#name`s for children classes for
|
75
|
+
# {MetasploitDataModels::Match::Parent#match_child}.
|
76
|
+
#
|
77
|
+
# @return [Array<String>] class_names`
|
78
|
+
def match_children_named(class_names)
|
79
|
+
@match_child_names = class_names
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Instance Methods
|
85
|
+
#
|
86
|
+
|
87
|
+
# @param formatted_value [#to_s] A formatted value for the child's `#value`.
|
88
|
+
# @return [Object] instance of the first of {ClassMethods#match_children} that matches the `formatted_value`.
|
89
|
+
# @return [nil] if no {ClassMethods#match_children} matches the `formatted_value`.
|
90
|
+
def match_child(formatted_value)
|
91
|
+
child = nil
|
92
|
+
|
93
|
+
self.class.match_children.each do |child_class|
|
94
|
+
child = child_class.match(formatted_value)
|
95
|
+
|
96
|
+
if child
|
97
|
+
break
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
child
|
102
|
+
end
|
103
|
+
end
|
@@ -4,14 +4,14 @@ module MetasploitDataModels
|
|
4
4
|
# The major version number.
|
5
5
|
MAJOR = 0
|
6
6
|
# The minor version number, scoped to the {MAJOR} version number.
|
7
|
-
MINOR =
|
7
|
+
MINOR = 19
|
8
8
|
# The patch number, scoped to the {MINOR} version number.
|
9
|
-
PATCH =
|
9
|
+
PATCH = 0
|
10
10
|
|
11
|
-
# The full version string, including the {MAJOR}, {MINOR}, {PATCH}, and optionally, the
|
11
|
+
# The full version string, including the {MAJOR}, {MINOR}, {PATCH}, and optionally, the `PRERELEASE` in the
|
12
12
|
# {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0} format.
|
13
13
|
#
|
14
|
-
# @return [String] '{MAJOR}.{MINOR}.{PATCH}' on master. '{MAJOR}.{MINOR}.{PATCH}-
|
14
|
+
# @return [String] '{MAJOR}.{MINOR}.{PATCH}' on master. '{MAJOR}.{MINOR}.{PATCH}-PRERELEASE' on any branch
|
15
15
|
# other than master.
|
16
16
|
def self.full
|
17
17
|
version = "#{MAJOR}.#{MINOR}.#{PATCH}"
|
@@ -30,7 +30,8 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.add_development_dependency 'rake'
|
31
31
|
|
32
32
|
# documentation
|
33
|
-
|
33
|
+
# @note 0.8.7.4 has a bug where attribute writers show up as undocumented
|
34
|
+
s.add_development_dependency 'yard', '< 0.8.7.4'
|
34
35
|
# debugging
|
35
36
|
s.add_development_dependency 'pry'
|
36
37
|
|
@@ -83,14 +83,63 @@ describe Mdm::Cred do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
context 'methods' do
|
86
|
+
#
|
87
|
+
# lets
|
88
|
+
#
|
89
|
+
|
90
|
+
let(:host) {
|
91
|
+
FactoryGirl.create(
|
92
|
+
:mdm_host,
|
93
|
+
workspace: workspace
|
94
|
+
)
|
95
|
+
}
|
96
|
+
|
97
|
+
let(:other_service) {
|
98
|
+
FactoryGirl.create(
|
99
|
+
:mdm_service,
|
100
|
+
host: host
|
101
|
+
)
|
102
|
+
}
|
103
|
+
|
104
|
+
let(:service) {
|
105
|
+
FactoryGirl.create(
|
106
|
+
:mdm_service,
|
107
|
+
host: host
|
108
|
+
)
|
109
|
+
}
|
110
|
+
|
111
|
+
let(:ssh_key) {
|
112
|
+
FactoryGirl.create(
|
113
|
+
:mdm_cred,
|
114
|
+
pass: '/path/to/keyfile',
|
115
|
+
proof: "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a",
|
116
|
+
ptype: 'ssh_key',
|
117
|
+
service: service,
|
118
|
+
user: 'msfadmin'
|
119
|
+
)
|
120
|
+
}
|
121
|
+
|
122
|
+
let(:ssh_pubkey) {
|
123
|
+
FactoryGirl.create(
|
124
|
+
:mdm_cred,
|
125
|
+
pass: '/path/to/keyfile',
|
126
|
+
proof: "KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a",
|
127
|
+
ptype: 'ssh_pubkey',
|
128
|
+
service: service,
|
129
|
+
user: 'msfadmin'
|
130
|
+
)
|
131
|
+
}
|
132
|
+
|
133
|
+
let(:workspace) {
|
134
|
+
FactoryGirl.create(:mdm_workspace)
|
135
|
+
}
|
136
|
+
|
137
|
+
#
|
138
|
+
# Callbacks
|
139
|
+
#
|
140
|
+
|
86
141
|
before(:all) do
|
87
142
|
Mdm::Workspace.any_instance.stub(:valid_ip_or_range? => true)
|
88
|
-
workspace = FactoryGirl.create(:mdm_workspace)
|
89
|
-
host = FactoryGirl.create(:mdm_host, :workspace => workspace)
|
90
|
-
@svc1 = FactoryGirl.create(:mdm_service, :host => host)
|
91
|
-
@svc2 = FactoryGirl.create(:mdm_service, :host => host)
|
92
|
-
@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")
|
93
|
-
@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")
|
94
143
|
end
|
95
144
|
|
96
145
|
context '#ptype_human' do
|
@@ -140,79 +189,163 @@ describe Mdm::Cred do
|
|
140
189
|
|
141
190
|
context '#ssh_key_matches?' do
|
142
191
|
it 'should return true if the ssh_keys match' do
|
143
|
-
|
144
|
-
|
192
|
+
other_ssh_key = FactoryGirl.create(
|
193
|
+
:mdm_cred,
|
194
|
+
pass: '/path/to/keyfile',
|
195
|
+
proof: 'KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a',
|
196
|
+
ptype: 'ssh_key',
|
197
|
+
service: other_service,
|
198
|
+
user: 'msfadmin'
|
199
|
+
)
|
200
|
+
|
201
|
+
expect(other_ssh_key.ssh_key_matches?(ssh_key)).to eq(true)
|
145
202
|
end
|
146
203
|
|
147
204
|
it 'should return false if passed something other than a cred' do
|
148
|
-
|
205
|
+
expect(ssh_key.ssh_key_matches?(service)).to eq(false)
|
149
206
|
end
|
150
207
|
|
151
208
|
it 'should return false if the ptypes do not match' do
|
152
|
-
|
153
|
-
|
209
|
+
different_ptype = FactoryGirl.create(
|
210
|
+
:mdm_cred,
|
211
|
+
pass: '/path/to/keyfile',
|
212
|
+
proof: 'KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a',
|
213
|
+
ptype: 'ssh_pubkey',
|
214
|
+
service: other_service,
|
215
|
+
user: 'msfadmin'
|
216
|
+
)
|
217
|
+
|
218
|
+
expect(different_ptype.ssh_key_matches?(ssh_key)).to eq(false)
|
154
219
|
end
|
155
220
|
|
156
221
|
it 'should return false if the key ids do not match' do
|
157
|
-
|
158
|
-
|
222
|
+
different_proof = FactoryGirl.create(
|
223
|
+
:mdm_cred,
|
224
|
+
pass: '/path/to/keyfile',
|
225
|
+
proof: 'KEY=66:d4:22:6e:88:d6:74:A1:44:3e:d6:d5:AA:89:73:8b',
|
226
|
+
ptype: 'ssh_pubkey',
|
227
|
+
service: other_service,
|
228
|
+
user: 'msfadmin'
|
229
|
+
)
|
230
|
+
|
231
|
+
expect(different_proof.ssh_key_matches?(ssh_key)).to eq(false)
|
159
232
|
end
|
160
233
|
|
161
234
|
it 'should behave the same for public keys as private keys' do
|
162
|
-
pubkey2 = FactoryGirl.create(:mdm_cred, :service =>
|
163
|
-
pubkey3 = FactoryGirl.create(:mdm_cred, :service =>
|
164
|
-
pubkey2.ssh_key_matches?(
|
235
|
+
pubkey2 = FactoryGirl.create(:mdm_cred, :service => service, :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")
|
236
|
+
pubkey3 = FactoryGirl.create(:mdm_cred, :service => service, :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")
|
237
|
+
pubkey2.ssh_key_matches?(ssh_pubkey).should == true
|
165
238
|
pubkey2.ssh_key_matches?(pubkey3).should == false
|
166
239
|
end
|
167
240
|
|
168
241
|
it 'should always return false for non ssh key creds' do
|
169
|
-
cred2 = FactoryGirl.create(:mdm_cred, :service =>
|
170
|
-
cred3 = FactoryGirl.create(:mdm_cred, :service =>
|
242
|
+
cred2 = FactoryGirl.create(:mdm_cred, :service => other_service, :ptype => 'password', :user => 'msfadmin', :pass => 'msfadmin' )
|
243
|
+
cred3 = FactoryGirl.create(:mdm_cred, :service => other_service, :ptype => 'password', :user => 'msfadmin', :pass => 'msfadmin' )
|
171
244
|
cred2.ssh_key_matches?(cred3).should == false
|
172
245
|
end
|
173
246
|
end
|
174
247
|
|
175
248
|
context '#ssh_keys' do
|
176
|
-
|
177
|
-
|
249
|
+
#
|
250
|
+
# lets
|
251
|
+
#
|
252
|
+
|
253
|
+
let(:other_ssh_key) {
|
254
|
+
FactoryGirl.create(
|
255
|
+
:mdm_cred,
|
256
|
+
pass: '/path/to/keyfile',
|
257
|
+
proof: 'KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a',
|
258
|
+
ptype: 'ssh_key',
|
259
|
+
service: other_service,
|
260
|
+
user: 'msfadmin'
|
261
|
+
)
|
262
|
+
}
|
263
|
+
|
264
|
+
#
|
265
|
+
# Callbacks
|
266
|
+
#
|
267
|
+
|
268
|
+
before(:each) do
|
269
|
+
ssh_key
|
270
|
+
ssh_pubkey
|
178
271
|
end
|
272
|
+
|
179
273
|
it 'should return all ssh private keys with a matching id' do
|
180
|
-
|
274
|
+
other_ssh_key.ssh_keys.should include(ssh_key)
|
181
275
|
end
|
182
276
|
|
183
277
|
it 'should return all ssh public keys with a matching id' do
|
184
|
-
|
278
|
+
other_ssh_key.ssh_keys.should include(ssh_pubkey)
|
185
279
|
end
|
186
280
|
end
|
187
281
|
|
188
282
|
context '#ssh_private_keys' do
|
189
|
-
|
190
|
-
|
283
|
+
#
|
284
|
+
# lets
|
285
|
+
#
|
286
|
+
|
287
|
+
let(:other_ssh_key) {
|
288
|
+
FactoryGirl.create(
|
289
|
+
:mdm_cred,
|
290
|
+
pass: '/path/to/keyfile',
|
291
|
+
proof: 'KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a',
|
292
|
+
ptype: 'ssh_key',
|
293
|
+
service: other_service,
|
294
|
+
user: 'msfadmin',
|
295
|
+
)
|
296
|
+
}
|
297
|
+
|
298
|
+
#
|
299
|
+
# Callbacks
|
300
|
+
#
|
301
|
+
|
302
|
+
before(:each) do
|
303
|
+
ssh_key
|
304
|
+
ssh_pubkey
|
191
305
|
end
|
192
306
|
|
193
307
|
it 'should return ssh private keys with matching ids' do
|
194
|
-
|
308
|
+
other_ssh_key.ssh_private_keys.should include(ssh_key)
|
195
309
|
end
|
196
310
|
|
197
311
|
it 'should not return ssh public keys with matching ids' do
|
198
|
-
|
312
|
+
other_ssh_key.ssh_private_keys.should_not include(ssh_pubkey)
|
199
313
|
end
|
200
314
|
end
|
201
315
|
|
202
316
|
context '#ssh_public_keys' do
|
203
|
-
|
204
|
-
|
317
|
+
#
|
318
|
+
# lets
|
319
|
+
#
|
320
|
+
|
321
|
+
let(:other_ssh_key) {
|
322
|
+
FactoryGirl.create(
|
323
|
+
:mdm_cred,
|
324
|
+
pass: '/path/to/keyfile',
|
325
|
+
proof: 'KEY=57:c3:11:5d:77:c5:63:90:33:2d:c5:c4:99:78:62:7a',
|
326
|
+
ptype: 'ssh_key',
|
327
|
+
service: other_service,
|
328
|
+
user: 'msfadmin'
|
329
|
+
)
|
330
|
+
}
|
331
|
+
|
332
|
+
#
|
333
|
+
# Callbacks
|
334
|
+
#
|
335
|
+
|
336
|
+
before(:each) do
|
337
|
+
ssh_key
|
338
|
+
ssh_pubkey
|
205
339
|
end
|
206
340
|
|
207
341
|
it 'should not return ssh private keys with matching ids' do
|
208
|
-
|
342
|
+
other_ssh_key.ssh_public_keys.should_not include(ssh_key)
|
209
343
|
end
|
210
344
|
|
211
345
|
it 'should return ssh public keys with matching ids' do
|
212
|
-
|
346
|
+
other_ssh_key.ssh_public_keys.should include(ssh_pubkey)
|
213
347
|
end
|
214
348
|
end
|
215
|
-
|
216
349
|
end
|
217
350
|
|
218
351
|
context 'factory' do
|