mu 5.7.39 → 5.7.40
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.
- data/lib/mu/command/cmd_runanalysis.rb +519 -46
- data/version.rb +1 -1
- metadata +107 -79
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'mu/api/muapi'
|
4
4
|
class Mu
|
5
5
|
class Command
|
6
|
-
class
|
6
|
+
class Cmd_runanalysis < Command
|
7
7
|
|
8
8
|
attr_accessor :host, :username, :password, :api, :docroot
|
9
9
|
|
@@ -12,6 +12,12 @@ class Cmd_runfuzz < Command
|
|
12
12
|
def cmd_help argv
|
13
13
|
help
|
14
14
|
end
|
15
|
+
|
16
|
+
# logging in this script
|
17
|
+
def log(message="",level=nil)
|
18
|
+
msg message, level
|
19
|
+
File.open(@@output_log, "a") {|f| f.write(message) }
|
20
|
+
end
|
15
21
|
|
16
22
|
# capture has a set of three commands that are used to generate
|
17
23
|
# packet captures, poll the status and return the resulting file
|
@@ -23,8 +29,12 @@ class Cmd_runfuzz < Command
|
|
23
29
|
# * port = the Mu interface on which to capture packets
|
24
30
|
def cmd_run argv
|
25
31
|
setup argv
|
26
|
-
# set all
|
32
|
+
# set all params
|
27
33
|
archive = @hash['archive']
|
34
|
+
if archive == nil
|
35
|
+
archive = false
|
36
|
+
end
|
37
|
+
archive_options = @hash['archive_options']
|
28
38
|
directory = @hash['directory']
|
29
39
|
force = @hash['force']
|
30
40
|
interval = @hash['interval']
|
@@ -32,6 +42,14 @@ class Cmd_runfuzz < Command
|
|
32
42
|
prepend = @hash['prepend']
|
33
43
|
template = @hash['template']
|
34
44
|
uuid = @hash['uuid']
|
45
|
+
verify = @hash['verify']
|
46
|
+
if verify == nil
|
47
|
+
verify = false
|
48
|
+
end
|
49
|
+
verifyonly = @hash['verifyonly']
|
50
|
+
if verifyonly == nil
|
51
|
+
verifyonly = false
|
52
|
+
end
|
35
53
|
|
36
54
|
# set any timers to minimum non psychotic numbers
|
37
55
|
sleeptime = 10 # 10 sec
|
@@ -64,7 +82,7 @@ class Cmd_runfuzz < Command
|
|
64
82
|
files = Dir.glob(File.join(@hash["directory"],"","*.xml"))
|
65
83
|
files.each do | file |
|
66
84
|
response = @api.import_templates(file)
|
67
|
-
|
85
|
+
log response, Logger::DEBUG
|
68
86
|
doc = make_xml(response)
|
69
87
|
unless doc.xpath("//model_object").empty?
|
70
88
|
doc.xpath("//model_object").each do |node|
|
@@ -72,7 +90,7 @@ class Cmd_runfuzz < Command
|
|
72
90
|
my_name = node.xpath("name").text
|
73
91
|
my_type = node.xpath("type").text
|
74
92
|
if my_type=="Analysis"
|
75
|
-
|
93
|
+
log "type = #{my_type} uuid = #{my_uuid} name = #{my_name}", Logger::DEBUG
|
76
94
|
my_uuid_hash[my_uuid] = my_name
|
77
95
|
end
|
78
96
|
end
|
@@ -82,7 +100,7 @@ class Cmd_runfuzz < Command
|
|
82
100
|
if template != nil
|
83
101
|
# import template file into mu and add all uuids to list
|
84
102
|
response = @api.import_templates(template)
|
85
|
-
|
103
|
+
log response, Logger::DEBUG
|
86
104
|
doc = make_xml(response)
|
87
105
|
unless doc.xpath("//model_object").empty?
|
88
106
|
doc.xpath("//model_object").each do |node|
|
@@ -90,7 +108,7 @@ class Cmd_runfuzz < Command
|
|
90
108
|
my_name = node.xpath("name").text
|
91
109
|
my_type = node.xpath("type").text
|
92
110
|
if my_type=="Analysis"
|
93
|
-
|
111
|
+
log "type = #{my_type} uuid = #{my_uuid} name = #{my_name}", Logger::DEBUG
|
94
112
|
my_uuid_hash[my_uuid] = my_name
|
95
113
|
end
|
96
114
|
end
|
@@ -111,13 +129,15 @@ class Cmd_runfuzz < Command
|
|
111
129
|
end
|
112
130
|
end
|
113
131
|
if my_uuid_hash.empty?
|
114
|
-
|
132
|
+
log "no valid test option selected, please specify directory, template file, or uuid"
|
115
133
|
help
|
116
134
|
exit
|
135
|
+
else
|
136
|
+
log "#{my_uuid_hash.size} tests in queue."
|
117
137
|
end
|
118
138
|
|
119
139
|
# now we run all the tests
|
120
|
-
#
|
140
|
+
#log "RUNNING"
|
121
141
|
results = {}
|
122
142
|
map = my_uuid_hash.each_pair do |key,value|
|
123
143
|
t1 = Time.now.localtime.tv_sec
|
@@ -125,23 +145,47 @@ class Cmd_runfuzz < Command
|
|
125
145
|
suspend_time = t1
|
126
146
|
polling_time = t1
|
127
147
|
if prepend != nil
|
128
|
-
name = "#{prepend}
|
148
|
+
name = "#{prepend}#{value}"
|
129
149
|
else
|
130
|
-
name = value
|
150
|
+
name = "#{value}#{Time.now.localtime}"
|
151
|
+
end
|
152
|
+
if @@output_dir != nil
|
153
|
+
name = "#{@@output_dir}/#{prepend}#{value}"
|
154
|
+
end
|
155
|
+
log "my name = #{name} with uuid = #{key}", Logger::DEBUG
|
156
|
+
# need to set new host values if host values are present
|
157
|
+
hosts = @hash['hosts']
|
158
|
+
if hosts != nil
|
159
|
+
log "SET ALL HOSTS USING: #{hosts}", Logger::DEBUG
|
160
|
+
new_uuid = set_hosts(key,hosts)
|
161
|
+
end
|
162
|
+
verify_good = false
|
163
|
+
log "verify = #{verify} and verifyonly = #{verifyonly}"
|
164
|
+
if verify || verifyonly
|
165
|
+
log "verify = #{verify} and verifyonly = #{verifyonly}"
|
166
|
+
verify_good = verify_analysis(key,name)
|
167
|
+
end
|
168
|
+
if verifyonly
|
169
|
+
log "Verify Only! executing next test."
|
170
|
+
next
|
171
|
+
end
|
172
|
+
if verify && !verify_good
|
173
|
+
log "Analysis #{name} failed to verify! Executing next test."
|
174
|
+
next
|
131
175
|
end
|
132
|
-
msg "my name = #{name} with uuid = #{key}"
|
133
176
|
run = true
|
177
|
+
run_uuid = ""
|
134
178
|
run_uuid = @api.run(key, URI.encode(name))
|
135
179
|
while run
|
136
180
|
sleep(sleeptime)
|
137
181
|
status = @api.status(run_uuid)
|
138
|
-
|
182
|
+
log status
|
139
183
|
t2 = Time.now.localtime.tv_sec
|
140
|
-
|
184
|
+
log t2-t1
|
141
185
|
if interval > 0
|
142
186
|
if t2-polling_time > interval
|
143
187
|
faults = @api.get_faults(run_uuid)
|
144
|
-
|
188
|
+
log faults, Logger::DEBUG
|
145
189
|
# faults should be an xml doc already
|
146
190
|
unless faults.xpath("//fault_list_summary").empty?
|
147
191
|
count = 0
|
@@ -165,7 +209,7 @@ class Cmd_runfuzz < Command
|
|
165
209
|
confidence_level_1 += 1
|
166
210
|
end
|
167
211
|
end
|
168
|
-
|
212
|
+
log "Current fault count: #{count}, confidence_level 5: #{confidence_level_5}"+
|
169
213
|
", confidence_level 4: #{confidence_level_4}, confidence_level 3: #{confidence_level_3}"+
|
170
214
|
", confidence_level 2: #{confidence_level_2}, confidence_level 1: #{confidence_level_1}"
|
171
215
|
end
|
@@ -175,36 +219,66 @@ class Cmd_runfuzz < Command
|
|
175
219
|
if status =~ /ABORTED/ or status =~ /FINISHED/ or status =~ /FAILED/
|
176
220
|
run = false
|
177
221
|
elsif status =~ /SUSPENDED/
|
178
|
-
|
222
|
+
log "SUSPEND--->"
|
179
223
|
if t2-suspend_time > force*60
|
180
224
|
response = @api.resume(run_uuid)
|
181
|
-
|
225
|
+
log response
|
182
226
|
suspend_time = Time.now.localtime.tv_sec
|
183
227
|
end
|
184
228
|
end
|
185
229
|
end
|
186
|
-
# now we pull results for run and tabulate fault list
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
230
|
+
# now we pull results for run and tabulate fault list if needed
|
231
|
+
if archive
|
232
|
+
evts = false
|
233
|
+
pcaps = false
|
234
|
+
samples = false
|
235
|
+
logo = false
|
236
|
+
audit = false
|
237
|
+
sign = false
|
238
|
+
if archive_options =~ /evts/
|
239
|
+
evts = true
|
240
|
+
end
|
241
|
+
if archive_options =~ /pcaps/
|
242
|
+
pcaps = true
|
243
|
+
end
|
244
|
+
if archive_options =~ /samples/
|
245
|
+
samples = true
|
246
|
+
end
|
247
|
+
if archive_options =~ /logo/
|
248
|
+
logo = true
|
249
|
+
end
|
250
|
+
if archive_options =~ /audit/
|
251
|
+
audit = true
|
252
|
+
end
|
253
|
+
if archive_options =~ /sign/
|
254
|
+
sign = true
|
255
|
+
end
|
256
|
+
log "evts = #{evts}, pcaps = #{pcaps}, samples = #{samples}, logo = #{logo}, audit = #{audit}, sign = #{sign}", Logger::DEBUG
|
257
|
+
job_id = @api.archive("run",run_uuid,"",name,"Run via Mu Ruby Gem API #{Time.now}",evts,pcaps,samples,logo,audit,sign)
|
258
|
+
job = true
|
259
|
+
count = 0
|
260
|
+
while job
|
261
|
+
job_status = @api.archive("status", job_id)
|
262
|
+
log "archive job_status = #{job_status}"
|
263
|
+
if job_status =~ /Finished/
|
264
|
+
job = false
|
265
|
+
end
|
266
|
+
sleep(sleeptime)
|
267
|
+
count += 1
|
268
|
+
if count > 30
|
269
|
+
job = false
|
270
|
+
end
|
195
271
|
end
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
272
|
+
if File.exists?(name) && File.directory?(name)
|
273
|
+
log "directiry #{name} already exists", Logger::DEBUG
|
274
|
+
else
|
275
|
+
log "creating directory for archive results: #{name}", Logger::DEBUG
|
276
|
+
Dir.mkdir(name)
|
277
|
+
end
|
278
|
+
response = @api.archive("get",job_id,name)
|
201
279
|
end
|
202
|
-
if Dir[name] == nil
|
203
|
-
Dir.mkdir(name)
|
204
|
-
end
|
205
|
-
response = @api.archive("get",job_id,name)
|
206
280
|
faults = @api.get_faults(run_uuid)
|
207
|
-
|
281
|
+
log faults, Logger::DEBUG
|
208
282
|
# faults should be an xml doc already
|
209
283
|
unless faults.xpath("//fault_list_summary").empty?
|
210
284
|
count = 0
|
@@ -229,7 +303,7 @@ class Cmd_runfuzz < Command
|
|
229
303
|
end
|
230
304
|
end
|
231
305
|
|
232
|
-
|
306
|
+
log "Ending fault countfor #{name}: #{count}, confidence_level 5: #{confidence_level_5}"+
|
233
307
|
", confidence_level 4: #{confidence_level_4}, confidence_level 3: #{confidence_level_3}"+
|
234
308
|
", confidence_level 2: #{confidence_level_2}, confidence_level 1: #{confidence_level_1}"
|
235
309
|
end
|
@@ -244,6 +318,18 @@ private
|
|
244
318
|
|
245
319
|
def setup argv
|
246
320
|
parse_cli argv
|
321
|
+
@@output_dir = @hash['output_dir']
|
322
|
+
if @@output_dir != nil
|
323
|
+
@@output_log = "#{@@output_dir}/cmd_runanalysis_#{Time.now.localtime}.log"
|
324
|
+
begin
|
325
|
+
Dir.mkdir(@@output_dir)
|
326
|
+
rescue
|
327
|
+
msg "Directory already exists", Logger::DEBUG
|
328
|
+
end
|
329
|
+
else
|
330
|
+
@@output_dir = ""
|
331
|
+
@@output_log = "cmd_runanalysis_#{Time.now.localtime}.log"
|
332
|
+
end
|
247
333
|
@host = (@@mu_ip.nil?) ? "127.0.0.1" : @@mu_ip
|
248
334
|
@username = (@@mu_admin_user.nil?) ? "admin" : @@mu_admin_user
|
249
335
|
@password = (@@mu_admin_pass.nil?) ? "admin" : @@mu_admin_pass
|
@@ -251,7 +337,8 @@ private
|
|
251
337
|
@params = nil
|
252
338
|
@expected_error = nil
|
253
339
|
@api = Muapi.new(@host, @username, @password)
|
254
|
-
|
340
|
+
@http = Mu::HttpHelper.new(@host, @username, @password, @docroot)
|
341
|
+
log "Created API object to :#{@host}", Logger::DEBUG
|
255
342
|
end
|
256
343
|
|
257
344
|
def parse_cli argv
|
@@ -261,9 +348,13 @@ private
|
|
261
348
|
args << argv.shift if argv.first[0,1] != '-'
|
262
349
|
|
263
350
|
k = argv.shift
|
351
|
+
|
352
|
+
#@hash['verifyonly'] = false
|
353
|
+
#@hash['verify'] = false
|
264
354
|
|
265
355
|
if [ '-a', '--archive' ].member? k
|
266
|
-
@hash['archive'] =
|
356
|
+
@hash['archive'] = true
|
357
|
+
@hash['archive_options'] = shift(k, argv)
|
267
358
|
next
|
268
359
|
end
|
269
360
|
|
@@ -282,6 +373,11 @@ private
|
|
282
373
|
exit
|
283
374
|
end
|
284
375
|
|
376
|
+
if [ '-H', '--hosts' ].member? k
|
377
|
+
@hash['hosts'] = shift(k, argv)
|
378
|
+
next
|
379
|
+
end
|
380
|
+
|
285
381
|
if [ '-i', '--interval' ].member? k
|
286
382
|
@hash['interval'] = shift(k, argv)
|
287
383
|
next
|
@@ -303,7 +399,7 @@ private
|
|
303
399
|
end
|
304
400
|
|
305
401
|
if [ '-o', '--output' ].member? k
|
306
|
-
|
402
|
+
@hash['output_dir'] = shift(k, argv)
|
307
403
|
next
|
308
404
|
end
|
309
405
|
|
@@ -326,7 +422,18 @@ private
|
|
326
422
|
$log.level = Logger::DEBUG
|
327
423
|
next
|
328
424
|
end
|
329
|
-
|
425
|
+
|
426
|
+
if [ '-z', '--verify' ].member? k
|
427
|
+
@hash['verify'] = true
|
428
|
+
next
|
429
|
+
end
|
430
|
+
|
431
|
+
if [ '-Z', '--verifyonly' ].member? k
|
432
|
+
@hash['verifyonly'] = true
|
433
|
+
next
|
434
|
+
end
|
435
|
+
|
436
|
+
log "Unknown argument #{k}"
|
330
437
|
help
|
331
438
|
exit
|
332
439
|
|
@@ -341,23 +448,48 @@ private
|
|
341
448
|
{ :short => '-d', :long => '--dir', :value => '<string>', :help => 'directory containing the scenario files' },
|
342
449
|
{ :short => '-f', :long => '--force', :value => '<integer>', :help => 'force resume on pause after time elapse in min' },
|
343
450
|
{ :short => '-h', :long => '--help', :value => '', :help => 'help on command line options' },
|
451
|
+
{ :short => '-H', :long => '--hosts', :value => '<string>', :help => 'list of hosts: host_0:a1:HOST_V4,host_1:a2:HOST_V4 or src:a1:IF_V6_LOCAL,dst:my_host_name:HOST_MAC,src_proxy:a1:HOST_V4,dst_proxy:a1:HOST_V4' },
|
344
452
|
{ :short => '-i', :long => '--interval', :value => '<integer>', :help => 'execute fault status update at intervalin seconds. minimum = 5' },
|
345
453
|
{ :short => '-m', :long => '--mu_string', :value => '<string>', :help => 'user, password, mu_ip in the form of admin:admin@10.9.8.7' },
|
346
|
-
{ :short => '-o', :long => '--output', :value => '<string>', :help => 'output
|
454
|
+
{ :short => '-o', :long => '--output', :value => '<string>', :help => 'save all output to this directory or path location' },
|
347
455
|
{ :short => '-p', :long => '--prepend', :value => '<string>', :help => 'prepend test name with <string>' },
|
348
|
-
{ :short => '-t', :long => '--template', :value => '', :help => 'the template file to run' },
|
456
|
+
{ :short => '-t', :long => '--template', :value => '<string>', :help => 'the template file to run' },
|
349
457
|
{ :short => '-u', :long => '--uuid', :value => '<string>', :help => 'comma seperated uuid list of template uuids' },
|
350
|
-
{ :short => '-v', :long => '--verbose', :value => '', :help => 'set Logger::DEBUG level' }
|
458
|
+
{ :short => '-v', :long => '--verbose', :value => '', :help => 'set Logger::DEBUG level' },
|
459
|
+
{ :short => '-z', :long => '--verify', :value => '', :help => 'test if instrumentation is sucessfull' },
|
460
|
+
{ :short => '-Z', :long => '--verifyonly', :value => '', :help => 'only test instrumentation, run no test cases' }
|
351
461
|
]
|
352
462
|
|
353
463
|
cmds = [
|
354
|
-
"
|
464
|
+
"Run a basic test:",
|
465
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -p <string> -a <string pcaps,evts,samples,logo,audit,sign ",
|
466
|
+
"Run a DoS test seting interfaces:",
|
467
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -p My_Name_To_Append -m admin:admin@192.168.1.253 -H src:a1:IF_V4,dst:MS_SQL:HOST_V4,dos_inst_src:a1:IF_V4,dos_inst_dst:Mu_IP:HOST_V4",
|
468
|
+
"Run a Sceanrio mutation test seting interfaces:",
|
469
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -p My_Name_To_Append -m admin:admin@192.168.1.253 -f 5 -H host_0:a1:IF_V4,host_1:a2:IF_V4,host_2:a2:IF_V4,host_3:a1:IF_V4,host_4:a1:IF_V4",
|
470
|
+
"Run a PVA test seting interfaces:",
|
471
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -p My_Name_To_Append -m admin:admin@192.168.1.253 -f 5 -H src:a1:IF_V4,dst:a2:IF_V4",
|
472
|
+
"Run a Protocal mutation test seting interfaces:",
|
473
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -p My_Name_To_Append -m admin:admin@192.168.1.253 -H src:a1:IF_V4,dst:a2:IF_V4",
|
474
|
+
"Run a protocal mutation test and force verifiaction before saving all output to a specified directory:",
|
475
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -m admin:admin@192.168.1.253 -p My_Name_To_Append -o /path/my-output-dir -z",
|
476
|
+
"Run a test with aditional instrumentation setting all additional instramentation to same source and destination:",
|
477
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -p My_Name_To_Append -m admin:admin@192.168.1.253 -H src:a1:IF_V4,dst:a2:IF_V4,add_inst_src:a1:IF_V4,add_inst_dst:My_Target_Host,HOST_V4",
|
478
|
+
"Run a scenario test with ssh chanels:",
|
479
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -p My_Name_To_Append -m admin:admin@192.168.1.253 -H host_0:a1:IF_V4,host_1:a2:IF_V4,channel:TargetHost,channel_1:TargetHost2",
|
480
|
+
"Run a protocal test setting all monitors to a new target:",
|
481
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -m admin:admin@192.168.1.253 -p My_Name_To_Append -o /path/my-output-dir -H src:a1:IF_V4,dst:a2:IF_V4,monitor:MyHost",
|
482
|
+
"Run a test with actions:",
|
483
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -m admin:admin@192.168.1.253 -p My_Name_To_Append -o /path/my-output-dir -H src:a1:IF_V4,dst:a2:IF_V4,action:MyHost",
|
484
|
+
"Run a test seting restarter host:",
|
485
|
+
" mu cmd_runanalysis:run -t /path/my-template-name.xml -m admin:admin@192.168.1.253 -p My_Name_To_Append -o /path/my-output-dir -H src:a1:IF_V4,dst:a2:IF_V4,restart:MyHost",
|
486
|
+
|
355
487
|
]
|
356
488
|
|
357
489
|
max_long_size = helps.inject(0) { |memo, obj| [ obj[:long].size, memo ].max }
|
358
490
|
max_value_size = helps.inject(0) { |memo, obj| [ obj[:value].size, memo ].max }
|
359
491
|
puts
|
360
|
-
puts "Usage: mu
|
492
|
+
puts "Usage: mu cmd_runanalysis <options>"
|
361
493
|
puts
|
362
494
|
helps.each do |h|
|
363
495
|
puts "%-*s %*s %-*s %s" % [max_long_size, h[:long], 2, h[:short], max_value_size, h[:value], h[:help]]
|
@@ -371,6 +503,347 @@ private
|
|
371
503
|
puts
|
372
504
|
end
|
373
505
|
|
506
|
+
def set_hosts(uuid, hosts)
|
507
|
+
log uuid,Logger::DEBUG
|
508
|
+
template_uuid = ""
|
509
|
+
verify_uuid = ""
|
510
|
+
# 1. get the test template from Mu server. return false if not an analysis template
|
511
|
+
doc = @api.export_by_uuid(uuid)
|
512
|
+
if doc.xpath("//analysis").size <= 0
|
513
|
+
log "Unexpected template type found at uuid: #{uuid}"
|
514
|
+
return "ERROR_SETTING_HOSTS"
|
515
|
+
end
|
516
|
+
|
517
|
+
host_list = hosts.split(",")
|
518
|
+
# 3. replace all host data
|
519
|
+
doc.xpath("//endpoint").each do |endpoint|
|
520
|
+
role = ""
|
521
|
+
host_data = ""
|
522
|
+
children = endpoint.children()
|
523
|
+
children.each do |child|
|
524
|
+
if child.name =~ /role/
|
525
|
+
role = child.content
|
526
|
+
elsif child.name =~ /reference/
|
527
|
+
host_data = child
|
528
|
+
end
|
529
|
+
end
|
530
|
+
#log role, Logger::INFO
|
531
|
+
#log host_data, Logger::INFO
|
532
|
+
host_list.each do |host|
|
533
|
+
if host =~ /#{role}/
|
534
|
+
host_parts = host.split(":")
|
535
|
+
host_data['name'] = host_parts[1]
|
536
|
+
host_data['type'] = host_parts[2]
|
537
|
+
end
|
538
|
+
end
|
539
|
+
log endpoint, Logger::DEBUG
|
540
|
+
end
|
541
|
+
# 4. replace any DoS monitoring host data
|
542
|
+
dst_data = ""
|
543
|
+
src_data = ""
|
544
|
+
begin
|
545
|
+
doc.xpath("//availability_monitor").children().each do |data|
|
546
|
+
if data.name =~ /src/
|
547
|
+
src_data = data
|
548
|
+
elsif data.name =~ /dst/
|
549
|
+
dst_data = data
|
550
|
+
end
|
551
|
+
#log data, Logger::INFO
|
552
|
+
end
|
553
|
+
host_list.each do |host|
|
554
|
+
if host =~ /dos_inst_src/
|
555
|
+
host_parts = host.split(":")
|
556
|
+
src_data['name'] = host_parts[1]
|
557
|
+
src_data['type'] = host_parts[2]
|
558
|
+
elsif host =~ /dos_inst_dst/
|
559
|
+
host_parts = host.split(":")
|
560
|
+
dst_data['name'] = host_parts[1]
|
561
|
+
dst_data['type'] = host_parts[2]
|
562
|
+
end
|
563
|
+
end
|
564
|
+
rescue
|
565
|
+
log "No host settings for DoS Instrumentation", Logger::DEBUG
|
566
|
+
end
|
567
|
+
|
568
|
+
# 5. replace any additional instrumentation host data
|
569
|
+
begin
|
570
|
+
dst_data_name = ""
|
571
|
+
dst_data_type = ""
|
572
|
+
src_data_name = ""
|
573
|
+
src_data_type = ""
|
574
|
+
host_list.each do |host|
|
575
|
+
if host =~ /add_inst_src/
|
576
|
+
host_parts = host.split(":")
|
577
|
+
src_data_name = host_parts[1]
|
578
|
+
src_data_type = host_parts[2]
|
579
|
+
elsif host =~ /add_inst_dst/
|
580
|
+
host_parts = host.split(":")
|
581
|
+
dst_data_name = host_parts[1]
|
582
|
+
dst_data_type = host_parts[2]
|
583
|
+
end
|
584
|
+
end
|
585
|
+
doc.xpath("//additional_instrumentation").children().each do |data|
|
586
|
+
if data.name =~ /dst/
|
587
|
+
data['name'] = dst_data_name
|
588
|
+
data['type'] = dst_data_type
|
589
|
+
elsif data.name =~ /src/
|
590
|
+
data['name'] = src_data_name
|
591
|
+
data['type'] = src_data_type
|
592
|
+
end
|
593
|
+
end
|
594
|
+
rescue
|
595
|
+
log "No host settings for Additional Instrumentation", Logger::DEBUG
|
596
|
+
end
|
597
|
+
|
598
|
+
# 6. replace any channel host data using role channel, channel_1, channel_2
|
599
|
+
begin
|
600
|
+
channel_host = ""
|
601
|
+
channel_type = ""
|
602
|
+
doc.xpath("//channel").each do |channel|
|
603
|
+
role = ""
|
604
|
+
host_data = ""
|
605
|
+
children = channel.children()
|
606
|
+
children.each do |child|
|
607
|
+
begin
|
608
|
+
if child.name =~ /role/
|
609
|
+
role = child.content
|
610
|
+
elsif child.name =~ /reference/
|
611
|
+
host_data = child
|
612
|
+
end
|
613
|
+
end
|
614
|
+
end
|
615
|
+
host_list.each do |host|
|
616
|
+
host_parts = host.split(":")
|
617
|
+
if role =~ /#{host_parts[0]}/
|
618
|
+
host_data['name'] = host_parts[1]
|
619
|
+
#host_data['type'] = host_parts[2]
|
620
|
+
end
|
621
|
+
end
|
622
|
+
log channel, Logger::DEBUG
|
623
|
+
end
|
624
|
+
rescue
|
625
|
+
log "No channel settings found", Logger::ERROR
|
626
|
+
end
|
627
|
+
|
628
|
+
# 7. replace any monitor host data
|
629
|
+
begin
|
630
|
+
mon_host_name = ""
|
631
|
+
#mon_host_type = ""
|
632
|
+
host_list.each do |host|
|
633
|
+
if host =~ /^monitor/
|
634
|
+
host_parts = host.split(":")
|
635
|
+
mon_host_name = host_parts[1]
|
636
|
+
#mon_host_type = host_parts[2]
|
637
|
+
end
|
638
|
+
end
|
639
|
+
doc.xpath("//remote_log_monitor").children().each do |data|
|
640
|
+
if data.name =~ /host/
|
641
|
+
data['name'] = mon_host_name
|
642
|
+
#data['type'] = mon_host_type
|
643
|
+
end
|
644
|
+
end
|
645
|
+
doc.xpath("//snmp_monitor").children().each do |data|
|
646
|
+
if data.name =~ /host/
|
647
|
+
data['name'] = mon_host_name
|
648
|
+
#data['type'] = mon_host_type
|
649
|
+
end
|
650
|
+
end
|
651
|
+
doc.xpath("//console_monitor").children().each do |data|
|
652
|
+
if data.name =~ /host/
|
653
|
+
data['name'] = mon_host_name
|
654
|
+
#data['type'] = mon_host_type
|
655
|
+
end
|
656
|
+
end
|
657
|
+
doc.xpath("//command_monitor").children().each do |data|
|
658
|
+
if data.name =~ /host/
|
659
|
+
data['name'] = mon_host_name
|
660
|
+
#data['type'] = mon_host_type
|
661
|
+
end
|
662
|
+
end
|
663
|
+
rescue
|
664
|
+
log "No monitors found", Logger::DEBUG
|
665
|
+
end
|
666
|
+
|
667
|
+
# 8. replace any action host data. host type is always "HOST"
|
668
|
+
begin
|
669
|
+
action_host_name = ""
|
670
|
+
action_host_type = "HOST"
|
671
|
+
host_list.each do |host|
|
672
|
+
if host =~ /action/
|
673
|
+
host_parts = host.split(":")
|
674
|
+
action_host_name = host_parts[1]
|
675
|
+
#action_host_type = host_parts[2]
|
676
|
+
end
|
677
|
+
end
|
678
|
+
doc.xpath("//syslog_notifier").children().each do |data|
|
679
|
+
if data.name =~ /host/
|
680
|
+
data['name'] = action_host_name
|
681
|
+
#data['type'] = action_host_type
|
682
|
+
end
|
683
|
+
end
|
684
|
+
doc.xpath("//remote_trigger").children().each do |data|
|
685
|
+
if data.name =~ /host/
|
686
|
+
data['name'] = action_host_name
|
687
|
+
#data['type'] = action_host_type
|
688
|
+
end
|
689
|
+
end
|
690
|
+
rescue
|
691
|
+
log "No actions found", Logger::DEBUG
|
692
|
+
end
|
693
|
+
|
694
|
+
# 9. replace any restarter host data
|
695
|
+
begin
|
696
|
+
action_host_name = ""
|
697
|
+
action_host_type = "HOST"
|
698
|
+
host_list.each do |host|
|
699
|
+
if host =~ /restart/
|
700
|
+
host_parts = host.split(":")
|
701
|
+
action_host_name = host_parts[1]
|
702
|
+
end
|
703
|
+
end
|
704
|
+
# service restarter
|
705
|
+
doc.xpath("//service_controller").children().each do |data|
|
706
|
+
if data.name =~ /host/
|
707
|
+
data['name'] = action_host_name
|
708
|
+
#data['type'] = action_host_type
|
709
|
+
end
|
710
|
+
end
|
711
|
+
# proces restarter
|
712
|
+
doc.xpath("//process_controller").children().each do |data|
|
713
|
+
if data.name =~ /host/
|
714
|
+
data['name'] = action_host_name
|
715
|
+
#data['type'] = action_host_type
|
716
|
+
end
|
717
|
+
end
|
718
|
+
# power restarter
|
719
|
+
doc.xpath("//internal_restarter").children().each do |data|
|
720
|
+
if data.name =~ /port/
|
721
|
+
data.content = action_host_name
|
722
|
+
end
|
723
|
+
end
|
724
|
+
rescue
|
725
|
+
log "No restarters found", Logger::DEBUG
|
726
|
+
end
|
727
|
+
|
728
|
+
# 10. upload to mu with new host information overwriting old info.
|
729
|
+
log "Updting test on appliance with host info"
|
730
|
+
template_uuid = ""
|
731
|
+
response = @http.post("/templates/import",doc.to_s())
|
732
|
+
log response, Logger::DEBUG
|
733
|
+
return uuid
|
734
|
+
end
|
735
|
+
|
736
|
+
def verify_analysis(uuid='', name='')
|
737
|
+
log "Verify analysis instrumentation"
|
738
|
+
status = "NOT_RUN"
|
739
|
+
template_uuid = ""
|
740
|
+
verify_uuid = ""
|
741
|
+
# 1. get the test template from Mu server. return false if not an analysis template
|
742
|
+
doc = @api.export_by_uuid(uuid)
|
743
|
+
if doc.xpath("//analysis").size <= 0
|
744
|
+
log "Unexpected template type found at uuid: #{uuid}"
|
745
|
+
return false
|
746
|
+
end
|
747
|
+
|
748
|
+
# 2. replace the exclude/include portions of the template
|
749
|
+
doc.search("//analysis").each do |analysis|
|
750
|
+
template_uuid = new_uuid
|
751
|
+
analysis['uuid'] = "#{template_uuid}"
|
752
|
+
analysis['name'] = "VERIFY "+analysis['name']
|
753
|
+
end
|
754
|
+
doc.xpath("//excludes").each do |excludes|
|
755
|
+
excludes.content = nil
|
756
|
+
end
|
757
|
+
filter = Nokogiri::XML("<include><variant_filter><name>123abc454bca321</name><operator>CONTAINS</operator></variant_filter></include>").xpath("//include")
|
758
|
+
doc.xpath("//includes").each do |includes|
|
759
|
+
includes.content = nil
|
760
|
+
includes.children.first.add_previous_sibling(filter)
|
761
|
+
log doc, Logger::DEBUG
|
762
|
+
end
|
763
|
+
|
764
|
+
# 3. upload to mu with VERIFY name tag.
|
765
|
+
log "Importing 'verify' template"
|
766
|
+
template_uuid = ""
|
767
|
+
response = @http.post("/templates/import",doc.to_s())
|
768
|
+
log response, Logger::DEBUG
|
769
|
+
doc = make_xml(response)
|
770
|
+
name = ""
|
771
|
+
unless doc.xpath("//model_object").empty?
|
772
|
+
doc.xpath("//model_object").each do |node|
|
773
|
+
my_uuid = node.xpath("uuid").text
|
774
|
+
my_name = node.xpath("name").text
|
775
|
+
my_type = node.xpath("type").text
|
776
|
+
if my_type=="Analysis"
|
777
|
+
template_uuid = my_uuid
|
778
|
+
name = my_name
|
779
|
+
end
|
780
|
+
end
|
781
|
+
end
|
782
|
+
|
783
|
+
# 4. run verify and pull status from result
|
784
|
+
verify_uuid = @api.run(template_uuid,URI.encode(name))
|
785
|
+
log "verify_uuid = #{verify_uuid}"
|
786
|
+
run = true
|
787
|
+
while run
|
788
|
+
sleep(10)
|
789
|
+
status = @api.status(verify_uuid)
|
790
|
+
log "verify status = #{status}"
|
791
|
+
if status =~ /ABORTED/ or status =~ /FINISHED/ or status =~ /FAILED/
|
792
|
+
run = false
|
793
|
+
end
|
794
|
+
end
|
795
|
+
|
796
|
+
# 5. delete template and result from Mu
|
797
|
+
response = @api.delete(template_uuid)
|
798
|
+
log response, Logger::DEBUG
|
799
|
+
response = @api.delete(verify_uuid)
|
800
|
+
log response, Logger::DEBUG
|
801
|
+
|
802
|
+
# end of verify process #########################
|
803
|
+
log "Analysis #{name} verify result: #{status}."
|
804
|
+
|
805
|
+
if status=~/FINISHED/
|
806
|
+
return true
|
807
|
+
else
|
808
|
+
return false
|
809
|
+
end
|
810
|
+
return false
|
811
|
+
end
|
812
|
+
|
813
|
+
def new_uuid
|
814
|
+
uuid = ""
|
815
|
+
validChars = ("A".."F").to_a + ("0".."9").to_a
|
816
|
+
length = validChars.size
|
817
|
+
hexCode=""
|
818
|
+
1.upto(8) do |i|
|
819
|
+
hexCode << validChars[rand(length-1)]
|
820
|
+
end
|
821
|
+
uuid = hexCode
|
822
|
+
hexCode=""
|
823
|
+
1.upto(4) do |i|
|
824
|
+
hexCode << validChars[rand(length-1)]
|
825
|
+
end
|
826
|
+
uuid = "#{uuid}-#{hexCode}"
|
827
|
+
hexCode=""
|
828
|
+
1.upto(4) do |i|
|
829
|
+
hexCode << validChars[rand(length-1)]
|
830
|
+
end
|
831
|
+
uuid = "#{uuid}-#{hexCode}"
|
832
|
+
hexCode=""
|
833
|
+
1.upto(4) do |i|
|
834
|
+
hexCode << validChars[rand(length-1)]
|
835
|
+
end
|
836
|
+
uuid = "#{uuid}-#{hexCode}"
|
837
|
+
hexCode=""
|
838
|
+
1.upto(12) do |i|
|
839
|
+
hexCode << validChars[rand(length-1)]
|
840
|
+
end
|
841
|
+
uuid = "#{uuid}-#{hexCode}"
|
842
|
+
uuid = uuid.downcase
|
843
|
+
log "uuid = #{uuid}"
|
844
|
+
return uuid
|
845
|
+
end
|
846
|
+
|
374
847
|
end
|
375
848
|
end # Command
|
376
849
|
end # Mu
|
data/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
VERSION='5.7.
|
1
|
+
VERSION='5.7.40'
|
metadata
CHANGED
@@ -1,90 +1,122 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: mu
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.7.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 5.7.40
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- MuEng
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
dependencies:
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-11-16 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: nokogiri
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.4.4
|
17
22
|
type: :runtime
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
23
29
|
version: 1.4.4
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
30
|
+
- !ruby/object:Gem::Dependency
|
26
31
|
name: rest-client
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.6.1
|
27
38
|
type: :runtime
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
30
|
-
|
31
|
-
|
32
|
-
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
33
45
|
version: 1.6.1
|
34
|
-
|
35
|
-
- !ruby/object:Gem::Dependency
|
46
|
+
- !ruby/object:Gem::Dependency
|
36
47
|
name: mime-types
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.16'
|
37
54
|
type: :runtime
|
38
|
-
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
- !ruby/object:Gem::Dependency
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.16'
|
62
|
+
- !ruby/object:Gem::Dependency
|
46
63
|
name: json
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
47
70
|
type: :runtime
|
48
|
-
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
- !ruby/object:Gem::Dependency
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
56
79
|
name: hexy
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.1.1
|
57
86
|
type: :runtime
|
58
|
-
|
59
|
-
version_requirements: !ruby/object:Gem::Requirement
|
60
|
-
|
61
|
-
|
62
|
-
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
63
93
|
version: 0.1.1
|
64
|
-
|
65
|
-
- !ruby/object:Gem::Dependency
|
94
|
+
- !ruby/object:Gem::Dependency
|
66
95
|
name: uuid
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.0.2
|
67
102
|
type: :runtime
|
68
|
-
|
69
|
-
version_requirements: !ruby/object:Gem::Requirement
|
70
|
-
|
71
|
-
|
72
|
-
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
73
109
|
version: 2.0.2
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
to many of these same libraries
|
79
|
-
email:
|
110
|
+
description: ! "The Mu gem allows users to include Mu libraries within scripts\n that
|
111
|
+
interact with the appliance software. The gem also supplies command line interfaces\n
|
112
|
+
\ to many of these same libraries"
|
113
|
+
email:
|
80
114
|
- support@mudynamics.com
|
81
|
-
executables:
|
115
|
+
executables:
|
82
116
|
- mu
|
83
117
|
extensions: []
|
84
|
-
|
85
118
|
extra_rdoc_files: []
|
86
|
-
|
87
|
-
files:
|
119
|
+
files:
|
88
120
|
- lib/mu/api/ddt.rb
|
89
121
|
- lib/mu/api/homepage.rb
|
90
122
|
- lib/mu/api/muapi.rb
|
@@ -119,33 +151,29 @@ files:
|
|
119
151
|
- version.rb
|
120
152
|
- LICENSE.txt
|
121
153
|
- README.md
|
122
|
-
has_rdoc: true
|
123
154
|
homepage: http://www.spirent.com
|
124
155
|
licenses: []
|
125
|
-
|
126
156
|
post_install_message:
|
127
157
|
rdoc_options: []
|
128
|
-
|
129
|
-
require_paths:
|
158
|
+
require_paths:
|
130
159
|
- lib
|
131
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
132
|
-
|
133
|
-
|
134
|
-
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
135
165
|
version: 1.8.7
|
136
|
-
|
137
|
-
|
138
|
-
requirements:
|
139
|
-
- -
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
version:
|
142
|
-
version:
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
|
+
none: false
|
168
|
+
requirements:
|
169
|
+
- - ! '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
143
172
|
requirements: []
|
144
|
-
|
145
173
|
rubyforge_project:
|
146
|
-
rubygems_version: 1.
|
174
|
+
rubygems_version: 1.8.24
|
147
175
|
signing_key:
|
148
176
|
specification_version: 3
|
149
177
|
summary: Spirent Communications General Purpose Library and Command Line Tool
|
150
178
|
test_files: []
|
151
|
-
|
179
|
+
has_rdoc:
|