1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-04-01 06:50:25 +03:00

Added support for X509 authorization in econe server.

This commit is contained in:
Ted 2011-09-12 11:06:51 -05:00
parent ac71f33c15
commit aee86437c3
3 changed files with 119 additions and 24 deletions

View File

@ -88,7 +88,12 @@ class CloudServer
# [return] an OpenNebula client session
def one_client_user(name, password)
client = Client.new("dummy:dummy")
client.one_auth = "#{name}:#{password}"
if name=="dummy"
#STDERR.puts "#{password}"
client.one_auth = "#{password}"
else
client.one_auth = "#{name}:#{password}"
end
return client
end
@ -101,7 +106,37 @@ class CloudServer
return @user_pool["USER[NAME=\"#{name}\"]/PASSWORD"]
end
# Gets the username associated with a password
# password:: _String_ the password
# [return] _Hash_ with the username
def get_username(password)
@user_pool.info
#STDERR.puts 'the password is ' + password
#STDERR.puts @user_pool["User[PASSWORD=\"#{password}\"]"]
username = @user_pool["User[PASSWORD=\"#{password}\"]/NAME"]
return username if (username != nil)
# Check if the DN is part of a |-separted multi-DN password
user_elts = Array.new
@user_pool.each {|e| user_elts << e['PASSWORD']}
multiple_users = user_elts.select {|e| e=~ /\|/ }
matched = nil
multiple_users.each do |e|
e.to_s.split('|').each do |w|
if (w == password)
matched=e
break
end
end
break if matched
end
if matched
password = matched.to_s
end
puts("The password is " + password)
return @user_pool["USER[PASSWORD=\"#{password}\"]/NAME"]
end
# Finds out if a port is available on ip
# ip:: _String_ IP address where the port to check is
# port:: _String_ port to find out whether is open

View File

@ -86,34 +86,88 @@ class EC2QueryServer < CloudServer
# params:: of the request
# [return] true if authenticated
def authenticate(params,env)
password = get_user_password(params['AWSAccessKeyId'])
return nil if !password
failed = 'Authentication failed. '
# For https, the web service should be set to include the user cert in the environment.
cert_line = env['HTTP_SSL_CLIENT_CERT']
cert_line = nil if cert_line == '(null)' # For Apache mod_ssl
if cert_line == nil
# Use the secret key for authentication.
password = get_user_password(params['AWSAccessKeyId'])
return nil if !password
signature = case params['SignatureVersion']
when "1" then signature_version_1(params.clone, password)
when "2" then signature_version_2(params,
password,
env,
true,
false)
end
if params['Signature']==signature
return one_client_user(params['AWSAccessKeyId'], password)
else
if params['SignatureVersion']=="2"
signature = signature_version_2(params,
signature = case params['SignatureVersion']
when "1" then signature_version_1(params.clone, password)
when "2" then signature_version_2(params,
password,
env,
false,
true,
false)
if params['Signature']==signature
return one_client_user(params['AWSAccessKeyId'], password)
end
if params['Signature']==signature
return one_client_user(params['AWSAccessKeyId'], password)
else
if params['SignatureVersion']=="2"
signature = signature_version_2(params,
password,
env,
false,
false)
if params['Signature']==signature
return one_client_user(params['AWSAccessKeyId'], password)
end
end
end
end
return nil
return nil
else
# Use the https credentials for authentication
require 'server_auth'
while cert_line
begin
cert_array=cert_line.scan(/([^\s]*)\s/)
cert_array = cert_array[2..-3]
cert_array.unshift('-----BEGIN CERTIFICATE-----')
cert_array.push('-----END CERTIFICATE-----')
cert_pem = cert_array.join("\n")
#cert_pem = cert_line.scan(/(-+BEGIN CERTIFICATE-+\n[^-]*\n-+END CERTIFICATE-+)/)
cert = OpenSSL::X509::Certificate.new(cert_pem)
rescue
raise failed + "Could not create X509 certificate from " + cert_line
end
# Password should be DN with whitespace removed.
subjectname = cert.subject.to_s.delete("\s")
#STDERR.puts 'the cert is' + cert.subject.to_s
begin
username = get_username(subjectname)
rescue
username = nil
end
#STDERR.puts "the username is " + username
break if username
chain_dn = (!chain_dn ? "" : chain_dn) + "\n" + subjectname
chain_index = !chain_index ? 0 : chain_index + 1
cert_line = env["HTTP_SSL_CLIENT_CERT_CHAIN_#{chain_index}"]
cert_line = nil if cert_line == '(null)' # For Apache mod_ssl
end
if !cert_line
raise failed + "Username not found in certificate chain " + chain_dn
end
auth = ServerAuth.new
login = auth.login_token(username, subjectname, 300)
STDERR.puts login
return one_client_user("dummy", login)
end
end

View File

@ -70,7 +70,13 @@ set :port, $econe_server.config[:port]
##############################################################################
before do
@client = $econe_server.authenticate(params,env)
#STDERR.puts Time.now.strftime("%d/%b/%Y %H:%M:%S")
begin
@client = $econe_server.authenticate(params,env)
rescue => e
#STDERR.puts Time.now.strftime("%d/%b/%Y %H:%M:%S") + ' Exception in authentication. ' + e.to_s
@client = nil
end
if @client.nil?
error 400, error_xml("AuthFailure", 0)