PageRenderTime 1803ms CodeModel.GetById 3ms RepoModel.GetById 1ms app.codeStats 0ms

/analyzer/automation/Studio_Fx_On_Rails_5.0/lib/mu_api.rb

http://mu-labs.googlecode.com/
Ruby | 329 lines | 273 code | 24 blank | 32 comment | 11 complexity | 87ce5bb61c0d6e5842731d4fc96690c2 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. require 'rubygems'
  2. require 'net/https'
  3. require 'libxml'
  4. require 'uri'
  5. $api_version = '1.0'
  6. # Class for Mu Api commands. UUID and JobId for most calls are remembered
  7. # but can be overridden when needed.
  8. class Mu_Api
  9. include LibXML
  10. attr_accessor :host, :docroot, :posted_uuid, :run_uuid, :job_id, :username, :password, :params, :expected_error
  11. def initialize(host=ENV['MU_IP'], docroot="/api/v3" )
  12. @host = host
  13. @username = (ENV['MU_ADMIN_USER'].nil?) ? "admin" : ENV['MU_ADMIN_USER']
  14. @password = (ENV['MU_ADMIN_PASS'].nil?) ? "admin" : ENV['MU_ADMIN_PASS']
  15. @docroot = docroot
  16. @params = nil
  17. @expected_error = nil
  18. $DEBUG and puts "Created API object to :#{@host}"
  19. end
  20. # send request to api
  21. def request(doc,verbose=false)
  22. uri = URI.parse("https://#{@host}/")
  23. resp = response = "";
  24. http = Net::HTTP.new(uri.host, uri.port)
  25. http.use_ssl = true
  26. escaped = URI.escape(doc)
  27. $DEBUG and puts "DOC: #{@docroot}/#{escaped}"
  28. http.start do |http|
  29. req = Net::HTTP::Get.new("#{@docroot}/#{escaped}", {"User-Agent" => @username})
  30. req.basic_auth(@username, @password)
  31. response = http.request(req)
  32. resp = response.body
  33. end
  34. begin
  35. if (/<.+>/).match(resp)
  36. xmldoc = XML::Document.string(resp)
  37. else
  38. xmldoc = XML::Document.new
  39. xmldoc.root = XML::Node.new('err_node', resp)
  40. end
  41. # a test case may set the expected_error string if it expects
  42. # there to be an error in the http request.
  43. # if there was an expected error, and we find it in the response,
  44. # then set it to the 'found' string (which the test case will check for)
  45. @expected_error = "found expected error" if xmldoc.to_s.include?(@expected_error) unless @expected_error.nil?
  46. rescue SocketError
  47. raise "Host " + @host + " nicht erreichbar"
  48. rescue Exception => e
  49. print "Error parsing XML " + e.to_s
  50. ensure
  51. return xmldoc
  52. end
  53. end
  54. # Post the analysis/template object to the muserver.
  55. def post(doc)
  56. xmldoc = nil
  57. uri = URI.parse("https://#{@host}/")
  58. resp = response = "";
  59. http = Net::HTTP.new(uri.host, uri.port)
  60. http.use_ssl = true
  61. begin
  62. http.start do |http|
  63. req = Net::HTTP::Post.new("#{@docroot}/templates/import", {"User-Agent" => @username})
  64. req.basic_auth(@username, @password)
  65. req.body = doc.to_s
  66. response = http.request(req)
  67. resp = response.body
  68. end
  69. # XML Document
  70. if (/<.+>/).match(resp)
  71. xmldoc = XML::Document.string(resp)
  72. else
  73. xmldoc = XML::Document.new
  74. xmldoc.root = XML::Node.new('err_node', resp)
  75. end
  76. rescue SocketError
  77. raise "Host " + host + " nicht erreichbar"
  78. rescue Exception => e
  79. $DEBUG and puts "error parsing XML " + e.to_s
  80. end
  81. $DEBUG and puts resp
  82. if (xmldoc.nil? || xmldoc.find("//err_node"))
  83. $DEBUG and puts xmldoc
  84. @posted_uuid = nil
  85. end
  86. @posted_uuid = xmldoc.find_first("//uuid").content if xmldoc.find_first("//uuid")
  87. return xmldoc
  88. end
  89. # used by archive(get) to access report.zip, returns the size of the zipfile
  90. def download(doc, filename="tmp.zip")
  91. escaped = URI.escape(doc)
  92. resp = href = "";
  93. http = Net::HTTP.new(@host, 443)
  94. http.use_ssl = true
  95. $DEBUG and puts "DOC: #{@docroot}/#{escaped}"
  96. http.start do |http|
  97. req = Net::HTTP::Get.new("#{@docroot}/#{escaped}", {"User-Agent" => @username})
  98. req.basic_auth(@username, @password)
  99. resp = http.request(req)
  100. if resp.body.include?("Could not download archive")
  101. puts "==> Could not download archive"
  102. return -1
  103. end
  104. open(filename, "wb") { |f|
  105. f.write(resp.body)
  106. }
  107. return File.size(filename)
  108. end
  109. end
  110. # For any of the possible status values, returns a list of analysis
  111. def list_by_status(status)
  112. uuid_list = Array.new()
  113. doc = request("analysis/list?status=#{status}")
  114. unless doc.find_first("//analysis").nil?
  115. doc.find('//analysis').each { |e| uuid_list << e['uuid'] }
  116. end
  117. return uuid_list
  118. end
  119. # Get the status of a particular analysis, reference is the uuid
  120. def status(uuid=@run_uuid)
  121. doc = request("analysis/status?uuid=#{uuid}")
  122. unless doc.find_first("//analysis").nil?
  123. status = doc.find_first("//status").content
  124. return status
  125. end
  126. return doc
  127. end
  128. # Run an analysis, reference is the posted uuid. A name parameter can
  129. # be included so that each successive run of the same uuid yields a
  130. # new name
  131. # ex: run(1234-1234-1234-1234, "new_name")
  132. def run(uuid=@posted_uuid, rename="")
  133. req = "analysis/run?uuid=#{uuid}"
  134. unless rename.empty?
  135. req = "#{req}&rename=#{rename}"
  136. end
  137. doc = request(req)
  138. unless doc.find_first("//analysis").nil?
  139. @run_uuid = doc.find_first("//analysis").attributes['uuid']
  140. return @run_uuid
  141. end
  142. return doc
  143. end
  144. # abort a running analysis. Next queued analysis will start
  145. def stop(uuid=@run_uuid)
  146. doc = request("analysis/stop?uuid=#{uuid}")
  147. unless doc.find_first("//analysis").nil?
  148. status = doc.find_first("//analysis").attributes['status']
  149. return status
  150. end
  151. return false
  152. end
  153. # pause a running analysis. Note that any queued analysis will NOT begin
  154. def pause(uuid=@run_uuid)
  155. doc = request("analysis/pause?uuid=#{uuid}")
  156. unless doc.find_first("//analysis").nil?
  157. status = doc.find_first("//analysis").attributes['status']
  158. return status
  159. end
  160. return false
  161. end
  162. # anti-pause
  163. def resume(uuid=@run_uuid)
  164. doc = request("analysis/resume?uuid=#{uuid}")
  165. unless doc.find_first("//analysis").nil?
  166. status = doc.find_first("//analysis").attributes['status']
  167. return status
  168. end
  169. return false
  170. end
  171. # delete analysis or template of any type
  172. def delete(uuid=@run_uuid)
  173. doc = request("analysis/delete?uuid=#{uuid}")
  174. unless doc.find_first("//analysis").nil?
  175. status = doc.find_first("//analysis").attributes['status']
  176. return status
  177. end
  178. return true
  179. end
  180. # return a list of faults (if any) for the analysis
  181. def get_faults(uuid=@run_uuid)
  182. doc = request("templates/export?uuid=#{uuid}")
  183. unless doc.find_first("//analysis").nil?
  184. faults = request("analysis/getFaultList?uuid=#{uuid}",true)
  185. return faults
  186. end
  187. return "error: no analysis with uuid: #{uuid} found"
  188. end
  189. # return the name of an analysis referenced by uuid
  190. def get_name(uuid=@run_uuid)
  191. doc = request("templates/export?uuid=#{uuid}")
  192. unless doc.find_first("//analysis").nil?
  193. return doc.find_first("//analysis").attributes['name']
  194. end
  195. return
  196. end
  197. # list all templates of type
  198. def list(type="analysis", templates_only='')
  199. case templates_only
  200. when "true"
  201. template_param = "?templatesOnly=true"
  202. when "false"
  203. template_param = "?templatesOnly=false"
  204. else
  205. template_param = ""
  206. end
  207. doc = request("#{type}/list#{template_param}")
  208. return doc
  209. end
  210. # return a list of template names for a Type,
  211. # Type can be any of those returned by "request('tempates/types')"
  212. def list_names(type)
  213. names = Array.new
  214. doc = request("templates/list?type=#{type}")
  215. doc.find("//templates/*").each {|a| names << a['name'] }
  216. return names
  217. end
  218. def export_byname(name)
  219. return request("templates/export?name=#{name}")
  220. end
  221. # archive has a set of three commands that are used to
  222. # generate and download an archive of all data produced by
  223. # a particular analysis
  224. # ex:
  225. # * achive(run)
  226. # * archive(status)
  227. # * archive(get) if archive(status) == "Finished"
  228. def archive(command="run", id=@run_uuid)
  229. case command
  230. when 'run'
  231. request_string = "archive/run?uuid=#{id}"
  232. request_string += @params unless @params.nil?
  233. doc = request(request_string)
  234. unless doc.find_first("//job").nil?
  235. @job_id = doc.find_first("//job").attributes['id']
  236. return @job_id
  237. end
  238. return doc
  239. when 'status'
  240. id = @job_id if id == @run_uuid
  241. $DEBUG and puts id
  242. doc = request("archive/status?jobId=#{id}")
  243. unless doc.find_first("//status").nil?
  244. status = doc.find_first("//status").content
  245. return status
  246. end
  247. return doc
  248. when 'get'
  249. id = @job_id if id == @run_uuid
  250. file_size = download("archive/get?jobId=#{id}","#{id}.zip")
  251. return file_size
  252. end
  253. return false
  254. end
  255. def backup(command="run")
  256. case command
  257. when 'run'
  258. doc = request("backup/run")
  259. unless doc.find_first("//job").nil?
  260. @job_id = doc.find_first("//job").attributes['id']
  261. return @job_id
  262. end
  263. return doc
  264. when 'status'
  265. id = @job_id
  266. $DEBUG and puts id
  267. doc = request("backup/status?jobId=#{id}")
  268. unless doc.find_first("//status").nil?
  269. status = doc.find_first("//status").content
  270. return status
  271. end
  272. return doc
  273. when 'get'
  274. id = @job_id
  275. file_size = download("backup/get?jobId=#{id}","#{id}.dat")
  276. return file_size
  277. end
  278. return false
  279. end
  280. def capture(command='run',port='a1')
  281. case command
  282. when 'run'
  283. doc = request("capture/run?port=#{port}")
  284. unless doc.find_first("//job").nil?
  285. @job_id = doc.find_first("//job").attributes['id']
  286. return @job_id
  287. end
  288. return doc
  289. when 'status'
  290. id = @job_id
  291. $DEBUG and puts id
  292. doc = request("capture/status?jobId=#{id}")
  293. unless doc.find_first("//status").nil?
  294. status = doc.find_first("//status").content
  295. return status
  296. end
  297. return doc
  298. when 'get'
  299. id = @job_id
  300. file_size = download("capture/get?jobId=#{id}","#{id}.pcap")
  301. return file_size
  302. end
  303. return false
  304. end
  305. end