Skip to content

Instantly share code, notes, and snippets.

@jmazzi
Forked from gmcmillan/chef.rb
Created July 27, 2012 03:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jmazzi/3186019 to your computer and use it in GitHub Desktop.
Save jmazzi/3186019 to your computer and use it in GitHub Desktop.
Simple Ruby class for manually querying the Chef REST API (using Net::HTTP instead of Chef's REST resources)
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')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment