ytti/oxidized

View on GitHub
lib/oxidized/input/http.rb

Summary

Maintainability
A
35 mins
Test Coverage
module Oxidized
  require "oxidized/input/cli"
  require "net/http"
  require "json"
  require "net/http/digest_auth"

  class HTTP < Input
    include Input::CLI

    def connect(node)
      @node = node
      @secure = false
      @username = nil
      @password = nil
      @headers = {}
      @log = File.open(Oxidized::Config::LOG + "/#{@node.ip}-http", "w") if Oxidized.config.input.debug?
      @node.model.cfg["http"].each { |cb| instance_exec(&cb) }

      return true unless @main_page && defined?(login)

      begin
        require "mechanize"
      rescue LoadError
        raise OxidizedError, "mechanize not found: sudo gem install mechanize"
      end

      @m = Mechanize.new
      url = URI::HTTP.build host: @node.ip, path: @main_page
      @m_page = @m.get(url.to_s)
      login
    end

    def cmd(callback_or_string)
      return cmd_cb callback_or_string if callback_or_string.is_a?(Proc)

      cmd_str callback_or_string
    end

    def cmd_cb(callback)
      instance_exec(&callback)
    end

    def cmd_str(string)
      path = string % { password: @node.auth[:password] }
      get_http path
    end

    private

    def get_http(path)
      schema = @secure ? "https://" : "http://"
      uri = URI("#{schema}#{@node.ip}#{path}")

      Oxidized.logger.debug "Making request to: #{uri}"

      ssl_verify = Oxidized.config.input.http.ssl_verify? ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE

      res = make_request(uri, ssl_verify)

      if res.code == '401' && res['www-authenticate']&.include?('Digest')
        uri.user = @username
        uri.password = @password
        Oxidized.logger.debug "Server requires Digest authentication"
        auth = Net::HTTP::DigestAuth.new.auth_header(uri, res['www-authenticate'], 'GET')

        res = make_request(uri, ssl_verify, 'Authorization' => auth)
      elsif @username && @password
        Oxidized.logger.debug "Falling back to Basic authentication"
        res = make_request(uri, ssl_verify, 'Authorization' => basic_auth_header)
      end

      Oxidized.logger.debug "Response code: #{res.code}"
      res.body
    end

    def make_request(uri, ssl_verify, extra_headers = {})
      Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https", verify_mode: ssl_verify) do |http|
        req = Net::HTTP::Get.new(uri)
        @headers.merge(extra_headers).each { |header, value| req.add_field(header, value) }
        Oxidized.logger.debug "Sending request with headers: #{@headers.merge(extra_headers)}"
        http.request(req)
      end
    end

    def basic_auth_header
      "Basic " + ["#{@username}:#{@password}"].pack('m').delete("\r\n")
    end

    def log(str)
      @log&.write(str)
    end

    def disconnect
      @log.close if Oxidized.config.input.debug?
    end
  end
end