Skip to content

Commit

Permalink
Merge pull request gwdg#23 from arax/client-dev
Browse files Browse the repository at this point in the history
X.509 proxy certificate support
  • Loading branch information
ffeldhaus committed Dec 5, 2012
2 parents a86238d + d406486 commit 4a8e6ff
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 5 deletions.
12 changes: 10 additions & 2 deletions Gemfile.lock
Expand Up @@ -14,6 +14,7 @@ GEM
amq-protocol (>= 0.9.4)
eventmachine
antlr3 (1.8.12)
bouncy-castle-java (1.5.0146.1)
builder (3.1.4)
crack (0.3.1)
cucumber (1.2.1)
Expand All @@ -23,20 +24,26 @@ GEM
json (>= 1.4.6)
diff-lcs (1.1.3)
eventmachine (1.0.0)
eventmachine (1.0.0-java)
gherkin (2.11.5)
json (>= 1.4.6)
gherkin (2.11.5-java)
json (>= 1.4.6)
hashie (1.2.0)
highline (1.6.15)
httparty (0.9.0)
multi_json (~> 1.0)
multi_xml
i18n (0.6.1)
jruby-openssl (0.7.7)
bouncy-castle-java (>= 1.5.0146.1)
json (1.7.5)
json (1.7.5-java)
multi_json (1.3.7)
multi_xml (0.5.1)
nokogiri (1.5.5)
nokogiri (1.5.5-java)
rake (0.9.2.2)
redcarpet (2.2.2)
rspec (2.11.0)
rspec-core (~> 2.11.0)
rspec-expectations (~> 2.11.0)
Expand Down Expand Up @@ -67,6 +74,7 @@ GEM
yard (~> 0.7)

PLATFORMS
java
ruby

DEPENDENCIES
Expand All @@ -78,10 +86,10 @@ DEPENDENCIES
highline
httparty
i18n
jruby-openssl
json
nokogiri
rake
redcarpet
rspec
rspec-http
simplecov
Expand Down
20 changes: 19 additions & 1 deletion lib/occi/api/client/client_http.rb
@@ -1,5 +1,7 @@
require 'rubygems'
require 'httparty'
require 'occi/api/client/http/net_http_fix'
require 'occi/api/client/http/httparty_fix'

module Occi
module Api
Expand All @@ -9,6 +11,7 @@ class ClientHttp

# HTTParty for raw HTTP requests
include HTTParty

# TODO: uncomment the following line as JSON is properly implemented in OpenStack
# headers 'Accept' => 'application/occi+json,text/plain;q=0.8,text/occi;q=0.2'
headers 'Accept' => 'text/plain,text/occi;q=0.2'
Expand Down Expand Up @@ -586,14 +589,29 @@ def change_auth(auth_options)
raise ArgumentError, "The file specified in 'user_cert' does not exist!" unless File.exists? @auth_options[:user_cert]

self.class.pem File.read(@auth_options[:user_cert]), @auth_options[:user_cert_password]
self.class.ssl_ca_path @auth_options[:ca_path] unless @auth_options[:ca_path].nil? or @auth_options[:ca_path].empty?
self.class.ssl_ca_path @auth_options[:ca_path] unless @auth_options[:ca_path].nil?
self.class.ssl_ca_file @auth_options[:ca_file] unless @auth_options[:ca_file].nil?
self.class.ssl_extra_chain_cert certs_to_file_ary(@auth_options[:proxy_ca]) unless @auth_options[:proxy_ca].nil?
when "none", nil
# do nothing
else
raise ArgumentError, "Unknown AUTH method [#{@auth_options[:type]}]!"
end
end

# Reads X.509 certificates from a file to an array.
#
# @example
# certs_to_file_ary "~/.globus/usercert.pem"
# # => [#<String>, #<String>, ...]
#
# @param [String] Path to a PEM file containing certificates
# @return [Array<String>] An array of read certificates
def certs_to_file_ary(ca_file)
# TODO: read and separate multiple certificates
[] << File.read(ca_file)
end

# Performs GET request and parses the responses to collections.
#
# @example
Expand Down
53 changes: 53 additions & 0 deletions lib/occi/api/client/http/httparty_fix.rb
@@ -0,0 +1,53 @@
module HTTParty
class ConnectionAdapter

private

def attach_ssl_certificates(http, options)
if http.use_ssl?
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

# Client certificate authentication
if options[:pem]
http.cert = OpenSSL::X509::Certificate.new(options[:pem])
http.key = OpenSSL::PKey::RSA.new(options[:pem], options[:pem_password])
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
end

# Set chain of client certificates
if options[:ssl_extra_chain_cert]
http.extra_chain_cert = []

options[:ssl_extra_chain_cert].each do |p_ca|
http.extra_chain_cert << OpenSSL::X509::Certificate.new(p_ca)
end
end

# SSL certificate authority file and/or directory
if options[:ssl_ca_file]
http.ca_file = options[:ssl_ca_file]
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
end

if options[:ssl_ca_path]
http.ca_path = options[:ssl_ca_path]
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
end

# This is only Ruby 1.9+
if options[:ssl_version] && http.respond_to?(:ssl_version=)
http.ssl_version = options[:ssl_version]
end
end
end

end

module ClassMethods

def ssl_extra_chain_cert(ary_of_certs)
default_options[:ssl_extra_chain_cert] = ary_of_certs
end

end
end
46 changes: 46 additions & 0 deletions lib/occi/api/client/http/net_http_fix.rb
@@ -0,0 +1,46 @@
##############################################################################
## Net::HTTP hack allowing the use of X.509 proxy certificates.
##############################################################################

# When running Ruby 1.8.x, RUBY_ENGINE is not defined
RUBY_ENGINE = "ruby" unless defined? RUBY_ENGINE

# detect jRuby
if RUBY_ENGINE == 'jruby'
#TODO: add jRuby support, this doesn't work
module Net
class HTTP

SSL_ATTRIBUTES = SSL_ATTRIBUTES.concat %w(extra_chain_cert)

# An Array of certificates that will be sent to the client.
attr_accessor :extra_chain_cert

end
end
else
net_http_fix_rby_ver = RUBY_VERSION.split('.')

# detect old Rubies, tested with 1.8.7-p371
if net_http_fix_rby_ver[1] == "8"
module Net
class HTTP

# An Array of certificates that will be sent to the client.
ssl_context_accessor :extra_chain_cert

end
end
else
module Net
class HTTP

SSL_ATTRIBUTES = SSL_ATTRIBUTES.concat %w(extra_chain_cert)

# An Array of certificates that will be sent to the client.
attr_accessor :extra_chain_cert

end
end
end
end
15 changes: 13 additions & 2 deletions lib/occi/bin/occi_opts.rb
Expand Up @@ -32,6 +32,7 @@ def self.parse(args)
options.auth[:user_cert] = ENV['HOME'] + "/.globus/usercred.pem"
options.auth[:ca_path] = "/etc/grid-security/certificates"
options.auth[:username] = "anonymous"
options.auth[:ca_file] = nil

options.output_format = :plain

Expand Down Expand Up @@ -81,17 +82,27 @@ def self.parse(args)
end

opts.on("-c",
"--ca-path PATH", String, "Path to CA certificates, defaults to '#{options.auth[:ca_path]}'") do |ca_path|
"--ca-path PATH", String, "Path to CA certificates directory, defaults to '#{options.auth[:ca_path]}'") do |ca_path|
options.auth[:ca_path] = ca_path
end

opts.on("-f",
"--ca-file PATH", String, "Path to CA certificates in a file") do |ca_file|
options.auth[:ca_file] = ca_file
end

opts.on("-x",
"--user-cred X509_CREDENTIALS",
"--user-cred PATH",
String,
"Path to user's x509 credentials, defaults to '#{options.auth[:user_cert]}'") do |user_cred|
options.auth[:user_cert] = user_cred
end

opts.on("-X",
"--proxy-ca PATH", String, "Path to a file with GSI proxy's CA certificate(s)") do |proxy_ca|
options.auth[:proxy_ca] = proxy_ca
end

opts.on("-y",
"--media-type MEDIA_TYPE",
MEDIA_TYPES,
Expand Down

0 comments on commit 4a8e6ff

Please sign in to comment.