nexpose 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -134,6 +134,19 @@ module Nexpose
134
134
  # Valid Operators: CONTAINS, NOT_CONTAINS
135
135
  SOFTWARE = 'SOFTWARE'
136
136
 
137
+ # Valid Operators: IS, IS_NOT, GREATER_THAN, LESS_THAN, IS_APPLIED, IS_NOT_APPLIED
138
+ # Valid Values: VERY_HIGH, HIGH, NORMAL, LOW, VERY_LOW
139
+ USER_ADDED_CRITICALITY_LEVEL = 'TAG_CRITICALITY'
140
+
141
+ # Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED, IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
142
+ USER_ADDED_CUSTOM_TAG = 'TAG'
143
+
144
+ # Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED, IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
145
+ USER_ADDED_TAG_LOCATION = 'TAG_LOCATION'
146
+
147
+ # Valid Operators: IS, IS_NOT, STARTS_WITH, ENDS_WITH, IS_APPLIED, IS_NOT_APPLIED, CONTAINS, NOT_CONTAINS
148
+ USER_ADDED_TAG_OWNER = 'TAG_OWNER'
149
+
137
150
  # Valid Operators: ARE
138
151
  # Valid Values: PRESENT, NOT_PRESENT
139
152
  VALIDATED_VULNERABILITIES = 'VULNERABILITY_VALIDATED_STATUS'
@@ -171,6 +184,8 @@ module Nexpose
171
184
  IS_NOT_EMPTY = 'IS_NOT_EMPTY'
172
185
  INCLUDE = 'INCLUDE'
173
186
  DO_NOT_INCLUDE = 'DO_NOT_INCLUDE'
187
+ IS_APPLIED = 'IS_APPLIED'
188
+ IS_NOT_APPLIED = 'IS_NOT_APPLIED'
174
189
  end
175
190
 
176
191
  # Specialized values used by certain search fields
@@ -263,7 +278,7 @@ module Nexpose
263
278
  def to_map
264
279
  { 'metadata' => { 'fieldName' => field },
265
280
  'operator' => operator,
266
- 'values' => value.kind_of?(Array) ? value : [value] }
281
+ 'values' => Array(value) }
267
282
  end
268
283
 
269
284
  def self.parse(json)
@@ -283,11 +298,7 @@ module Nexpose
283
298
  attr_accessor :criteria
284
299
 
285
300
  def initialize(criteria = [], match = 'AND')
286
- if criteria.kind_of?(Array)
287
- @criteria = criteria
288
- else
289
- @criteria = [criteria]
290
- end
301
+ @criteria = Array(criteria)
291
302
  @match = match.upcase
292
303
  end
293
304
 
data/lib/nexpose/group.rb CHANGED
@@ -28,9 +28,10 @@ module Nexpose
28
28
  if r.success
29
29
  r.res.elements.each('AssetGroupListingResponse/AssetGroupSummary') do |group|
30
30
  groups << AssetGroupSummary.new(group.attributes['id'].to_i,
31
- group.attributes['name'],
32
- group.attributes['description'],
33
- group.attributes['riskscore'].to_f)
31
+ group.attributes['name'],
32
+ group.attributes['description'],
33
+ group.attributes['riskscore'].to_f,
34
+ group.attributes['dynamic'].to_i == 1)
34
35
  end
35
36
  end
36
37
  groups
@@ -43,10 +44,14 @@ module Nexpose
43
44
  # Summary value object for asset group information.
44
45
  #
45
46
  class AssetGroupSummary
46
- attr_reader :id, :name, :description, :risk_score
47
+ attr_reader :id, :name, :description, :risk_score, :dynamic
47
48
 
48
- def initialize(id, name, desc, risk)
49
- @id, @name, @description, @risk_score = id, name, desc, risk
49
+ def initialize(id, name, desc, risk, dynamic)
50
+ @id, @name, @description, @risk_score, @dyanmic = id, name, desc, risk, dynamic
51
+ end
52
+
53
+ def dynamic?
54
+ dynamic
50
55
  end
51
56
 
52
57
  # Delete this asset group and all associated data.
@@ -63,7 +68,7 @@ module Nexpose
63
68
  class AssetGroup < AssetGroupSummary
64
69
  include Sanitize
65
70
 
66
- attr_accessor :name, :description, :id
71
+ attr_accessor :name, :description, :id , :tags
67
72
 
68
73
  # Array[Device] of devices associated with this asset group.
69
74
  attr_accessor :assets
@@ -73,6 +78,7 @@ module Nexpose
73
78
  def initialize(name, desc, id = -1, risk = 0.0)
74
79
  @name, @description, @id, @risk_score = name, desc, id, risk
75
80
  @assets = []
81
+ @tags = []
76
82
  end
77
83
 
78
84
  def save(connection)
@@ -98,6 +104,11 @@ module Nexpose
98
104
  xml << %(<device id="#{asset.id}"/>)
99
105
  end
100
106
  xml << '</Devices>'
107
+ xml << '<Tags>'
108
+ @tags.each do |tag|
109
+ xml << tag.as_xml.to_s
110
+ end
111
+ xml << '</Tags>'
101
112
  xml << '</AssetGroup>'
102
113
  end
103
114
 
@@ -133,7 +144,6 @@ module Nexpose
133
144
 
134
145
  def self.parse(xml)
135
146
  return nil unless xml
136
-
137
147
  group = REXML::XPath.first(xml, 'AssetGroupConfigResponse/AssetGroup')
138
148
  asset_group = new(group.attributes['name'],
139
149
  group.attributes['description'],
@@ -146,6 +156,9 @@ module Nexpose
146
156
  dev.attributes['riskfactor'].to_f,
147
157
  dev.attributes['riskscore'].to_f)
148
158
  end
159
+ group.elements.each('Tags/Tag') do |tag|
160
+ asset_group.tags << TagSummary.parse_xml(tag)
161
+ end
149
162
  asset_group
150
163
  end
151
164
  end
@@ -0,0 +1,219 @@
1
+ module Nexpose
2
+
3
+ class Connection
4
+ include XMLUtils
5
+
6
+ # Retrieve a list of all users the user is authorized to view or manage.
7
+ #
8
+ # @return [Array[MultiTenantUserSummary]] Array of MultiTenantUserSummary objects.
9
+ #
10
+ def list_silo_users
11
+ r = execute(make_xml('MultiTenantUserListingRequest'), '1.2')
12
+ arr = []
13
+ if r.success
14
+ r.res.elements.each('MultiTenantUserListingResponse/MultiTenantUserSummaries/MultiTenantUserSummary') do |user|
15
+ arr << MultiTenantUserSummary.parse(user)
16
+ end
17
+ end
18
+ arr
19
+ end
20
+
21
+ # Delete the specified silo user
22
+ #
23
+ # @return Whether or not the delete request succeeded.
24
+ #
25
+ def delete_silo_user(user_id)
26
+ r = execute(make_xml('MultiTenantUserDeleteRequest', {'user-id' => user_id}), '1.2')
27
+ r.success
28
+ end
29
+ end
30
+
31
+ class MultiTenantUserSummary
32
+ attr_reader :id
33
+ attr_reader :full_name
34
+ attr_reader :user_name
35
+ attr_reader :email
36
+ attr_reader :superuser
37
+ attr_reader :enabled
38
+ attr_reader :auth_module
39
+ attr_reader :auth_source
40
+ attr_reader :silo_count
41
+ attr_reader :locked
42
+
43
+ def initialize(&block)
44
+ instance_eval &block if block_given?
45
+ end
46
+
47
+ def self.parse(xml)
48
+ new do
49
+ @id = xml.attributes['id'].to_i
50
+ @full_name = xml.attributes['full-name']
51
+ @user_name = xml.attributes['user-name']
52
+ @email = xml.attributes['email']
53
+ @superuser = xml.attributes['superuser'].to_s.chomp.eql?('true')
54
+ @enabled = xml.attributes['enabled'].to_s.chomp.eql?('true')
55
+ @auth_module = xml.attributes['auth-module']
56
+ @auth_source = xml.attributes['auth-source']
57
+ @silo_count = xml.attributes['silo-count'].to_i
58
+ @locked = xml.attributes['locked'].to_s.chomp.eql?('true')
59
+ end
60
+ end
61
+ end
62
+
63
+ class MultiTenantUser
64
+ attr_accessor :id
65
+ attr_accessor :full_name
66
+ attr_accessor :user_name
67
+ attr_accessor :auth_source_id
68
+ attr_accessor :email
69
+ attr_accessor :password
70
+ attr_accessor :superuser
71
+ attr_accessor :enabled
72
+ attr_accessor :silo_access
73
+
74
+ def initialize(&block)
75
+ instance_eval &block if block_given?
76
+
77
+ @silo_access = Array(@silo_access)
78
+ end
79
+
80
+ def save(connection)
81
+ if (@id)
82
+ update(connection)
83
+ else
84
+ create(connection)
85
+ end
86
+ end
87
+
88
+ # Updates this silo user on a Nexpose console.
89
+ #
90
+ # @param [Connection] connection Connection to console where this silo user will be saved.
91
+ # @return [String] User ID assigned to this configuration, if successful.
92
+ #
93
+ def update(connection)
94
+ xml = connection.make_xml('MultiTenantUserUpdateRequest')
95
+ xml.add_element(as_xml)
96
+ r = connection.execute(xml, '1.2')
97
+ @id = r.attributes['user-id'] if r.success
98
+ end
99
+
100
+ # Saves this silo user to a Nexpose console.
101
+ #
102
+ # @param [Connection] connection Connection to console where this silo user will be saved.
103
+ # @return [String] User ID assigned to this configuration, if successful.
104
+ #
105
+ def create(connection)
106
+ xml = connection.make_xml('MultiTenantUserCreateRequest')
107
+ xml.add_element(as_xml)
108
+ r = connection.execute(xml, '1.2')
109
+ @id = r.attributes['user-id'] if r.success
110
+ end
111
+
112
+ def as_xml
113
+ xml = REXML::Element.new('MultiTenantUserConfig')
114
+ xml.add_attributes({'id' => @id,
115
+ 'full-name' => @full_name,
116
+ 'user-name' => @user_name,
117
+ 'authsrcid' => @auth_source_id,
118
+ 'email' => @email,
119
+ 'password' => @password,
120
+ 'superuser' => @superuser,
121
+ 'enabled' => @enabled})
122
+ siloaccesses = xml.add_element('SiloAccesses')
123
+ @silo_access.each { |silo_access| siloaccesses.add_element(silo_access.as_xml) }
124
+ xml
125
+ end
126
+
127
+ def delete(connection)
128
+ connection.delete_silo_user(@id)
129
+ end
130
+
131
+ def to_xml
132
+ as_xml.to_s
133
+ end
134
+
135
+ def self.parse(xml)
136
+ new do |user|
137
+ user.id = xml.attributes['id'].to_i
138
+ user.full_name = xml.attributes['full-name']
139
+ user.user_name = xml.attributes['user-name']
140
+ user.email = xml.attributes['email']
141
+ user.superuser = xml.attributes['superuser'].to_s.chomp.eql?('true')
142
+ user.enabled = xml.attributes['enabled'].to_s.chomp.eql?('true')
143
+ user.auth_source_id = xml.attributes['authsrcid'].to_i
144
+ user.silo_access = []
145
+ xml.elements.each('SiloAccesses/SiloAccess') { |access| user.silo_access << SiloAccess.parse(access) }
146
+ end
147
+ end
148
+
149
+ def self.load(connection, user_id)
150
+ r = connection.execute(connection.make_xml('MultiTenantUserConfigRequest', {'user-id' => user_id}), '1.2')
151
+
152
+ if r.success
153
+ r.res.elements.each('MultiTenantUserConfigResponse/MultiTenantUserConfig') do |config|
154
+ return MultiTenantUser.parse(config)
155
+ end
156
+ end
157
+ nil
158
+ end
159
+ end
160
+
161
+ class SiloAccess
162
+ attr_accessor :all_groups
163
+ attr_accessor :all_sites
164
+ attr_accessor :role_name
165
+ attr_accessor :silo_id
166
+ attr_accessor :default
167
+ attr_accessor :sites
168
+ attr_accessor :groups
169
+
170
+ def initialize(&block)
171
+ instance_eval &block if block_given?
172
+ @sites = Array(@sites)
173
+ @groups = Array(@groups)
174
+ end
175
+
176
+ def as_xml
177
+ xml = REXML::Element.new('SiloAccess')
178
+ xml.add_attributes({'all-groups' => @all_groups,
179
+ 'all-sites' => @all_sites,
180
+ 'role-name' => @role_name,
181
+ 'silo-id' => @silo_id,
182
+ 'default-silo' => @default})
183
+
184
+ unless @groups.empty?
185
+ groups = xml.add_element('AllowedGroups')
186
+ @groups.each do |group|
187
+ groups.add_element('AllowedGroup', {'id' => group})
188
+ end
189
+ end
190
+
191
+ unless @sites.empty?
192
+ sites = xml.add_element('AllowedSites')
193
+ @sites.each do |site|
194
+ sites.add_element('AllowedSite', {'id' => site})
195
+ end
196
+ end
197
+
198
+ xml
199
+ end
200
+
201
+ def to_xml
202
+ as_xml.to_s
203
+ end
204
+
205
+ def self.parse(xml)
206
+ new do |access|
207
+ access.all_groups = xml.attributes['all-groups'].to_s.chomp.eql?('true')
208
+ access.all_sites = xml.attributes['all-sites'].to_s.chomp.eql?('true')
209
+ access.role_name = xml.attributes['role-name']
210
+ access.silo_id = xml.attributes['silo-id']
211
+ access.default = xml.attributes['default-silo'].to_s.chomp.eql?('true')
212
+ access.sites = []
213
+ xml.elements.each('AllowedSites/AllowedSite') { |site| access.sites << site.attributes['id'].to_i }
214
+ access.groups = []
215
+ xml.elements.each('AllowedGroups/AllowedGroup') { |group| access.groups << group.attributes['id'].to_i }
216
+ end
217
+ end
218
+ end
219
+ end
@@ -27,7 +27,7 @@ module Nexpose
27
27
  # @param [String] template_id Unique identifier of the report template to remove.
28
28
  #
29
29
  def delete_report_template(template_id)
30
- AJAX.delete(self, "/data/report/templates/#{template_id}")
30
+ AJAX.delete(self, "/data/report/templates/#{URI.escape(template_id)}")
31
31
  end
32
32
  end
33
33
 
data/lib/nexpose/scan.rb CHANGED
@@ -208,6 +208,17 @@ module Nexpose
208
208
  false
209
209
  end
210
210
  end
211
+
212
+ # Delete a scan and all its data from a console.
213
+ # Warning, this method is destructive and not guaranteed to leave a site
214
+ # in a valid state. DBCC may need to be run to correct missing or empty
215
+ # assets.
216
+ #
217
+ # @param [Fixnum] scan_id Scan ID to remove data for.
218
+ #
219
+ def delete_scan(scan_id)
220
+ AJAX.delete(self, "/data/scan/#{scan_id}")
221
+ end
211
222
  end
212
223
 
213
224
  # Object that represents a summary of a scan.
data/lib/nexpose/silo.rb CHANGED
@@ -3,347 +3,351 @@ module Nexpose
3
3
  class Connection
4
4
  include XMLUtils
5
5
 
6
- ###################
7
- # SILO MANAGEMENT #
8
- ###################
9
-
10
- #########################
11
- # MULTI-TENANT USER OPS #
12
- #########################
13
-
14
- #-------------------------------------------------------------------------
15
- # Creates a multi-tenant user
6
+ # Retrieve a list of all silos the user is authorized to view or manage.
16
7
  #
17
- # user_config - A map of the user data.
8
+ # @return [Array[SiloSummary]] Array of SiloSummary objects.
18
9
  #
19
- # REQUIRED PARAMS
20
- # user-id, authsrcid, user-name, full-name, enabled, superuser
10
+ def list_silos
11
+ r = execute(make_xml('SiloListingRequest'), '1.2')
12
+ arr = []
13
+ if r.success
14
+ r.res.elements.each('SiloListingResponse/SiloSummaries/SiloSummary') do |silo|
15
+ arr << SiloSummary.parse(silo)
16
+ end
17
+ end
18
+ arr
19
+ end
20
+
21
+ alias_method :silos, :list_silos
22
+
23
+ # Delete the specified silo
21
24
  #
22
- # OPTIONAL PARAMS
23
- # email, password
25
+ # @return Whether or not the delete request succeeded.
24
26
  #
25
- # silo_configs - An array of maps of silo specific data
27
+ def delete_silo(silo_id)
28
+ r = execute(make_xml('SiloDeleteRequest', {'silo-id' => silo_id}), '1.2')
29
+ r.success
30
+ end
31
+ end
32
+
33
+ class Silo
34
+ # Required fields
35
+ attr_accessor :id
36
+ attr_accessor :profile_id
37
+ attr_accessor :name
38
+ attr_accessor :max_assets
39
+ attr_accessor :max_users
40
+ attr_accessor :max_hosted_assets
41
+
42
+ #Optional fields
43
+ attr_accessor :description
44
+ attr_accessor :merchant
45
+ attr_accessor :organization
46
+
47
+ def initialize(&block)
48
+ instance_eval &block if block_given?
49
+ end
50
+
51
+ # Copy an existing configuration from a Nexpose instance.
52
+ # Returned object will reset the silo ID and name
26
53
  #
27
- # REQUIRED PARAMS
28
- # silo-id, role-name, all-groups, all-sites, default-silo
54
+ # @param [Connection] connection Connection to the security console.
55
+ # @param [String] id Silo ID of an existing silo.
56
+ # @return [Silo] Silo configuration loaded from a Nexpose console.
29
57
  #
30
- # allowed_groups/allowed_sites - An array of ids
31
- #-------------------------------------------------------------------------
32
- def create_multi_tenant_user(user_config, silo_configs)
33
- xml = make_xml('MultiTenantUserCreateRequest')
34
- mtu_config_xml = make_xml('MultiTenantUserConfig', user_config, '', false)
35
-
36
- # Add the silo access
37
- silo_xml = make_xml('SiloAccesses', {}, '', false)
38
- silo_configs.each do |silo_config|
39
- silo_config_xml = make_xml('SiloAccess', {}, '', false)
40
- silo_config.keys.each do |k|
41
- if k == 'allowed_sites'
42
- allowed_sites_xml = make_xml('AllowedSites', {}, '', false)
43
- silo_config['allowed_sites'].each do |allowed_site|
44
- allowed_sites_xml.add_element(make_xml('AllowedSite', {'id' => allowed_site}, '', false))
45
- end
46
- silo_config_xml.add_element(allowed_sites_xml)
47
- elsif k == 'allowed_groups'
48
- allowed_groups_xml = make_xml('AllowedGroups', {}, '', false)
49
- silo_config['allowed_groups'].each do |allowed_group|
50
- allowed_groups_xml.add_element(make_xml('AllowedGroup', {'id' => allowed_group}, '', false))
51
- end
52
- silo_config_xml.add_element(allowed_groups_xml)
53
- else
54
- silo_config_xml.attributes[k] = silo_config[k]
55
- end
56
- end
57
- silo_xml.add_element(silo_config_xml)
58
- end
59
- mtu_config_xml.add_element(silo_xml)
60
- xml.add_element(mtu_config_xml)
61
- r = execute(xml, '1.2')
62
- r.success
58
+ def self.copy(connection, id)
59
+ silo = load(connection, id)
60
+ silo.id = nil
61
+ silo.name = nil
62
+ silo
63
63
  end
64
64
 
65
- #-------------------------------------------------------------------------
66
- # Lists all the multi-tenant users and their attributes.
67
- #-------------------------------------------------------------------------
68
- def list_mtu
69
- xml = make_xml('MultiTenantUserListingRequest')
70
- r = execute xml, '1.2'
65
+ # Load an existing configuration from a Nexpose instance.
66
+ #
67
+ # @param [Connection] connection Connection to console where site exists.
68
+ # @param [String] id Silo ID of an existing silo.
69
+ # @return [Silo] Silo configuration loaded from a Nexpose console.
70
+ #
71
+ def self.load(connection, id)
72
+ r = connection.execute(connection.make_xml('SiloConfigRequest', {'silo-id' => id}), '1.2')
71
73
 
72
74
  if r.success
73
- res = []
74
- r.res.elements.each("//MultiTenantUserSummary") do |mtu|
75
- res << {
76
- :id => mtu.attributes['id'],
77
- :full_name => mtu.attributes['full-name'],
78
- :user_name => mtu.attributes['user-name'],
79
- :email => mtu.attributes['email'],
80
- :super_user => mtu.attributes['superuser'],
81
- :enabled => mtu.attributes['enabled'],
82
- :auth_module => mtu.attributes['auth-module'],
83
- :silo_count => mtu.attributes['silo-count'],
84
- :locked => mtu.attributes['locked']
85
- }
75
+ r.res.elements.each('SiloConfigResponse/SiloConfig') do |config|
76
+ return Silo.parse(config)
86
77
  end
87
- res
88
- else
89
- false
90
78
  end
79
+ nil
91
80
  end
92
81
 
93
- #-------------------------------------------------------------------------
94
- # Delete a multi-tenant user
95
- #-------------------------------------------------------------------------
96
- def delete_mtu user_name, user_id
97
- using_user_name = (user_name and not user_name.empty?)
98
- xml = make_xml('MultiTenantUserDeleteRequest', (using_user_name ? {'user-name' => user_name} : {'user-id' => user_id}))
99
- r = execute xml, '1.2'
100
- r.success
82
+ def save(connection)
83
+ begin
84
+ update(connection)
85
+ rescue APIError => error
86
+ raise error unless (error.message =~ /A silo .* does not exist./)
87
+ create(connection)
88
+ end
101
89
  end
102
90
 
103
- ####################
104
- # SILO PROFILE OPS #
105
- ####################
106
-
107
- #-------------------------------------------------------------------------
108
- # Creates a silo profile
91
+ # Updates this silo on a Nexpose console.
109
92
  #
110
- # silo_config - A map of the silo data.
93
+ # @param [Connection] connection Connection to console where this silo will be saved.
94
+ # @return [String] Silo ID assigned to this configuration, if successful.
111
95
  #
112
- # REQUIRED PARAMS
113
- # id, name, all‐licensed-modules, all‐global-engines, all-global-report-templates, all‐global-scan‐templates
114
- #
115
- # OPTIONAL PARAMS
116
- # description
117
- #
118
- # permissions - A map of an array of maps of silo specific data
96
+ def update(connection)
97
+ xml = connection.make_xml('SiloUpdateRequest')
98
+ xml.add_element(as_xml)
99
+ r = connection.execute(xml, '1.2')
100
+ @id = r.attributes['id'] if r.success
101
+ end
102
+
103
+ # Saves a new silo to a Nexpose console.
119
104
  #
120
- # REQUIRED PARAMS
121
- # silo-id, role-name, all-groups, all-sites, default-silo
105
+ # @param [Connection] connection Connection to console where this silo will be saved.
106
+ # @return [String] Silo ID assigned to this configuration, if successful.
122
107
  #
123
- # allowed_groups/allowed_sites - An array of ids
124
- #-------------------------------------------------------------------------
125
- def create_silo_profile silo_profile_config, permissions
126
- xml = make_xml 'SiloProfileCreateRequest'
127
- spc_xml = make_xml('SiloProfileConfig', silo_profile_config, '', false)
128
-
129
- # Add the permissions
130
- if permissions['global_report_templates']
131
- grt_xml = make_xml('GlobalReportTemplates', {}, '', false)
132
- permissions['global_report_templates'].each do |name|
133
- grt_xml.add_element make_xml('GlobalReportTemplate', {'name' => name}, '', false)
134
- end
135
- spc_xml.add_element grt_xml
136
- end
108
+ def create(connection)
109
+ xml = connection.make_xml('SiloCreateRequest')
110
+ xml.add_element(as_xml)
111
+ r = connection.execute(xml, '1.2')
112
+ @id = r.attributes['id'] if r.success
113
+ end
137
114
 
138
- if permissions['global_scan_engines']
139
- gse_xml = make_xml('GlobalScanEngines', {}, '', false)
140
- permissions['global_scan_engines'].each do |name|
141
- gse_xml.add_element make_xml('GlobalScanEngine', {'name' => name}, '', false)
142
- end
143
- spc_xml.add_element gse_xml
144
- end
115
+ def delete(connection)
116
+ connection.delete_silo(@id)
117
+ end
145
118
 
146
- if permissions['global_scan_templates']
147
- gst_xml = make_xml('GlobalScanTemplates', {}, '', false)
148
- permissions['global_scan_templates'].each do |name|
149
- gst_xml.add_element make_xml('GlobalScanTemplate', {'name' => name}, '', false)
150
- end
151
- spc_xml.add_element gst_xml
152
- end
119
+ def as_xml
120
+ xml = REXML::Element.new('SiloConfig')
121
+ xml.add_attributes({'description' => @description, 'name' => @name, 'id' => @id, 'silo-profile-id' => @profile_id, 'max-assets' => @max_assets, 'max-users' => @max_users, 'max-hosted-assets' => @max_hosted_assets})
122
+ xml.add(@merchant.as_xml) if @merchant
123
+ xml.add(@organization.as_xml) if @organization
124
+ xml
125
+ end
153
126
 
154
- if permissions['licensed_modules']
155
- lm_xml = make_xml('LicensedModules', {}, '', false)
156
- permissions['licensed_modules'].each do |name|
157
- lm_xml.add_element make_xml('LicensedModule', {'name' => name}, '', false)
158
- end
159
- spc_xml.add_element lm_xml
160
- end
127
+ def to_xml
128
+ as_xml.to_s
129
+ end
161
130
 
162
- if permissions['restricted_report_formats']
163
- rrf_xml = make_xml('RestrictedReportFormats', {}, '', false)
164
- permissions['restricted_report_formats'].each do |name|
165
- rrf_xml.add_element make_xml('RestrictedReportFormat', {'name' => name}, '', false)
131
+ def self.parse(xml)
132
+ new do |silo|
133
+ silo.id = xml.attributes['id']
134
+ silo.profile_id = xml.attributes['silo-profile-id']
135
+ silo.name = xml.attributes['name']
136
+ silo.max_assets = xml.attributes['max-assets'].to_i
137
+ silo.max_users = xml.attributes['max-users'].to_i
138
+ silo.max_hosted_assets = xml.attributes['max-hosted-assets'].to_i
139
+ silo.description = xml.attributes['description']
140
+
141
+ xml.elements.each('Merchant') do |merchant|
142
+ silo.merchant = Merchant.parse(merchant)
166
143
  end
167
- spc_xml.add_element rrf_xml
168
- end
169
144
 
170
- if permissions['restricted_report_sections']
171
- rrs_xml = make_xml('RestrictedReportSections', {}, '', false)
172
- permissions['restricted_report_sections'].each do |name|
173
- rrs_xml.add_element make_xml('RestrictedReportSection', {'name' => name}, '', false)
145
+ xml.elements.each('Organization') do |organization|
146
+ silo.organization = Organization.parse(organization)
174
147
  end
175
- spc_xml.add_element rrs_xml
176
148
  end
177
-
178
- xml.add_element spc_xml
179
- r = execute xml, '1.2'
180
- r.success
181
149
  end
182
150
 
183
- #-------------------------------------------------------------------------
184
- # Lists all the silo profiles and their attributes.
185
- #-------------------------------------------------------------------------
186
- def list_silo_profiles
187
- xml = make_xml('SiloProfileListingRequest')
188
- r = execute xml, '1.2'
151
+ class Address
152
+ attr_accessor :line1
153
+ attr_accessor :line2
154
+ attr_accessor :city
155
+ attr_accessor :state
156
+ attr_accessor :zip
157
+ attr_accessor :country
189
158
 
190
- if r.success
191
- res = []
192
- r.res.elements.each("//SiloProfileSummary") do |silo_profile|
193
- res << {
194
- :id => silo_profile.attributes['id'],
195
- :name => silo_profile.attributes['name'],
196
- :description => silo_profile.attributes['description'],
197
- :global_report_template_count => silo_profile.attributes['global-report-template-count'],
198
- :global_scan_engine_count => silo_profile.attributes['global-scan-engine-count'],
199
- :global_scan_template_count => silo_profile.attributes['global-scan-template-count'],
200
- :licensed_module_count => silo_profile.attributes['licensed-module-count'],
201
- :restricted_report_section_count => silo_profile.attributes['restricted-report-section-count'],
202
- :all_licensed_modules => silo_profile.attributes['all-licensed-modules'],
203
- :all_global_engines => silo_profile.attributes['all-global-engines'],
204
- :all_global_report_templates => silo_profile.attributes['all-global-report-templates'],
205
- :all_global_scan_templates => silo_profile.attributes['all-global-scan-templates']
206
- }
159
+
160
+ def initialize(&block)
161
+ instance_eval &block if block_given?
162
+ end
163
+
164
+ def self.parse(xml)
165
+ new do |address|
166
+ address.line1 = xml.attributes['line1']
167
+ address.line2 = xml.attributes['line2']
168
+ address.city = xml.attributes['city']
169
+ address.state = xml.attributes['state']
170
+ address.zip = xml.attributes['zip']
171
+ address.country = xml.attributes['country']
207
172
  end
208
- res
209
- else
210
- false
211
173
  end
212
- end
213
174
 
214
- #-------------------------------------------------------------------------
215
- # Delete a silo profile
216
- #-------------------------------------------------------------------------
217
- def delete_silo_profile name, id
218
- using_name = (name and not name.empty?)
219
- xml = make_xml('SiloProfileDeleteRequest', (using_name ? {'name' => name} : {'silo-profile-id' => id}))
220
- r = execute xml, '1.2'
221
- r.success
175
+ def as_xml
176
+ xml = REXML::Element.new('Address')
177
+ xml.add_attributes({'city' => @city, 'country' => @country, 'line1' => @line1, 'line2' => @line2, 'state' => @state, 'zip' => @zip})
178
+ xml
179
+ end
222
180
  end
223
181
 
224
- ####################
225
- # SILO OPS #
226
- ####################
182
+ class Organization
183
+ attr_accessor :company
184
+ attr_accessor :first_name
185
+ attr_accessor :last_name
186
+ attr_accessor :phone
187
+ attr_accessor :address
188
+ attr_accessor :email
189
+ attr_accessor :title
190
+ attr_accessor :url
191
+
192
+ def initialize(&block)
193
+ instance_eval &block if block_given?
194
+ end
227
195
 
228
- #-------------------------------------------------------------------------
229
- # Creates a silo
230
- #
231
- # silo_config - A map of the silo creation data.
232
- #
233
- # REQUIRED PARAMS
234
- # id, name, silo-profile-id, max-assets, max-hosted-assets, max-users
235
- #
236
- # OPTIONAL PARAMS
237
- # description
238
- #-------------------------------------------------------------------------
239
- def create_silo silo_config
240
- xml = make_xml 'SiloCreateRequest'
241
- silo_config_xml = make_xml 'SiloConfig', {}, '', false
242
-
243
- # Add the attributes
244
- silo_config.keys.each do |key|
245
- if not 'merchant'.eql? key and not 'organization'.eql? key
246
- silo_config_xml.attributes[key] = silo_config[key]
247
- end
196
+ def as_xml
197
+ xml = REXML::Element.new('Organization')
198
+ xml.add_attributes({'company' => @company, 'email-address' => @email, 'first-name' => @first_name, 'last-name' => @last_name, 'phone-number' => @phone, 'title' => @title, 'url' => @url})
199
+ xml.add(@address.as_xml)
200
+ xml
248
201
  end
249
202
 
250
- # Add Organization info
251
- if silo_config['organization']
252
- org_xml = make_xml 'Organization', {}, '', false
253
- silo_config['organization'].keys.each do |key|
254
- if not 'address'.eql? key
255
- org_xml.attributes[key] = silo_config['organization'][key]
203
+ def self.parse(xml)
204
+ new do |organization|
205
+ organization.company = xml.attributes['company']
206
+ organization.first_name = xml.attributes['first-name']
207
+ organization.last_name = xml.attributes['last-name']
208
+ organization.phone = xml.attributes['phone-number']
209
+ xml.elements.each('Address') do |address|
210
+ organization.address = Address.parse(address)
256
211
  end
212
+ organization.email = xml.attributes['email']
213
+ organization.title = xml.attributes['title']
214
+ organization.url = xml.attributes['url']
257
215
  end
216
+ end
217
+ end
258
218
 
259
- address_xml = make_xml 'Address', silo_config['organization']['address'], '', false
260
- org_xml.add_element address_xml
261
- silo_config_xml.add_element org_xml
219
+ class Merchant < Organization
220
+ attr_accessor :acquirer_relationship
221
+ attr_accessor :agent_relationship
222
+ attr_accessor :ecommerce
223
+ attr_accessor :grocery
224
+ attr_accessor :mail_order
225
+ attr_accessor :payment_application
226
+ attr_accessor :payment_version
227
+ attr_accessor :petroleum
228
+ attr_accessor :retail
229
+ attr_accessor :telecommunication
230
+ attr_accessor :travel
231
+ attr_accessor :dbas
232
+ attr_accessor :industries
233
+ attr_accessor :qsa
234
+
235
+ def initialize(&block)
236
+ instance_eval &block if block_given?
237
+ @dbas = Array(@dbas)
238
+ @industries = Array(@industries)
239
+ @qsa = Array(@qsa)
262
240
  end
263
241
 
264
- # Add Merchant info
265
- if silo_config['merchant']
266
- merchant_xml = make_xml 'Merchant', {}, '', false
242
+ def self.parse(xml)
243
+ new do |merchant|
244
+ merchant.acquirer_relationship = xml.attributes['acquirer-relationship'].to_s.chomp.eql?('true')
245
+ merchant.agent_relationship = xml.attributes['agent-relationship'].to_s.chomp.eql?('true')
246
+ merchant.ecommerce = xml.attributes['ecommerce'].to_s.chomp.eql?('true')
247
+ merchant.grocery = xml.attributes['grocery'].to_s.chomp.eql?('true')
248
+ merchant.mail_order = xml.attributes['mail-order'].to_s.chomp.eql?('true')
249
+ merchant.payment_application = xml.attributes['payment-application']
250
+ merchant.payment_version = xml.attributes['payment-version']
251
+ merchant.petroleum = xml.attributes['petroleum'].to_s.chomp.eql?('true')
252
+ merchant.retail = xml.attributes['retail'].to_s.chomp.eql?('true')
253
+ merchant.telecommunication = xml.attributes['telecommunication'].to_s.chomp.eql?('true')
254
+ merchant.travel = xml.attributes['travel'].to_s.chomp.eql?('true')
255
+ merchant.company = xml.attributes['company']
256
+ merchant.first_name = xml.attributes['first-name']
257
+ merchant.last_name = xml.attributes['last-name']
258
+ merchant.phone = xml.attributes['phone-number']
259
+ merchant.email = xml.attributes['email']
260
+ merchant.title = xml.attributes['title']
261
+ merchant.url = xml.attributes['url']
262
+
263
+ xml.elements.each('Address') do |address|
264
+ merchant.address = Address.parse(address)
265
+ end
267
266
 
268
- silo_config['merchant'].keys.each do |key|
269
- if not 'dba'.eql? key and not 'other_industries'.eql? key and not 'qsa'.eql? key and not 'address'.eql? key
270
- merchant_xml.attributes[key] = silo_config['merchant'][key]
267
+ merchant.dbas = []
268
+ xml.elements.each('DBAs/DBA') do |dba|
269
+ merchant.dbas << dba.attributes['name']
271
270
  end
272
- end
273
271
 
274
- # Add the merchant address
275
- merchant_address_xml = make_xml 'Address', silo_config['merchant']['address'], '', false
276
- merchant_xml.add_element merchant_address_xml
272
+ merchant.industries = []
273
+ xml.elements.each('OtherIndustries/Industry') do |industry|
274
+ merchant.industries << industry.attributes['name']
275
+ end
277
276
 
278
- #Now add the complex data types
279
- if silo_config['merchant']['dba']
280
- dba_xml = make_xml 'DBAs', {}, '', false
281
- silo_config['merchant']['dba'].each do |name|
282
- dba_xml.add_element make_xml('DBA', {'name' => name}, '', false)
277
+ merchant.qsa = []
278
+ xml.elements.each('QSA') do |organization|
279
+ merchant.qsa << Organization.parse(organization)
283
280
  end
284
- merchant_xml.add_element dba_xml
285
281
  end
282
+ end
283
+
284
+ def as_xml
285
+ xml = super
286
+ xml.name = 'Merchant'
287
+ xml.add_attributes({'acquirer-relationship' => @acquirer_relationship, 'agent-relationship' => @agent_relationship, 'ecommerce' => @ecommerce, 'grocery' => @grocery, 'mail-order' => @mail_order})
288
+ xml.add_attributes({'payment-application' => @payment_application, 'payment-version' => @payment_version, 'petroleum' => @petroleum, 'retail' => @retail, 'telecommunication' => @telecommunication, 'travel' => @travel})
286
289
 
287
- if silo_config['merchant']['other_industries']
288
- ois_xml = make_xml 'OtherIndustries', {}, '', false
289
- silo_config['merchant']['other_industries'].each do |name|
290
- ois_xml.add_element make_xml('Industry', {'name' => name}, '', false)
290
+ unless dbas.empty?
291
+ dbas = REXML::Element.new('DBAs')
292
+ @dbas.each do |dba|
293
+ dbas.add_element('DBA', {'name' => dba})
291
294
  end
292
- merchant_xml.add_element ois_xml
293
295
  end
294
296
 
295
- if silo_config['merchant']['qsa']
296
- qsa_xml = make_xml 'QSA', {}, '', false
297
- silo_config['merchant']['qsa'].keys.each do |key|
298
- if not 'address'.eql? key
299
- qsa_xml.attributes[key] = silo_config['merchant']['qsa'][key]
300
- end
297
+ unless @industries.empty?
298
+ industries = REXML::Element.new('OtherIndustries')
299
+ @industries.each do |industry|
300
+ industries.add_element('Industry', {'name' => industry})
301
301
  end
302
+ end
302
303
 
303
- # Add the address for this QSA
304
- address_xml = make_xml 'Address', silo_config['merchant']['qsa']['address'], '', false
304
+ xml.add(@qsa.as_xml) unless @qsa.empty?
305
305
 
306
- qsa_xml.add_element address_xml
307
- merchant_xml.add_element qsa_xml
308
- end
309
- silo_config_xml.add_element merchant_xml
306
+ xml
310
307
  end
311
-
312
- xml.add_element silo_config_xml
313
- r = execute xml, '1.2'
314
- r.success
315
308
  end
309
+ end
316
310
 
317
- #-------------------------------------------------------------------------
318
- # Lists all the silos and their attributes.
319
- #-------------------------------------------------------------------------
320
- def list_silos
321
- xml = make_xml('SiloListingRequest')
322
- r = execute xml, '1.2'
311
+ # Object that represents the summary of a Nexpose Site.
312
+ #
313
+ class SiloSummary
314
+ # The silo ID.
315
+ attr_reader :id
316
+ # The silo name.
317
+ attr_reader :name
318
+ # A description of the silo.
319
+ attr_reader :description
320
+ # The ID of the silo profile being used for this silo.
321
+ attr_reader :profile_id
322
+ # The asset count for this silo
323
+ attr_reader :assets
324
+ # The asset count limit for this silo.
325
+ attr_reader :max_assets
326
+ # The hosted asset count limit for this silo.
327
+ attr_reader :max_hosted_assets
328
+ # The user count for this silo
329
+ attr_reader :users
330
+ # The user count limit for this silo.
331
+ attr_reader :max_users
332
+
333
+ def initialize(&block)
334
+ instance_eval &block if block_given?
335
+ end
323
336
 
324
- if r.success
325
- res = []
326
- r.res.elements.each("//SiloSummary") do |silo_profile|
327
- res << {
328
- :id => silo_profile.attributes['id'],
329
- :name => silo_profile.attributes['name'],
330
- :description => silo_profile.attributes['description']
331
- }
337
+ def self.parse(xml)
338
+ new do
339
+ @id = xml.attributes['id']
340
+ @name = xml.attributes['name']
341
+ @description = xml.attributes['description']
342
+ @profile_id = xml.attributes['silo-profile-id']
343
+ xml.elements.each('LicenseSummary') do |license|
344
+ @assets = license.attributes['assets']
345
+ @max_assets = license.attributes['max-assets']
346
+ @max_hosted_assets = license.attributes['max-hosted-assets']
347
+ @users = license.attributes['users']
348
+ @max_users = license.attributes['max-users']
332
349
  end
333
- res
334
- else
335
- false
336
350
  end
337
351
  end
338
-
339
- #-------------------------------------------------------------------------
340
- # Delete a silo
341
- #-------------------------------------------------------------------------
342
- def delete_silo name, id
343
- using_name = (name and not name.empty?)
344
- xml = make_xml('SiloDeleteRequest', (using_name ? {'silo-name' => name} : {'silo-id' => id}))
345
- r = execute xml, '1.2'
346
- r.success
347
- end
348
352
  end
349
353
  end