class PaloAlto::Helpers::Rest

Public Class Methods

execute(payload, headers: {}) click to toggle source
# File lib/palo_alto.rb, line 148
def self.execute(payload, headers: {})
  retried = false
  # configure options for the request
  options = {}
  options[:host]     = XML.host
  options[:port]     = XML.port
  options[:verify_ssl] = XML.verify_ssl
  options[:payload] = payload
  options[:headers] = headers

  if XML.debug.include?(:sent)
    warn "sent: (#{Time.now}\n#{options.pretty_inspect}\n"
  end

  start_time = Time.now
  text = Helpers::Rest.make_request(options)
  if XML.debug.include?(:statistics)
    warn "Elapsed for API call #{payload[:type]}/#{payload[:action]||'(unknown action)'}: #{Time.now-start_time} seconds"
  end

  if XML.debug.include?(:received)
    warn "received: #{Time.now}\n#{text}\n"
  end

  data = Nokogiri::XML.parse(text)
  unless data.xpath('//response/@status').to_s == 'success'
    if XML.debug.include?(:sent_on_error)
      warn "sent:\n#{options.inspect}\n"
    end
    if XML.debug.include?(:received_on_error)
      warn "received:\n#{text.inspect}\n"
    end
    code = data.at_xpath('//response/@code')&.value.to_i # sometimes there is no code :( e.g. for 'op' errors
    message = data.xpath('/response/msg/line').map(&:text).map(&:strip).join("\n")
    raise_error(code, message)
  end

  return data
end
make_request(opts) click to toggle source
# File lib/palo_alto.rb, line 77
def self.make_request(opts)
  options                            = {}
  options[:verify_ssl]              = OpenSSL::SSL::VERIFY_PEER
  options[:timeout]                  = 60

  headers                  = {}
  headers['User-Agent']    = 'ruby-keystone-client'
  headers['Accept']        = 'application/xml'
  headers['Content-Type'] = 'application/x-www-form-urlencoded'

  # merge in settings from method caller
  options = options.merge(opts)
  options[:headers].merge!(headers)

  thread = Thread.current
  unless thread[:http]
    thread[:http] = Net::HTTP.new(options[:host], options[:port])
    thread[:http].use_ssl = true
    thread[:http].verify_mode = options[:verify_ssl]
    thread[:http].read_timeout = thread[:http].open_timeout = options[:timeout]
    thread[:http].set_debug_output($stdout) if XML.debug.include?(:http)
  end

  thread[:http].start unless thread[:http].started?

  response = thread[:http].post('/api/', URI.encode_www_form(options[:payload]), options[:headers])

  if response.code == '200'
    return response.body
  elsif response.code == '400' or response.code == '403'
    begin
      data = Nokogiri::XML.parse(response.body)
      message = data.xpath('//response/response/msg').text
      code = response.code.to_i
    rescue
      raise ConnectionErrorException, "#{response.code} #{response.message}"
    end
    raise_error(code, message)
  else
    raise ConnectionErrorException, "#{response.code} #{response.message}"
  end
  nil

rescue Net::OpenTimeout, Errno::ECONNREFUSED => e
  raise ConnectionErrorException, e.message
end
raise_error(code, message) click to toggle source
# File lib/palo_alto.rb, line 124
def self.raise_error(code, message)
  error = case code
          when 400 then BadRequestException
          when 403 then ForbiddenException
          when 1 then UnknownCommandException
          when 2..5 then InternalErrorsException
          when 6 then BadXpathException
          when 7 then ObjectNotPresentException
          when 8 then ObjectNotUniqueException
          when 10 then ReferenceCountNotZeroException
          when 0, 11, 21 then InternalErrorException # also if there is no code..
          when 12 then InvalidObjectException
          when 14 then OperationNotPossibleException
          when 15 then OperationDeniedException
          when 16 then UnauthorizedException
          when 17 then InvalidCommandException
          when 18 then MalformedCommandException
          when 19..20 then SuccessException
          when 22 then SessionTimedOutException
          else InternalErrorException
  end
  raise error, message
end