class Inspec::Resources::Elasticsearch
def curl_command_string(username, password, ssl_verify)
def curl_command_string(username, password, ssl_verify) cmd_string = ['curl'] cmd_string << '-k' unless ssl_verify cmd_string << "-H 'Content-Type: application/json'" cmd_string << " -u #{username}:#{password}" unless username.nil? || password.nil? cmd_string << URI.join(url, '_nodes') cmd_string.join(' ') end
def fix_mash_key_collision(data)
Any key that is in conflict will be renamed "es_ORIGINALKEY"
hard-coding a bunch of key renames.
method on a Hashie::Mash instance. This is a crude way of avoiding those warnings without
Hashie::Mash will throw warnings if the Mash contains a key that is the same as a built-in
def fix_mash_key_collision(data) test_mash = Hashie::Mash.new new_data = {} data.each do |key, value| new_key = test_mash.respond_to?(key.to_sym) ? "es_#{key}" : key new_value = value.is_a?(Hash) ? fix_mash_key_collision(value) : value new_data[new_key] = new_value end new_data end
def initialize(opts = {})
def initialize(opts = {}) return skip_resource 'Package `curl` not avaiable on the host' unless inspec.command('curl').exist? @url = opts.fetch(:url, 'http://localhost:9200') username = opts.fetch(:username, nil) password = opts.fetch(:password, nil) ssl_verify = opts.fetch(:ssl_verify, true) cmd = inspec.command(curl_command_string(username, password, ssl_verify)) # after implementation of PR #2235, this begin..rescue won't be necessary. # The checks in verify_curl_success! can raise their own skip message exception. begin verify_curl_success!(cmd) rescue => e return skip_resource e.message end begin content = JSON.parse(cmd.stdout) # after implementation of PR #2235, this can be broken out of the begin..rescue # clause. The checks in verify_json_payload! can raise their own skip message exception. verify_json_payload!(content) rescue JSON::ParserError => e return skip_resource "Couldn't parse the Elasticsearch response: #{e.message}" rescue => e return skip_resource e.message end @nodes = parse_cluster(content) end
def parse_cluster(content)
def parse_cluster(content) return [] unless content['nodes'] nodes = [] content['nodes'].each do |node_id, node_data| node_data = fix_mash_key_collision(node_data) node = Hashie::Mash.new(node_data) node.node_id = node_id node.plugin_list = node.plugins.map(&:name) node.module_list = node.modules.map(&:name) node.cluster_name = node.settings.cluster.name nodes << node end nodes end
def to_s
def to_s "Elasticsearch Cluster #{url}" end
def verify_curl_success!(cmd)
def verify_curl_success!(cmd) # the following lines captures known possible curl command errors and provides compact skip resource messeges if cmd.stderr =~ /Failed to connect/ raise "Connection refused - please check the URL #{url} for accuracy" end if cmd.stderr =~ /Peer's Certificate issuer is not recognized/ raise 'Connection refused - peer certificate issuer is not recognized' end raise "Error fetching Elastcsearch data from curl #{url}: #{cmd.stderr}" unless cmd.exit_status.zero? end
def verify_json_payload!(content)
def verify_json_payload!(content) unless content['error'].nil? raise "#{content['error']['type']}: #{content['error']['reason']}" end raise 'No successful nodes available in cluster' if content['_nodes']['successful'].zero? end