1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-21 14:50:08 +03:00

feature #754: Added a server based authentication using x509 certificates

This commit is contained in:
Ruben S. Montero 2011-08-25 17:10:17 +02:00
parent 50de4242d4
commit 84b3ff38af

View File

@ -0,0 +1,124 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'openssl'
require 'base64'
require 'fileutils'
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
ETC_LOCATION="/etc/one/"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
ETC_LOCATION=ONE_LOCATION+"/etc/"
end
$: << RUBY_LIB_LOCATION
require 'x509_auth'
# Server authentication class. This authmethod can be used by opennebula services
# to let access authenticated users by other means. It is based on x509 server
# certificates
class ServerAuth < X509Auth
###########################################################################
#Constants with paths to relevant files and defaults
###########################################################################
if !ENV["ONE_LOCATION"]
ETC_LOCATION = "/etc/one"
else
ETC_LOCATION = ONE_LOCATION + "/etc"
end
SERVER_AUTH_CONF_PATH = ETC_LOCATION + "/auth/server_auth.conf"
DEFAULT_CERTS_PATH = {
:one_cert => ETC_LOCATION + "/auth/cert.pem",
:one_key => ETC_LOCATION + "/auth/key.pem",
:ca_dir => ETC_LOCATION + "/auth/certificates",
}
###########################################################################
def initialize()
@options = DEFAULT_CERTS_PATH
if File.readable?(SERVER_AUTH_CONF_PATH)
config = File.read(SERVER_AUTH_CONF_PATH)
@options.merge!(YAML::load(config))
end
begin
certs = Array.new
certs[0] = File.read(@options[:host_cert])
key = File.read(@options[:host_key])
super(:certs_pem => certs,
:key_pem => key,
:ca_dir => @options[:ca_dir])
rescue
raise
end
end
# Generates a login token in the form:
# user_name:x509:user_name:time_expires:cert_chain
# - user_name:time_expires is encrypted with the user certificate
# - user_name:time_expires:cert_chain is base64 encoded
def login_token(user, user_dn, expire)
expires = Time.now.to_i+expire
token_txt = "#{user}:#{user_dn}:#{expires}"
token = encrypt(token_txt)
token64 = Base64::encode64(token).strip.delete("\n")
login_out = "#{user}:server:#{token64}"
login_out
end
###########################################################################
# Server side
###########################################################################
# auth method for auth_mad
def authenticate(user, pass, signed_text)
begin
# Decryption demonstrates that the user posessed the private key.
_user, user_dn, expires = decrypt(signed_text).split(':')
return "User name missmatch" if user != _user
return "login token expired" if Time.now.to_i >= expires.to_i
# Check an explicitly-specified DN such as for a host-signed login
if !pass.split('|').include?(cert.subject.to_s.delete("\s"))
return "Certificate subject missmatch"
end
validate
return true
rescue => e
return e.message
end
end
end