Skip to content

Commit

Permalink
making more headway. requests successfully authenticate
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Ryan committed Jan 8, 2011
0 parents commit beebf13
Show file tree
Hide file tree
Showing 14 changed files with 249 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pkg/*
*.gem
.bundle
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source "http://rubygems.org"

# Specify your gem's dependencies in spice.gemspec
gemspec
29 changes: 29 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
PATH
remote: .
specs:
spice (0.0.1.alpha)
rest-client

GEM
remote: http://rubygems.org/
specs:
diff-lcs (1.1.2)
mime-types (1.16)
rest-client (1.6.1)
mime-types (>= 1.16)
rspec (2.4.0)
rspec-core (~> 2.4.0)
rspec-expectations (~> 2.4.0)
rspec-mocks (~> 2.4.0)
rspec-core (2.4.0)
rspec-expectations (2.4.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.4.0)

PLATFORMS
ruby

DEPENDENCIES
rest-client
rspec (= 2.4.0)
spice!
2 changes: 2 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require 'bundler'
Bundler::GemHelper.install_tasks
11 changes: 11 additions & 0 deletions lib/spice.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'json'

require 'spice/authentication'
require 'spice/connection'
require 'spice/client'
require 'spice/node'
require 'spice/cookbook'

module Spice
# Your code goes here...
end
49 changes: 49 additions & 0 deletions lib/spice/authentication.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require 'openssl'
require 'mixlib/authentication/signedheaderauth'

module Spice
class Authentication
attr_reader :key_file, :client_name, :key, :raw_key

def initialize(client_name=nil, key_file=nil)
@client_name, @key_file = client_name, key_file
load_signing_key if sign_requests?
end

def sign_requests?
!!key_file
end

def signature_headers(request_params={})
request_params = request_params.dup
request_params[:timestamp] = Time.now.utc.iso8601
request_params[:user_id] = client_name
host = request_params.delete(:host) || "localhost"

sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object(request_params)
signed = sign_obj.sign(key).merge({:host => host})
signed.inject({}){|memo, kv| memo["#{kv[0].to_s.upcase}"] = kv[1];memo}
end

private

def load_signing_key
begin
@raw_key = IO.read(key_file).strip
rescue SystemCallError, IOError => e
raise IOError, "Unable to read #{key_file}"
end
assert_valid_key_format!(@raw_key)
@key = OpenSSL::PKey::RSA.new(@raw_key)
end

def assert_valid_key_format!(raw_key)
unless (raw_key =~ /\A-----BEGIN RSA PRIVATE KEY-----$/) &&
(raw_key =~ /^-----END RSA PRIVATE KEY-----\Z/)
msg = "The file #{key_file} does not contain a correctly formatted private key.\n"
msg << "The key file should begin with '-----BEGIN RSA PRIVATE KEY-----' and end with '-----END RSA PRIVATE KEY-----'"
raise ArgumentError, msg
end
end
end
end
12 changes: 12 additions & 0 deletions lib/spice/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Spice
class Client
attr_reader :name
def initialize(name)
@name = name
end

def to_s
name
end
end
end
91 changes: 91 additions & 0 deletions lib/spice/connection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
require 'rest-client'

module Spice
class Connection
attr_reader :auth_credentials
attr_accessor :url, :default_headers

def initialize(url, client_name, key_file, options={})
@url = url
@client_name = client_name
@key_file = key_file
@auth_credentials = Authentication.new(client_name, key_file)
@sign_on_redirect, @sign_request = true, true
@default_headers = options[:headers] || {}
end

def clients
# Client.all
method = :GET
path = "/clients"
response = RestClient::Request.execute(
:method => method,
:url => "#{@url}/#{path}",
:headers => build_headers(method, path)
)
JSON.parse(response).map {|c| Client.new(c[0])}
end

def cookbooks
method = :GET
path = "/cookbooks"
response = RestClient::Request.execute(
:method => method,
:url => "#{@url}/#{path}",
:headers => build_headers(method, path)
)
JSON.parse(response).inject([]) {|r, e| r << Cookbook.new(e[0])}
end

def data
DataBag.all
end

alias :data_bags :data

def environments
# Not yet implemented
end

def nodes
Node.all
# node_hash = self.get_rest("/nodes")
# @nodes ||= node_hash.map {|n| self.get_rest("/nodes/#{n[0]}") }
end

def roles
Role.all
end

def search
end

def sandboxes
end

def sign_requests?
auth_credentials.sign_requests? && @sign_request
end

def authentication_headers(method, path, json_body=nil)
request_params = {
:http_method => method,
:path => path,
:body => json_body,
:host => url
}
request_params[:body] ||= ""
auth_credentials.signature_headers(request_params)
end

def build_headers(method, path, headers={}, json_body=false, raw=false)
headers = @default_headers.merge(headers)
headers['Accept'] = "application/json" unless raw
headers["Content-Type"] = 'application/json' if json_body
headers['Content-Length'] = json_body.bytesize.to_s if json_body
headers.merge!(authentication_headers(method, path, json_body)) if sign_requests?
headers
end

end
end
4 changes: 4 additions & 0 deletions lib/spice/cookbook.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Spice
class Cookbook
end
end
4 changes: 4 additions & 0 deletions lib/spice/data_bag.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Spice
class DataBag
end
end
5 changes: 5 additions & 0 deletions lib/spice/node.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Spice
class Node

end
end
7 changes: 7 additions & 0 deletions lib/spice/resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Spice
class Resource

def connection
@connection ||= Connection.new()
end
end
3 changes: 3 additions & 0 deletions lib/spice/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module Spice
VERSION = "0.0.1.alpha"
end
25 changes: 25 additions & 0 deletions spice.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "spice/version"

Gem::Specification.new do |s|
s.name = "spice"
s.version = Spice::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Dan Ryan"]
s.email = ["hi@iamdanryan.com"]
s.homepage = "http://github.com/danryan/spice"
s.summary = %q{Chef API wrapper}
s.description = %q{A zesty Chef API wrapper}

s.rubyforge_project = "spice"

s.add_dependency "rest-client"
s.add_dependency "mixlib-authentication"
s.add_development_dependency "rspec", "2.4.0"

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
end

0 comments on commit beebf13

Please sign in to comment.