require 'base64' require 'time' require 'digest/sha1' require 'openssl' require 'net/https' require 'json' class Chef attr_accessor :http, :path attr_accessor :client_name, :key_file def initialize(opts={}) server = opts[:server] port = opts.fetch(:port, 443) # They way you had it before would mean that setting it to false # would actually set it to true. something = false || true. See what I # mean? use_ssl = opts.fetch(:use_ssl, true) ssl_insecure = opts[:ssl_insecure] ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER @client_name = opts[:client_name] @key_file = opts[:key_file] @http = Net::HTTP.new(server, port) @http.use_ssl = use_ssl @http.verify_mode = ssl_insecure end def headers body = "" timestamp = Time.now.utc.iso8601 key = OpenSSL::PKey::RSA.new(File.read(key_file)) canonical = "Method:GET\nHashed Path:#{encode(path)}\nX-Ops-Content-Hash:#{encode(body)}\nX-Ops-Timestamp:#{timestamp}\nX-Ops-UserId:#{client_name}" header_hash = { 'Accept' => 'application/json', 'X-Ops-Sign' => 'version=1.0', 'X-Ops-Userid' => client_name, 'X-Ops-Timestamp' => timestamp, 'X-Ops-Content-Hash' => encode(body) } signature = Base64.encode64(key.private_encrypt(canonical)) signature_lines = signature.split(/\n/) signature_lines.each_index do |idx| key = "X-Ops-Authorization-#{idx + 1}" header_hash[key] = signature_lines[idx] end header_hash end def encode(string) ::Base64.encode64(Digest::SHA1.digest(string)).chomp end def get_request(req_path) @path = req_path begin request = Net::HTTP::Get.new(path, headers) response = http.request(request) JSON.parse(response.body).keys rescue OpenSSL::SSL::SSLError => e raise "SSL error: #{e.message}." end end end chef = Chef.new( :server => 'chef.server.com', :client_name => 'client-name', :key_file => '/path/to/your/client-name.pem', :ssl_insecure => true ) print chef.get_request('/environments/_default/nodes')