nexpose 0.0.9 → 0.0.91

Sign up to get free protection for your applications and to get access to all the features.
@@ -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