nexpose 0.0.9 → 0.0.91

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.
@@ -0,0 +1,280 @@
1
+ module Nexpose
2
+ module NexposeAPI
3
+ include XMLUtils
4
+
5
+ def scan_stop(param)
6
+ r = execute(make_xml('ScanStopRequest', {'scan-id' => param}))
7
+ r.success
8
+ end
9
+
10
+ def scan_status(param)
11
+ r = execute(make_xml('ScanStatusRequest', {'scan-id' => param}))
12
+ r.success ? r.attributes['status'] : nil
13
+ end
14
+
15
+ def scan_activity
16
+ r = execute(make_xml('ScanActivityRequest', {}))
17
+ if (r.success)
18
+ res = []
19
+ r.res.elements.each("//ScanSummary") do |scan|
20
+ res << {
21
+ :scan_id => scan.attributes['scan-id'].to_i,
22
+ :site_id => scan.attributes['site-id'].to_i,
23
+ :engine_id => scan.attributes['engine-id'].to_i,
24
+ :status => scan.attributes['status'].to_s,
25
+ :start_time => Date.parse(scan.attributes['startTime'].to_s).to_time
26
+ }
27
+ end
28
+ res
29
+ else
30
+ false
31
+ end
32
+ end
33
+
34
+ def scan_statistics(param)
35
+ r = execute(make_xml('ScanStatisticsRequest', {'scan-id' => param}))
36
+ if (r.success)
37
+ res = {}
38
+ r.res.elements.each("//ScanSummary/nodes") do |node|
39
+ res[:nodes] = {}
40
+ node.attributes.keys.each do |k|
41
+ res[:nodes][k] = node.attributes[k].to_i
42
+ end
43
+ end
44
+ r.res.elements.each("//ScanSummary/tasks") do |task|
45
+ res[:task] = {}
46
+ task.attributes.keys.each do |k|
47
+ res[:task][k] = task.attributes[k].to_i
48
+ end
49
+ end
50
+ r.res.elements.each("//ScanSummary/vulnerabilities") do |vuln|
51
+ res[:vulns] ||= {}
52
+ k = vuln.attributes['status'] + (vuln.attributes['severity'] ? ("-" + vuln.attributes['severity']) : '')
53
+ res[:vulns][k] = vuln.attributes['count'].to_i
54
+ end
55
+ r.res.elements.each("//ScanSummary") do |summ|
56
+ res[:summary] = {}
57
+ summ.attributes.keys.each do |k|
58
+ res[:summary][k] = summ.attributes[k]
59
+ if (res[:summary][k] =~ /^\d+$/)
60
+ res[:summary][k] = res[:summary][k].to_i
61
+ end
62
+ end
63
+ end
64
+ r.res.elements.each("//ScanSummary/message") do |message|
65
+ res[:message] = message.text
66
+ end
67
+ res
68
+ else
69
+ false
70
+ end
71
+ end
72
+ end
73
+
74
+ # === Description
75
+ # Object that represents a summary of a scan.
76
+ #
77
+ class ScanSummary
78
+ # The Scan ID of the Scan
79
+ attr_reader :scan_id
80
+ # The Engine ID used to perform the scan
81
+ attr_reader :engine_id
82
+ # TODO: add description
83
+ attr_reader :name
84
+ # The scan start time
85
+ attr_reader :startTime
86
+ # The scan finish time
87
+ attr_reader :endTime
88
+ # The scan status (running|finished|stopped|error| dispatched|paused|aborted|uknown)
89
+ attr_reader :status
90
+ # The number of pending tasks
91
+ attr_reader :tasks_pending
92
+ # The number of active tasks
93
+ attr_reader :tasks_active
94
+ # The number of completed tasks
95
+ attr_reader :tasks_completed
96
+ # The number of "live" nodes
97
+ attr_reader :nodes_live
98
+ # The number of "dead" nodes
99
+ attr_reader :nodes_dead
100
+ # The number of filtered nodes
101
+ attr_reader :nodes_filtered
102
+ # The number of unresolved nodes
103
+ attr_reader :nodes_unresolved
104
+ # The number of "other" nodes
105
+ attr_reader :nodes_other
106
+ # Confirmed vulnerabilities found (indexed by severity)
107
+ # Associative array, indexed by severity
108
+ attr_reader :vuln_exploit
109
+ # Unconfirmed vulnerabilities found (indexed by severity)
110
+ # Associative array, indexed by severity
111
+ attr_reader :vuln_version
112
+ # Not vulnerable checks run (confirmed)
113
+ attr_reader :not_vuln_exploit
114
+ # Not vulnerable checks run (unconfirmed)
115
+ attr_reader :not_vuln_version
116
+ # Vulnerability check errors
117
+ attr_reader :vuln_error
118
+ # Vulnerability checks disabled
119
+ attr_reader :vuln_disabled
120
+ # Vulnerability checks other
121
+ attr_reader :vuln_other
122
+
123
+ # Constructor
124
+ # ScanSummary(can_id, $engine_id, $name, tartTime, $endTime, tatus)
125
+ def initialize(scan_id, engine_id, name, startTime, endTime, status)
126
+
127
+ @scan_id = scan_id
128
+ @engine_id = engine_id
129
+ @name = name
130
+ @startTime = startTime
131
+ @endTime = endTime
132
+ @status = status
133
+
134
+ end
135
+
136
+ end
137
+
138
+ # TODO
139
+ # === Description
140
+ # Object that represents the overview statistics for a particular scan.
141
+ #
142
+ # === Examples
143
+ #
144
+ # # Create a new Nexpose Connection on the default port and Login
145
+ # nsc = Connection.new("10.1.40.10","nxadmin","password")
146
+ # nsc.login()
147
+ #
148
+ # # Get a Site (Site ID = 12) from the NSC
149
+ # site = new Site(nsc,12)
150
+ #
151
+ # # Start a Scan of this site and pause for 1 minute
152
+ # scan1 = site.scanSite()
153
+ # sleep(60)
154
+ #
155
+ # # Get the Scan Statistics for this scan
156
+ # scanStatistics = new ScanStatistics(nsc,scan1["scan_id"])
157
+ #
158
+ # # Print out number of confirmed vulnerabilities with a 10 severity
159
+ # puts scanStatistics.scansummary.vuln_exploit[10]
160
+ #
161
+ # # Print out the number of pending tasks left in the scan
162
+ # puts scanStatistics.scan_summary.tasks_pending
163
+ #
164
+ class ScanStatistics
165
+ # true if an error condition exists; false otherwise
166
+ attr_reader :error
167
+ # Error message string
168
+ attr_reader :error_msg
169
+ # The last XML request sent by this object
170
+ attr_reader :request_xml
171
+ # The last XML response received by this object
172
+ attr_reader :reseponse_xml
173
+ # The Scan ID
174
+ attr_reader :scan_id
175
+ # The ScanSummary of the scan
176
+ attr_reader :scan_summary
177
+ # The NSC Connection associated with this object
178
+ attr_reader :connection
179
+
180
+ # Vulnerability checks other
181
+ attr_reader :vuln_other
182
+
183
+ def initialize(connection, scan_id)
184
+ @error = false
185
+ @connection = connection
186
+ @scan_id = scan_id
187
+ end
188
+ end
189
+
190
+ # TODO add engineID
191
+ # === Description
192
+ # Object that represents the scanning configuration for a Site.
193
+ #
194
+ class ScanConfig
195
+ # A unique ID for this scan configuration
196
+ attr_reader :configID
197
+ # The name of the scan template
198
+ attr_reader :name
199
+ # The ID of the scan template used full-audit, exhaustive-audit, web-audit, dos-audit, internet-audit, network-audit
200
+ attr_reader :templateID
201
+ # The configuration version (default is 2)
202
+ attr_reader :configVersion
203
+ # Array of (Schedule)*
204
+ attr_reader :schedules
205
+ # Array of (ScanTrigger)*
206
+ attr_reader :scanTriggers
207
+
208
+ def initialize(configID, name, templateID, configVersion = 2)
209
+
210
+ @configID = configID
211
+ @name = name
212
+ @templateID = templateID
213
+ @configVersion = configVersion
214
+ @schedules = Array.new()
215
+ @scanTriggers = Array.new()
216
+
217
+ end
218
+
219
+ # Adds a new Schedule for this ScanConfig
220
+ def addSchedule(schedule)
221
+ @schedules.push(schedule)
222
+ end
223
+
224
+ # Adds a new ScanTrigger to the scanTriggers array
225
+ def addScanTrigger(scanTrigger)
226
+ @scanTriggers.push(scanTrigger)
227
+ end
228
+
229
+ def _set_configID(configID)
230
+ @configID = configID
231
+ end
232
+
233
+ def _set_name(name)
234
+ @name = name
235
+ end
236
+
237
+ end
238
+
239
+ # TODO: review
240
+ # <scanFilter scanStop='0' scanFailed='0' scanStart='1'/>
241
+ # === Description
242
+ #
243
+ class ScanFilter
244
+
245
+ attr_reader :scanStop
246
+ attr_reader :scanFailed
247
+ attr_reader :scanStart
248
+
249
+ def initialize(scanstop, scanFailed, scanStart)
250
+
251
+ @scanStop = scanStop
252
+ @scanFailed = scanFailed
253
+ @scanStart = scanStart
254
+
255
+ end
256
+
257
+ end
258
+
259
+
260
+ # === Description
261
+ # Object that holds an event that triggers the start of a scan.
262
+ #
263
+ class ScanTrigger
264
+ # Type of Trigger (AutoUpdate)
265
+ attr_reader :type
266
+ # Enable or disable this scan trigger
267
+ attr_reader :enabled
268
+ # Sets the trigger to start an incremental scan or a full scan
269
+ attr_reader :incremental
270
+
271
+ def initialize(type, incremental, enabled = 1)
272
+
273
+ @type = type
274
+ @incremental = incremental
275
+ @enabled = enabled
276
+
277
+ end
278
+ end
279
+
280
+ end
@@ -0,0 +1,147 @@
1
+ module Nexpose
2
+
3
+ # ==== Description
4
+ # Object that represents a listing of all of the scan engines available on to an NSC.
5
+ #
6
+ class EngineListing
7
+ # true if an error condition exists; false otherwise
8
+ attr_reader :error
9
+ # Error message string
10
+ attr_reader :error_msg
11
+ # The last XML request sent by this object
12
+ attr_reader :request_xml
13
+ # The last XML response received by this object
14
+ attr_reader :response_xml
15
+ # The NSC Connection associated with this object
16
+ attr_reader :connection
17
+ # Array containing (EngineSummary*)
18
+ attr_reader :engines
19
+ # The number of scan engines
20
+ attr_reader :engine_count
21
+
22
+ # Constructor
23
+ # EngineListing (connection)
24
+ def initialize(connection)
25
+ @connection = connection
26
+ @engines = []
27
+ @engine_count = 0
28
+ @error = false
29
+ r = @connection.execute('<EngineListingRequest session-id="' + @connection.session_id + '"/>', '1.2')
30
+
31
+ if (r.success)
32
+ r.res.elements.each('EngineListingResponse/EngineSummary') do |v|
33
+ @engines.push(EngineSummary.new(v.attributes['id'], v.attributes['name'], v.attributes['address'],
34
+ v.attributes['port'], v.attributes['status']))
35
+ end
36
+ else
37
+ @error = true
38
+ @error_msg = 'EngineListingRequest Parse Error'
39
+ end
40
+ @engine_count = @engines.length
41
+ end
42
+ end
43
+
44
+ # TODO
45
+ class EngineActivity
46
+ # true if an error condition exists; false otherwise
47
+ attr_reader :error
48
+ # Error message string
49
+ attr_reader :error_msg
50
+ # The last XML request sent by this object
51
+ attr_reader :request_xml
52
+ # The last XML response received by this object
53
+ attr_reader :response_xml
54
+ # The NSC Connection associated with this object
55
+ attr_reader :connection
56
+ # The Engine ID
57
+ attr_reader :engine_id
58
+ # Array containing (ScanSummary*)
59
+ attr_reader :scan_summaries
60
+ end
61
+
62
+ # ==== Description
63
+ # Object that represents the summary of a scan engine.
64
+ #
65
+ # ==== Examples
66
+ #
67
+ # # Create a new Nexpose Connection on the default port and Login
68
+ # nsc = Connection.new("10.1.40.10","nxadmin","password")
69
+ # nsc.login()
70
+ #
71
+ # # Get the engine listing for the connection
72
+ # enginelisting = EngineListing.new(nsc)
73
+ #
74
+ # # Print out the status of the first scan engine
75
+ # puts enginelisting.engines[0].status
76
+ #
77
+ class EngineSummary
78
+ # A unique ID that identifies this scan engine
79
+ attr_reader :id
80
+ # The name of this scan engine
81
+ attr_reader :name
82
+ # The hostname or IP address of the engine
83
+ attr_reader :address
84
+ # The port there the engine is listening
85
+ attr_reader :port
86
+ # The engine status (active|pending-auth| incompatible|not-responding|unknown)
87
+ attr_reader :status
88
+
89
+ # Constructor
90
+ # EngineSummary(id, name, address, port, status)
91
+ def initialize(id, name, address, port, status)
92
+ @id = id
93
+ @name = name
94
+ @address = address
95
+ @port = port
96
+ @status = status
97
+ end
98
+
99
+ end
100
+
101
+ #-------------------------------------------------------------------------------------------------------------------
102
+ #
103
+ #-------------------------------------------------------------------------------------------------------------------
104
+ class EngineConfig
105
+ attr_accessor :id
106
+ attr_accessor :address
107
+ attr_accessor :name
108
+ attr_accessor :port
109
+ attr_accessor :scope
110
+ attr_accessor :sites
111
+ attr_accessor :priority
112
+
113
+ def initialize(connection, engine_id)
114
+ @connection = connection
115
+ @id = nil
116
+ @address = nil
117
+ @name = nil
118
+ @port = nil
119
+ @scope = nil
120
+ @priority = 'global'
121
+ @sites = []
122
+
123
+ r = @connection.execute('<EngineConfigRequest session-id="' + @connection.session_id + '" engine-id="' + engine_id + '"/>', '1.2')
124
+
125
+ if (r.success)
126
+ r.res.elements.each('EngineConfigResponse/EngineConfig') do |v|
127
+ @id = v.attributes['id']
128
+ @address = v.attributes['address']
129
+ @name = v.attributes['name']
130
+ @port = v.attributes['port']
131
+ @scope = v.attributes['scope']
132
+ v.elements.each('Site') do |s|
133
+ @sites << s.attributes['id']
134
+ end
135
+ end
136
+ else
137
+ @error = true
138
+ @error_msg = 'EngineConfigRequest Parse Error'
139
+ end
140
+ end
141
+
142
+ def save
143
+
144
+ end
145
+ end
146
+
147
+ end
@@ -0,0 +1,347 @@
1
+ module Nexpose
2
+ module NexposeAPI
3
+ include XMLUtils
4
+
5
+ ###################
6
+ # SILO MANAGEMENT #
7
+ ###################
8
+
9
+ #########################
10
+ # MULTI-TENANT USER OPS #
11
+ #########################
12
+
13
+ #-------------------------------------------------------------------------
14
+ # Creates a multi-tenant user
15
+ #
16
+ # user_config - A map of the user data.
17
+ #
18
+ # REQUIRED PARAMS
19
+ # user-id, authsrcid, user-name, full-name, enabled, superuser
20
+ #
21
+ # OPTIONAL PARAMS
22
+ # email, password
23
+ #
24
+ # silo_configs - An array of maps of silo specific data
25
+ #
26
+ # REQUIRED PARAMS
27
+ # silo-id, role-name, all-groups, all-sites, default-silo
28
+ #
29
+ # allowed_groups/allowed_sites - An array of ids
30
+ #-------------------------------------------------------------------------
31
+ def create_multi_tenant_user(user_config, silo_configs)
32
+ xml = make_xml('MultiTenantUserCreateRequest')
33
+ mtu_config_xml = make_xml('MultiTenantUserConfig', user_config, '', false)
34
+
35
+ # Add the silo access
36
+ silo_xml = make_xml('SiloAccesses', {}, '', false)
37
+ silo_config_xml = make_xml('SiloAccess', {}, '', false)
38
+ silo_configs.keys.each do |k|
39
+ if k.eql? 'allowed_sites'
40
+ allowed_sites_xml = make_xml('AllowedSites', {}, '', false)
41
+ silo_configs['allowed_sites'].each do |allowed_site|
42
+ allowed_sites_xml.add_element make_xml('AllowedSite', {'id' => allowed_site}, '', false)
43
+ end
44
+ silo_config_xml.add_element allowed_sites_xml
45
+ elsif k.eql? 'allowed_groups'
46
+ allowed_groups_xml = make_xml('AllowedGroups', {}, '', false)
47
+ silo_configs['allowed_groups'].each do |allowed_group|
48
+ allowed_groups_xml.add_element make_xml('AllowedGroup', {'id' => allowed_group}, '', false)
49
+ end
50
+ silo_config_xml.add_element allowed_groups_xml
51
+ else
52
+ silo_config_xml.attributes[k] = silo_configs[k]
53
+ end
54
+ end
55
+ silo_xml.add_element silo_config_xml
56
+ mtu_config_xml.add_element silo_xml
57
+ xml.add_element mtu_config_xml
58
+ r = execute xml, '1.2'
59
+ r.success
60
+ end
61
+
62
+
63
+ #-------------------------------------------------------------------------
64
+ # Lists all the multi-tenant users and their attributes.
65
+ #-------------------------------------------------------------------------
66
+ def list_mtu
67
+ xml = make_xml('MultiTenantUserListingRequest')
68
+ r = execute xml, '1.2'
69
+
70
+ if r.success
71
+ res = []
72
+ r.res.elements.each("//MultiTenantUserSummary") do |mtu|
73
+ res << {
74
+ :id => mtu.attributes['id'],
75
+ :full_name => mtu.attributes['full-name'],
76
+ :user_name => mtu.attributes['user-name'],
77
+ :email => mtu.attributes['email'],
78
+ :super_user => mtu.attributes['superuser'],
79
+ :enabled => mtu.attributes['enabled'],
80
+ :auth_module => mtu.attributes['auth-module'],
81
+ :silo_count => mtu.attributes['silo-count'],
82
+ :locked => mtu.attributes['locked']
83
+ }
84
+ end
85
+ res
86
+ else
87
+ false
88
+ end
89
+ end
90
+
91
+ #-------------------------------------------------------------------------
92
+ # Delete a multi-tenant user
93
+ #-------------------------------------------------------------------------
94
+ def delete_mtu user_name, user_id
95
+ using_user_name = (user_name and not user_name.empty?)
96
+ xml = make_xml('MultiTenantUserDeleteRequest', (using_user_name ? {'user-name' => user_name} : {'user-id' => user_id}))
97
+ r = execute xml, '1.2'
98
+ r.success
99
+ end
100
+
101
+ ####################
102
+ # SILO PROFILE OPS #
103
+ ####################
104
+
105
+ #-------------------------------------------------------------------------
106
+ # Creates a silo profile
107
+ #
108
+ # silo_config - A map of the silo data.
109
+ #
110
+ # REQUIRED PARAMS
111
+ # id, name, all‐licensed-modules, all‐global-engines, all-global-report-templates, all‐global-scan‐templates
112
+ #
113
+ # OPTIONAL PARAMS
114
+ # description
115
+ #
116
+ # permissions - A map of an array of maps of silo specific data
117
+ #
118
+ # REQUIRED PARAMS
119
+ # silo-id, role-name, all-groups, all-sites, default-silo
120
+ #
121
+ # allowed_groups/allowed_sites - An array of ids
122
+ #-------------------------------------------------------------------------
123
+ def create_silo_profile silo_profile_config, permissions
124
+ xml = make_xml 'SiloProfileCreateRequest'
125
+ spc_xml = make_xml('SiloProfileConfig', silo_profile_config, '', false)
126
+
127
+ # Add the permissions
128
+ if permissions['global_report_templates']
129
+ grt_xml = make_xml('GlobalReportTemplates', {}, '', false)
130
+ permissions['global_report_templates'].each do |name|
131
+ grt_xml.add_element make_xml('GlobalReportTemplate', {'name' => name}, '', false)
132
+ end
133
+ spc_xml.add_element grt_xml
134
+ end
135
+
136
+ if permissions['global_scan_engines']
137
+ gse_xml = make_xml('GlobalScanEngines', {}, '', false)
138
+ permissions['global_scan_engines'].each do |name|
139
+ gse_xml.add_element make_xml('GlobalScanEngine', {'name' => name}, '', false)
140
+ end
141
+ spc_xml.add_element gse_xml
142
+ end
143
+
144
+ if permissions['global_scan_templates']
145
+ gst_xml = make_xml('GlobalScanTemplates', {}, '', false)
146
+ permissions['global_scan_templates'].each do |name|
147
+ gst_xml.add_element make_xml('GlobalScanTemplate', {'name' => name}, '', false)
148
+ end
149
+ spc_xml.add_element gst_xml
150
+ end
151
+
152
+ if permissions['licensed_modules']
153
+ lm_xml = make_xml('LicensedModules', {}, '', false)
154
+ permissions['licensed_modules'].each do |name|
155
+ lm_xml.add_element make_xml('LicensedModule', {'name' => name}, '', false)
156
+ end
157
+ spc_xml.add_element lm_xml
158
+ end
159
+
160
+ if permissions['restricted_report_formats']
161
+ rrf_xml = make_xml('RestrictedReportFormats', {}, '', false)
162
+ permissions['restricted_report_formats'].each do |name|
163
+ rrf_xml.add_element make_xml('RestrictedReportFormat', {'name' => name}, '', false)
164
+ end
165
+ spc_xml.add_element rrf_xml
166
+ end
167
+
168
+ if permissions['restricted_report_sections']
169
+ rrs_xml = make_xml('RestrictedReportSections', {}, '', false)
170
+ permissions['restricted_report_sections'].each do |name|
171
+ rrs_xml.add_element make_xml('RestrictedReportSection', {'name' => name}, '', false)
172
+ end
173
+ spc_xml.add_element rrs_xml
174
+ end
175
+
176
+ xml.add_element spc_xml
177
+ r = execute xml, '1.2'
178
+ r.success
179
+ end
180
+
181
+ #-------------------------------------------------------------------------
182
+ # Lists all the silo profiles and their attributes.
183
+ #-------------------------------------------------------------------------
184
+ def list_silo_profiles
185
+ xml = make_xml('SiloProfileListingRequest')
186
+ r = execute xml, '1.2'
187
+
188
+ if r.success
189
+ res = []
190
+ r.res.elements.each("//SiloProfileSummary") do |silo_profile|
191
+ res << {
192
+ :id => silo_profile.attributes['id'],
193
+ :name => silo_profile.attributes['name'],
194
+ :description => silo_profile.attributes['description'],
195
+ :global_report_template_count => silo_profile.attributes['global-report-template-count'],
196
+ :global_scan_engine_count => silo_profile.attributes['global-scan-engine-count'],
197
+ :global_scan_template_count => silo_profile.attributes['global-scan-template-count'],
198
+ :licensed_module_count => silo_profile.attributes['licensed-module-count'],
199
+ :restricted_report_section_count => silo_profile.attributes['restricted-report-section-count'],
200
+ :all_licensed_modules => silo_profile.attributes['all-licensed-modules'],
201
+ :all_global_engines => silo_profile.attributes['all-global-engines'],
202
+ :all_global_report_templates => silo_profile.attributes['all-global-report-templates'],
203
+ :all_global_scan_templates => silo_profile.attributes['all-global-scan-templates']
204
+ }
205
+ end
206
+ res
207
+ else
208
+ false
209
+ end
210
+ end
211
+
212
+ #-------------------------------------------------------------------------
213
+ # Delete a silo profile
214
+ #-------------------------------------------------------------------------
215
+ def delete_silo_profile name, id
216
+ using_name = (name and not name.empty?)
217
+ xml = make_xml('SiloProfileDeleteRequest', (using_name ? {'name' => name} : {'silo-profile-id' => id}))
218
+ r = execute xml, '1.2'
219
+ r.success
220
+ end
221
+
222
+ ####################
223
+ # SILO OPS #
224
+ ####################
225
+
226
+ #-------------------------------------------------------------------------
227
+ # Creates a silo
228
+ #
229
+ # silo_config - A map of the silo creation data.
230
+ #
231
+ # REQUIRED PARAMS
232
+ # id, name, silo-profile-id, max-assets, max-hosted-assets, max-users
233
+ #
234
+ # OPTIONAL PARAMS
235
+ # description
236
+ #-------------------------------------------------------------------------
237
+ def create_silo silo_config
238
+ xml = make_xml 'SiloCreateRequest'
239
+ silo_config_xml = make_xml 'SiloConfig', {}, '', false
240
+
241
+ # Add the attributes
242
+ silo_config.keys.each do |key|
243
+ if not 'merchant'.eql? key and not 'organization'.eql? key
244
+ silo_config_xml.attributes[key] = silo_config[key]
245
+ end
246
+ end
247
+
248
+ # Add Organization info
249
+ if silo_config['organization']
250
+ org_xml = make_xml 'Organization', {}, '', false
251
+ silo_config['organization'].keys.each do |key|
252
+ if not 'address'.eql? key
253
+ org_xml.attributes[key] = silo_config['organization'][key]
254
+ end
255
+ end
256
+
257
+ address_xml = make_xml 'Address', silo_config['organization']['address'], '', false
258
+ org_xml.add_element address_xml
259
+ silo_config_xml.add_element org_xml
260
+ end
261
+
262
+ # Add Merchant info
263
+ if silo_config['merchant']
264
+ merchant_xml = make_xml 'Merchant', {}, '', false
265
+
266
+ silo_config['merchant'].keys.each do |key|
267
+ if not 'dba'.eql? key and not 'other_industries'.eql? key and not 'qsa'.eql? key and not 'address'.eql? key
268
+ merchant_xml.attributes[key] = silo_config['merchant'][key]
269
+ end
270
+ end
271
+
272
+ # Add the merchant address
273
+ merchant_address_xml = make_xml 'Address', silo_config['merchant']['address'], '', false
274
+ merchant_xml.add_element merchant_address_xml
275
+
276
+ #Now add the complex data types
277
+ if silo_config['merchant']['dba']
278
+ dba_xml = make_xml 'DBAs', {}, '', false
279
+ silo_config['merchant']['dba'].each do |name|
280
+ dba_xml.add_element make_xml('DBA', {'name' => name}, '', false)
281
+ end
282
+ merchant_xml.add_element dba_xml
283
+ end
284
+
285
+ if silo_config['merchant']['other_industries']
286
+ ois_xml = make_xml 'OtherIndustries', {}, '', false
287
+ silo_config['merchant']['other_industries'].each do |name|
288
+ ois_xml.add_element make_xml('Industry', {'name' => name}, '', false)
289
+ end
290
+ merchant_xml.add_element ois_xml
291
+ end
292
+
293
+ if silo_config['merchant']['qsa']
294
+ qsa_xml = make_xml 'QSA', {}, '', false
295
+ silo_config['merchant']['qsa'].keys.each do |key|
296
+ if not 'address'.eql? key
297
+ qsa_xml.attributes[key] = silo_config['merchant']['qsa'][key]
298
+ end
299
+ end
300
+
301
+ # Add the address for this QSA
302
+ address_xml = make_xml 'Address', silo_config['merchant']['qsa']['address'], '', false
303
+
304
+ qsa_xml.add_element address_xml
305
+ merchant_xml.add_element qsa_xml
306
+ end
307
+ silo_config_xml.add_element merchant_xml
308
+ end
309
+
310
+ xml.add_element silo_config_xml
311
+ r = execute xml, '1.2'
312
+ r.success
313
+ end
314
+
315
+ #-------------------------------------------------------------------------
316
+ # Lists all the silos and their attributes.
317
+ #-------------------------------------------------------------------------
318
+ def list_silos
319
+ xml = make_xml('SiloListingRequest')
320
+ r = execute xml, '1.2'
321
+
322
+ if r.success
323
+ res = []
324
+ r.res.elements.each("//SiloSummary") do |silo_profile|
325
+ res << {
326
+ :id => silo_profile.attributes['id'],
327
+ :name => silo_profile.attributes['name'],
328
+ :description => silo_profile.attributes['description']
329
+ }
330
+ end
331
+ res
332
+ else
333
+ false
334
+ end
335
+ end
336
+
337
+ #-------------------------------------------------------------------------
338
+ # Delete a silo
339
+ #-------------------------------------------------------------------------
340
+ def delete_silo name, id
341
+ using_name = (name and not name.empty?)
342
+ xml = make_xml('SiloDeleteRequest', (using_name ? {'silo-name' => name} : {'silo-id' => id}))
343
+ r = execute xml, '1.2'
344
+ r.success
345
+ end
346
+ end
347
+ end