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

Merge branch 'bug-847' of git@git.opennebula.org:one into bug-847

This commit is contained in:
Daniel 2011-10-25 02:53:38 -07:00
commit 21b3753c41
22 changed files with 644 additions and 161 deletions

View File

@ -177,6 +177,17 @@ private:
int& group_id,
string& uname,
string& gname);
/**
* Function to authenticate internal users using a server driver
*/
bool authenticate_server(User * user,
const string& token,
int& user_id,
int& group_id,
string& uname,
string& gname);
/**
* Function to authenticate external (not known) users

View File

@ -232,7 +232,7 @@ VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/auth/plain \
$VAR_LOCATION/remotes/auth/ssh \
$VAR_LOCATION/remotes/auth/x509 \
$VAR_LOCATION/remotes/auth/server \
$VAR_LOCATION/remotes/auth/server_x509 \
$VAR_LOCATION/remotes/auth/server_cipher \
$VAR_LOCATION/remotes/auth/quota \
$VAR_LOCATION/remotes/auth/dummy"
@ -330,7 +330,7 @@ INSTALL_FILES=(
IM_PROBES_GANGLIA_FILES:$VAR_LOCATION/remotes/im/ganglia.d
AUTH_SSH_FILES:$VAR_LOCATION/remotes/auth/ssh
AUTH_X509_FILES:$VAR_LOCATION/remotes/auth/x509
AUTH_SERVER_FILES:$VAR_LOCATION/remotes/auth/server
AUTH_SERVER_X509_FILES:$VAR_LOCATION/remotes/auth/server_x509
AUTH_SERVER_CIPHER_FILES:$VAR_LOCATION/remotes/auth/server_cipher
AUTH_DUMMY_FILES:$VAR_LOCATION/remotes/auth/dummy
AUTH_PLAIN_FILES:$VAR_LOCATION/remotes/auth/plain
@ -503,7 +503,7 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \
src/tm_mad/TMScript.rb \
src/authm_mad/remotes/ssh/ssh_auth.rb \
src/authm_mad/remotes/quota/quota.rb \
src/authm_mad/remotes/server/server_auth.rb \
src/authm_mad/remotes/server_x509/server_x509_auth.rb \
src/authm_mad/remotes/server_cipher/server_cipher_auth.rb \
src/authm_mad/remotes/x509/x509_auth.rb"
@ -599,7 +599,7 @@ IM_PROBES_GANGLIA_FILES="src/im_mad/remotes/ganglia.d/ganglia_probe"
AUTH_SERVER_CIPHER_FILES="src/authm_mad/remotes/server_cipher/authenticate"
AUTH_SERVER_FILES="src/authm_mad/remotes/server/authenticate"
AUTH_SERVER_X509_FILES="src/authm_mad/remotes/server_x509/authenticate"
AUTH_X509_FILES="src/authm_mad/remotes/x509/authenticate"
@ -726,7 +726,7 @@ HM_ETC_FILES="src/hm_mad/hmrc"
# Auth Manager drivers config. files, to be installed under $ETC_LOCATION/auth
#-------------------------------------------------------------------------------
AUTH_ETC_FILES="src/authm_mad/remotes/server/server_auth.conf \
AUTH_ETC_FILES="src/authm_mad/remotes/server_x509/server_x509_auth.conf \
src/authm_mad/remotes/quota/quota.conf \
src/authm_mad/remotes/x509/x509_auth.conf"

View File

@ -552,12 +552,14 @@ HM_MAD = [
# --authz: authorization module
#
# SESSION_EXPIRATION_TIME: Time in seconds to keep an authenticated token as
# valid. During this time, the driver is not used.
# valid. During this time, the driver is not used. Use 0 to disable session
# caching
#*******************************************************************************
#AUTH_MAD = [
# executable = "one_auth_mad",
# arguments = "--authz quota --authn plain,ssh,x509"
# arguments = "--authn ssh, x509, server_cipher, server_x509"
# arguments = "--authz quota --authn plain,ssh,x509"ssh, x509, server_cipher, server_x509
#]
SESSION_EXPIRATION_TIME = 900
SESSION_EXPIRATION_TIME = 900

View File

@ -38,17 +38,16 @@ secret = ARGV[2] # Base64 encoded secret as obtained from login_token
#OpenNebula.log_debug("Authenticating #{user}, with password #{pass} (#{secret})")
begin
server_auth = ServerCipherAuth.new
rc,user = server_auth.authenticate(user, pass, secret)
server_auth = ServerCipherAuth.new_driver
rc = server_auth.authenticate(user, pass, secret)
rescue => e
OpenNebula.error_message e.message
exit -1
end
if rc == true
puts user
exit 0
else
OpenNebula.error_message user
OpenNebula.error_message rc
exit -1
end

View File

@ -29,63 +29,72 @@ class ServerCipherAuth
###########################################################################
CIPHER = "aes-256-cbc"
EXPIRE = 300
###########################################################################
def initialize(one_auth = nil)
begin
if one_auth
auth = one_auth
elsif ENV["ONE_AUTH"] and !ENV["ONE_AUTH"].empty? and
File.file?(ENV["ONE_AUTH"])
auth = File.read(ENV["ONE_AUTH"])
elsif File.file?(ENV["HOME"]+"/.one/one_auth")
auth = File.read(ENV["HOME"]+"/.one/one_auth")
else
raise "ONE_AUTH file not present"
end
auth.rstrip!
@server_user, passwd = auth.split(':')
@key = Digest::SHA1.hexdigest(passwd)
@cipher = OpenSSL::Cipher::Cipher.new(CIPHER)
rescue
raise
def initialize(srv_user, srv_passwd)
@srv_user = srv_user
@srv_passwd = srv_passwd
if !srv_passwd.empty?
@key = Digest::SHA1.hexdigest(@srv_passwd)
else
@key = ""
end
@cipher = OpenSSL::Cipher::Cipher.new(CIPHER)
end
###########################################################################
# Client side
###########################################################################
# Creates a ServerCipher for client usage
def self.new_client(srv_user, srv_passwd)
self.new(srv_user, srv_passwd)
end
# Generates a login token in the form:
# - server_user:target_user:time_expires
# The token is then encrypted with the contents of one_auth
def login_token(target_user=nil)
target_user ||= @server_user
token_txt = "#{@server_user}:#{target_user}:#{Time.now.to_i + EXPIRE}"
def login_token(expire, target_user=nil)
target_user ||= @srv_user
token_txt = "#{@srv_user}:#{target_user}:#{expire}"
token = encrypt(token_txt)
token64 = Base64::encode64(token).strip.delete("\n")
token = encrypt(token_txt)
token64 = Base64::encode64(token).strip.delete("\n")
return "#{@server_user}:#{token64}"
return "#{@srv_user}:#{target_user}:#{token64}"
end
# Returns a valid password string to create a user using this auth driver
def password
return @srv_passwd
end
###########################################################################
# Server side
# Driver side
###########################################################################
# Creates a ServerCipher for driver usage
def self.new_driver()
self.new("","")
end
# auth method for auth_mad
def authenticate(user, pass, signed_text)
begin
# Decryption demonstrates that the user posessed the private key.
s_user, t_user, expires = decrypt(signed_text,pass).split(':')
return "User name missmatch" if s_user != @server_user
def authenticate(srv_user,srv_pass, signed_text)
begin
@key = srv_pass
s_user, t_user, expires = decrypt(signed_text).split(':')
return "User name missmatch" if s_user != srv_user
return "login token expired" if Time.now.to_i >= expires.to_i
return true, t_user
return true
rescue => e
return false, e.message
return e.message
end
end
@ -101,13 +110,13 @@ class ServerCipherAuth
return rc
end
def decrypt(data,pass)
def decrypt(data)
@cipher.decrypt
@cipher.key = pass
@cipher.key = @key
rc = @cipher.update(Base64::decode64(data))
rc << @cipher.final
return rc
end
end
end

View File

@ -28,7 +28,7 @@ end
$: << RUBY_LIB_LOCATION
require 'server_auth'
require 'server_x509_auth'
require 'scripts_common'
user = ARGV[0] # username as registered in OpenNebula
@ -38,7 +38,7 @@ secret = ARGV[2] # Base64 encoded secret as obtained from login_token
#OpenNebula.log_debug("Authenticating #{user}, with password #{pass} (#{secret})")
begin
server_auth = ServerAuth.new
server_auth = ServerX509Auth.new
dsecret = Base64::decode64(secret)
rc = server_auth.authenticate(user, pass, dsecret)

View File

@ -1,3 +1,7 @@
# User to be used for x509 server authentication
#:srv_user: x509_server
# Path to the certificate used by the OpenNebula Services
# Certificates must be in PEM format

View File

@ -23,12 +23,12 @@ 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
class ServerX509Auth < X509Auth
###########################################################################
#Constants with paths to relevant files and defaults
###########################################################################
SERVER_AUTH_CONF_PATH = ETC_LOCATION + "/auth/server_auth.conf"
SERVER_AUTH_CONF_PATH = ETC_LOCATION + "/auth/server_x509_auth.conf"
SERVER_DEFAULTS = {
:one_cert => ETC_LOCATION + "/auth/cert.pem",
@ -46,51 +46,46 @@ class ServerAuth < X509Auth
certs = [ File.read(@options[:one_cert]) ]
key = File.read(@options[:one_key])
super(:certs_pem => certs,
:key_pem => key)
super(:certs_pem => certs, :key_pem => key)
rescue
raise
end
end
if @options[:srv_user] == nil || @options[:srv_user].empty?
raise "User for x509 server not defined"
end
end
# Generates a login token in the form:
# user_name:server:user_name:user_pass:time_expires
# - user_name:user_pass:time_expires is encrypted with the server certificate
def login_token(user, user_pass, expire)
# - server_user:target_user:time_expires
def login_token(expire, target_user=nil)
target_user ||= @options[:srv_user]
token_txt = "#{@options[:srv_user]}:#{target_user}:#{expire}"
expires = Time.now.to_i+expire
token_txt = "#{user}:#{user_pass}:#{expires}"
token = encrypt(token_txt)
token64 = Base64::encode64(token).strip.delete("\n")
token = encrypt(token_txt)
token64 = Base64::encode64(token).strip.delete("\n")
login_out = "#{user}:#{token64}"
login_out
return "#{@options[:srv_user]}:#{target_user}:#{token64}"
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_pass, expires = decrypt(signed_text).split(':')
return "User name missmatch" if user != _user
def authenticate(server_user, server_pass, signed_text)
begin
s_user, t_user, expires = decrypt(signed_text).split(':')
return "Server password missmatch" if server_pass != password
return "User name missmatch" if ( s_user != server_user ||
s_user != @options[:srv_user] )
return "login token expired" if Time.now.to_i >= expires.to_i
# Check that the signed password matches one for the user.
if !pass.split('|').include?(user_pass)
return "User password missmatch"
end
return true
rescue => e
return e.message
end
end
end
end

View File

@ -26,8 +26,6 @@ require 'fileutils'
class SshAuth
LOGIN_PATH = ENV['HOME']+'/.one/one_ssh'
attr_reader :public_key
# Initialize SshAuth object
#
# @param [Hash] default options for path
@ -91,6 +89,12 @@ class SshAuth
secret_crypted
end
# Returns a valid password string to create a user using this auth driver.
# In this case the ssh public key.
def password
@public_key
end
# Checks the proxy created with the login method
def authenticate(user, token)
begin

View File

@ -79,8 +79,9 @@ class X509Auth
write_login(login_token(user,expire))
end
# Returns the dn of the user certificate
def dn
# Returns a valid password string to create a user using this auth driver.
# In this case the dn of the user certificate.
def password
@cert_chain[0].subject.to_s.delete("\s")
end

View File

@ -37,11 +37,11 @@ class OneUserHelper < OpenNebulaHelper::OneHelper
return -1, "Can not read file: #{arg}"
end
else
if options[:x509]
password = arg.delete("\s")
else
password = arg
end
password = arg
end
if options[:x509]
password.delete!("\s")
end
return 0, password
@ -56,12 +56,10 @@ class OneUserHelper < OpenNebulaHelper::OneHelper
require 'ssh_auth'
begin
sshauth = SshAuth.new(:private_key=>options[:key])
auth = SshAuth.new(:private_key=>options[:key])
rescue Exception => e
return -1, e.message
end
return 0, sshauth.public_key
elsif options[:x509]
options[:cert] ||= ENV['X509_USER_CERT']
@ -72,16 +70,16 @@ class OneUserHelper < OpenNebulaHelper::OneHelper
require 'x509_auth'
begin
cert = [File.read(options[:cert])]
x509auth = X509Auth.new(:certs_pem=>cert)
cert = [File.read(options[:cert])]
auth = X509Auth.new(:certs_pem=>cert)
rescue Exception => e
return -1, e.message
end
return 0, x509auth.dn
else
return -1, "You have to specify an Auth method or define a password"
end
return 0, auth.password
end
def self.login(username, options)

View File

@ -275,7 +275,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
if rc.first == 0
pass = rc[1]
else
exit_with_code *rc
pass = ""
end
end

View File

@ -61,7 +61,7 @@ module X509CloudAuth
cert_line = nil if cert_line == '(null)' # For Apache mod_ssl
# Use the https credentials for authentication
require 'server_auth'
require 'server_x509_auth'
while cert_line
begin
cert_array=cert_line.scan(/([^\s]*)\s/)
@ -98,7 +98,7 @@ module X509CloudAuth
raise msg
end
auth = ServerAuth.new
auth = ServerX509Auth.new
@token = auth.login_token(username, subjectname, 300)
@client = Client.new(@token, @conf[:one_xmlrpc])

View File

@ -151,7 +151,8 @@ public class User extends PoolElement{
* @param client XML-RPC Client.
* @param id The user id (uid) of the target user we want to modify.
* @param auth The new auth driver.
* @param password The new password.
* @param password The new password. If it is an empty string,
* the user password is not changed
* @return If an error occurs the error message contains the reason.
*/
public static OneResponse chauth(Client client,
@ -229,7 +230,8 @@ public class User extends PoolElement{
* Changes the auth driver and the password of the given user
*
* @param auth The new auth driver.
* @param password The new password.
* @param password The new password. If it is an empty string,
* the user password is not changed
* @return If an error occurs the error message contains the reason.
*/
public OneResponse chauth(String auth, String password)
@ -237,6 +239,17 @@ public class User extends PoolElement{
return chauth(client, id, auth, password);
}
/**
* Changes the auth driver of the given user
*
* @param auth The new auth driver.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse chauth(String auth)
{
return chauth(auth, "");
}
/**
* Replaces the user template contents.
*

View File

@ -119,10 +119,11 @@ module OpenNebula
# Changes the auth driver and the password of the given User
#
# @param auth [String] the new auth driver
# @param password [String] the new password
# @param password [String] the new password. If it is an empty string,
# the user password is not changed
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def chauth(auth, password)
def chauth(auth, password="")
return Error.new('ID not defined') if !@pe_id
rc = @client.call(USER_METHODS[:chauth],@pe_id, auth, password)

View File

@ -88,15 +88,18 @@ int UserChangeAuth::user_action(User * user,
string new_auth = xmlrpc_c::value_string(paramList.getString(2));
string new_pass = xmlrpc_c::value_string(paramList.getString(3));
int rc;
int rc = 0;
if (new_auth == UserPool::CORE_AUTH)
if ( !new_pass.empty() )
{
new_pass = SSLTools::sha1_digest(new_pass);
}
if ( new_auth == UserPool::CORE_AUTH)
{
new_pass = SSLTools::sha1_digest(new_pass);
}
// The password may be invalid, try to change it first
rc = user->set_password(new_pass, error_str);
// The password may be invalid, try to change it first
rc = user->set_password(new_pass, error_str);
}
if ( rc == 0 )
{

View File

@ -31,7 +31,7 @@ module OpenNebulaJSON
else
template = template_to_str(vnet_hash)
end
self.allocate(template)
end
@ -46,6 +46,7 @@ module OpenNebulaJSON
when "rmleases" then self.rmleases(action_hash['params'])
when "publish" then self.publish
when "unpublish" then self.unpublish
when "update" then self.update(action_hash['params'])
when "chown" then self.chown(action_hash['params'])
else
error_msg = "#{action_hash['perform']} action not " <<
@ -62,6 +63,10 @@ module OpenNebulaJSON
super(params['ip'])
end
def update(params=Hash.new)
super(params['template_raw'])
end
def chown(params=Hash.new)
super(params['owner_id'].to_i,params['group_id'].to_i)
end

View File

@ -510,7 +510,17 @@ var OpenNebula = {
OpenNebula.Network.resource,
"rmleases",
action_obj);
}
},
"update": function(params){
var action_obj = {"template_raw" : params.data.extra_param };
OpenNebula.Action.simple_action(params,
OpenNebula.Network.resource,
"update",
action_obj);
},
"fetch_template" : function(params){
OpenNebula.Action.show(params,OpenNebula.Network.resource,"template");
},
},
"VM": {

View File

@ -169,6 +169,34 @@ var create_image_tmpl =
</div>\
</div>';
var update_image_tmpl =
'<form action="javascript:alert(\'js error!\');">\
<h3 style="margin-bottom:10px;">Please, choose and modify the image you want to update:</h3>\
<fieldset style="border-top:none;">\
<label for="image_template_update_select">Select an image:</label>\
<select id="image_template_update_select" name="image_template_update_select"></select>\
<div class="clear"></div>\
<div>\
<label for="image_template_update_public">Public:</label>\
<input type="checkbox" name="image_template_update_public" id="image_template_update_public" />\
</div>\
<div>\
<label for="image_template_update_public">Persistent:</label>\
<input type="checkbox" name="image_template_update_persistent" id="image_template_update_persistent" />\
</div>\
<label for="image_template_update_textarea">Template:</label>\
<div class="clear"></div>\
<textarea id="image_template_update_textarea" style="width:100%; height:14em;"></textarea>\
</fieldset>\
<fieldset>\
<div class="form_buttons">\
<button class="button" id="image_template_update_button" value="Image.update_template">\
Update\
</button>\
</div>\
</fieldset>\
</form>';
var images_select = "";
var dataTable_images;
var $create_image_dialog;
@ -228,7 +256,7 @@ var image_actions = {
type: "single",
call: OpenNebula.Image.fetch_template,
callback: function (request,response) {
$('#template_update_dialog #template_update_textarea').val(response.template);
$('#image_template_update_dialog #image_template_update_textarea').val(response.template);
},
error: onError
},
@ -236,14 +264,7 @@ var image_actions = {
"Image.update_dialog" : {
type: "custom",
call: function() {
popUpTemplateUpdateDialog("Image",
makeSelectOptions(dataTable_images,
1,//id_col
4,//name_col
[],
[]
),
getSelectedNodes(dataTable_images));
popUpImageTemplateUpdateDialog();
}
},
@ -450,6 +471,8 @@ function imageElements() {
// Returns an array containing the values of the image_json and ready
// to be inserted in the dataTable
function imageElementArray(image_json){
//Changing this? It may affect to the is_public and is_persistent
//variables in setupImageTemplateUpdateDialog();
var image = image_json.IMAGE;
return [
'<input type="checkbox" id="image_'+image.ID+'" name="selected_items" value="'+image.ID+'"/>',
@ -775,6 +798,127 @@ function popUpCreateImageDialog(){
$create_image_dialog.dialog('open');
}
function setupImageTemplateUpdateDialog(){
//Append to DOM
dialogs_context.append('<div id="image_template_update_dialog" title="Update image template"></div>');
var dialog = $('#image_template_update_dialog',dialogs_context);
//Put HTML in place
dialog.html(update_image_tmpl);
//Convert into jQuery
dialog.dialog({
autoOpen:false,
width:700,
modal:true,
height:480,
resizable:false,
});
$('button',dialog).button();
$('#image_template_update_select',dialog).change(function(){
var id = $(this).val();
if (id && id.length){
var dialog = $('#image_template_update_dialog');
$('#image_template_update_textarea',dialog).val("Loading...");
var data = getElementData(id,"#image",dataTable_images);
var is_public = data[7] == "yes";
var is_persistent = data[8] == "yes";
if (is_public){
$('#image_template_update_public',dialog).attr("checked","checked")
} else {
$('#image_template_update_public',dialog).removeAttr("checked")
}
if (is_persistent){
$('#image_template_update_persistent',dialog).attr("checked","checked")
} else {
$('#image_template_update_persistent',dialog).removeAttr("checked")
}
Sunstone.runAction("Image.fetch_template",id);
} else {
$('#image_template_update_textarea',dialog).val("");
};
});
$('#image_template_update_button',dialog).click(function(){
var dialog = $('#image_template_update_dialog');
var new_template = $('#image_template_update_textarea',dialog).val();
var id = $('#image_template_update_select',dialog).val();
if (!id || !id.length) {
dialog.dialog('close');
return false;
};
var data = getElementData(id,"#image",dataTable_images);
var is_public = data[7] == "yes";
var is_persistent = data[8] == "yes";
var new_public = $('#image_template_update_public:checked',dialog).length;
var new_persistent = $('#image_template_update_persistent:checked',dialog).length;
if (is_public != new_public){
if (new_public) Sunstone.runAction("Image.publish",id);
else Sunstone.runAction("Image.unpublish",id);
};
if (is_persistent != new_persistent){
if (new_persistent) Sunstone.runAction("Image.persistent",id);
else Sunstone.runAction("Image.nonpersistent",id);
};
Sunstone.runAction("Image.update",id,new_template);
dialog.dialog('close');
return false;
});
}
function popUpImageTemplateUpdateDialog(){
var select = makeSelectOptions(dataTable_images,
1,//id_col
4,//name_col
[],
[]
);
var sel_elems = getSelectedNodes(dataTable_images);
var dialog = $('#image_template_update_dialog');
$('#image_template_update_select',dialog).html(select);
$('#image_template_update_textarea',dialog).val("");
$('#image_template_update_public',dialog).removeAttr("checked")
$('#image_template_update_persistent',dialog).removeAttr("checked")
if (sel_elems.length >= 1){ //several items in the list are selected
//grep them
var new_select= sel_elems.length > 1? '<option value="">Please select</option>' : "";
$('option','<select>'+select+'</select>').each(function(){
var val = $(this).val();
if ($.inArray(val,sel_elems) >= 0){
new_select+='<option value="'+val+'">'+$(this).text()+'</option>';
};
});
$('#image_template_update_select',dialog).html(new_select);
if (sel_elems.length == 1) {
$('#image_template_update_select option',dialog).attr("selected","selected");
$('#image_template_update_select',dialog).trigger("change");
}
};
dialog.dialog('open');
return false;
}
// Set the autorefresh interval for the datatable
function setImageAutorefresh() {
setInterval(function(){
@ -811,6 +955,7 @@ $(document).ready(function(){
Sunstone.runAction("Image.list");
setupCreateImageDialog();
setupImageTemplateUpdateDialog();
setupTips($create_image_dialog);
setImageAutorefresh();

View File

@ -135,6 +135,30 @@ var create_vn_tmpl =
</div>\
</div>';
var update_vnet_tmpl =
'<form action="javascript:alert(\'js error!\');">\
<h3 style="margin-bottom:10px;">Please, choose and modify the virtual network you want to update:</h3>\
<fieldset style="border-top:none;">\
<label for="vnet_template_update_select">Select a network:</label>\
<select id="vnet_template_update_select" name="vnet_template_update_select"></select>\
<div class="clear"></div>\
<div>\
<label for="vnet_template_update_public">Public:</label>\
<input type="checkbox" name="vnet_template_update_public" id="vnet_template_update_public" />\
</div>\
<label for="vnet_template_update_textarea">Template:</label>\
<div class="clear"></div>\
<textarea id="vnet_template_update_textarea" style="width:100%; height:14em;"></textarea>\
</fieldset>\
<fieldset>\
<div class="form_buttons">\
<button class="button" id="vnet_template_update_button" value="Network.update_template">\
Update\
</button>\
</div>\
</fieldset>\
</form>';
var vnetworks_select="";
var dataTable_vNetworks;
var $create_vn_dialog;
@ -272,8 +296,34 @@ var vnet_actions = {
elements: vnElements,
error:onError,
notify: true
}
}
},
"Network.fetch_template" : {
type: "single",
call: OpenNebula.Network.fetch_template,
callback: function (request,response) {
$('#vnet_template_update_dialog #vnet_template_update_textarea').val(response.template);
},
error: onError
},
"Network.update_dialog" : {
type: "custom",
call: function() {
popUpVNetTemplateUpdateDialog();
}
},
"Network.update" : {
type: "single",
call: OpenNebula.Network.update,
callback: function() {
notifyMessage("Template updated correctly");
},
error: onError
},
};
var vnet_buttons = {
@ -288,6 +338,12 @@ var vnet_buttons = {
text: "+ New"
},
"Network.update_dialog" : {
type: "action",
text: "Update a template",
alwaysActive: true
},
"Network.publish" : {
type: "action",
text: "Publish"
@ -684,6 +740,109 @@ function popUpCreateVnetDialog() {
$create_vn_dialog.dialog('open');
}
function setupVNetTemplateUpdateDialog(){
//Append to DOM
dialogs_context.append('<div id="vnet_template_update_dialog" title="Update network template"></div>');
var dialog = $('#vnet_template_update_dialog',dialogs_context);
//Put HTML in place
dialog.html(update_vnet_tmpl);
//Convert into jQuery
dialog.dialog({
autoOpen:false,
width:700,
modal:true,
height:480,
resizable:false,
});
$('button',dialog).button();
$('#vnet_template_update_select',dialog).change(function(){
var id = $(this).val();
if (id && id.length){
var dialog = $('#vnet_template_update_dialog');
$('#vnet_template_update_textarea',dialog).val("Loading...");
var data = getElementData(id,"#vnetwork",dataTable_vNetworks);
var is_public = data[7] == "yes";
if (is_public){
$('#vnet_template_update_public',dialog).attr("checked","checked")
} else {
$('#vnet_template_update_public',dialog).removeAttr("checked")
}
Sunstone.runAction("Network.fetch_template",id);
} else {
$('#vnet_template_update_textarea',dialog).val("");
};
});
$('#vnet_template_update_button',dialog).click(function(){
var dialog = $('#vnet_template_update_dialog');
var new_template = $('#vnet_template_update_textarea',dialog).val();
var id = $('#vnet_template_update_select',dialog).val();
if (!id || !id.length) {
dialog.dialog('close');
return false;
};
var data = getElementData(id,"#vnetwork",dataTable_vNetworks);
var is_public = data[7] == "yes";
var new_public = $('#vnet_template_update_public:checked',dialog).length;
if (is_public != new_public){
if (new_public) Sunstone.runAction("Network.publish",id);
else Sunstone.runAction("Network.unpublish",id);
};
Sunstone.runAction("Network.update",id,new_template);
dialog.dialog('close');
return false;
});
};
function popUpVNetTemplateUpdateDialog(){
var select = makeSelectOptions(dataTable_vNetworks,
1,//id_col
4,//name_col
[],
[]
);
var sel_elems = getSelectedNodes(dataTable_vNetworks);
var dialog = $('#vnet_template_update_dialog');
$('#vnet_template_update_select',dialog).html(select);
$('#vnet_template_update_textarea',dialog).val("");
$('#vnet_template_update_public',dialog).removeAttr("checked")
if (sel_elems.length >= 1){ //several items in the list are selected
//grep them
var new_select= sel_elems.length > 1? '<option value="">Please select</option>' : "";
$('option','<select>'+select+'</select>').each(function(){
var val = $(this).val();
if ($.inArray(val,sel_elems) >= 0){
new_select+='<option value="'+val+'">'+$(this).text()+'</option>';
};
});
$('#vnet_template_update_select',dialog).html(new_select);
if (sel_elems.length == 1) {
$('#vnet_template_update_select option',dialog).attr("selected","selected");
$('#vnet_template_update_select',dialog).trigger("change");
}
};
dialog.dialog('open');
return false;
}
function setupAddRemoveLeaseDialog() {
dialogs_context.append('<div title="Lease management" id="lease_vn_dialog"></div>');
$lease_vn_dialog = $('#lease_vn_dialog',dialogs_context)
@ -786,6 +945,7 @@ $(document).ready(function(){
Sunstone.runAction("Network.list");
setupCreateVNetDialog();
setupVNetTemplateUpdateDialog();
setupAddRemoveLeaseDialog();
setVNetAutorefresh();

View File

@ -140,7 +140,7 @@ function tableCheckboxesListener(dataTable){
//listen to changes in the visible inputs
$('tbody input',dataTable).live("change",function(){
var datatable = $(this).parents('table');
recountCheckboxes(dataTable);
recountCheckboxes(datatable);
});
}
@ -163,6 +163,12 @@ function updateSingleElement(element,dataTable,tag){
recountCheckboxes(dataTable);
}
function getElementData(id, resource_tag, dataTable){
var nodes = dataTable.fnGetNodes();
var tr = $(resource_tag+'_'+id,nodes).parents('tr')[0];
return dataTable.fnGetData(tr);
}
// Returns an string in the form key=value key=value ...
// Does not explore objects in depth.
function stringJSON(json){
@ -657,6 +663,12 @@ function setupTemplateUpdateDialog(){
var dialog = $('#template_update_dialog');
var new_template = $('#template_update_textarea',dialog).val();
var id = $('#template_update_select',dialog).val();
if (!id || !id.length) {
dialog.dialog('close');
return false;
};
var resource = $(this).val();
Sunstone.runAction(resource+".update",id,new_template);
dialog.dialog('close');

View File

@ -28,9 +28,10 @@
#include <sys/types.h>
#include <pwd.h>
#include <stdlib.h>
#include <fnmatch.h>
const char * UserPool::CORE_AUTH = "core";
const char * UserPool::SERVER_AUTH = "server";
const char * UserPool::SERVER_AUTH = "server*";
const char * UserPool::PUBLIC_AUTH = "public";
const char * UserPool::DEFAULT_AUTH = "default";
@ -271,7 +272,7 @@ bool UserPool::authenticate_internal(User * user,
{
return true;
}
AuthRequest ar(user_id, group_id);
if ( auth_driver == UserPool::CORE_AUTH )
@ -281,7 +282,7 @@ bool UserPool::authenticate_internal(User * user,
if (!ar.core_authenticate())
{
goto auth_failure;
}
}
}
else if (auth_driver == UserPool::PUBLIC_AUTH )
{
@ -296,52 +297,27 @@ bool UserPool::authenticate_internal(User * user,
ar.wait();
if (ar.result!=true) //User was not authenticated
{
{
goto auth_failure_driver;
}
if (auth_driver == UserPool::SERVER_AUTH)
{
user = get(ar.message,true);
if (user == 0)
{
goto auth_failure_user;
}
user_id = user->oid;
group_id = user->gid;
uname = user->name;
gname = user->gname;
user->unlock();
}
}
}
else
{
goto auth_failure_nodriver;
}
user = get(username, true);
user = get(user_id, true);
if (user != 0)
{
user->set_session(token, _session_expiration_time);
user->unlock();
}
}
return true;
auth_failure_public:
oss << "User: " << username << "attempted a direct authentication.";
NebulaLog::log("AuM",Log::ERROR,oss);
goto auth_failure;
auth_failure_user:
oss << "User: " << ar.message
<< ", does not exist. Returned by server auth.";
oss << "User: " << username << " attempted a direct authentication.";
NebulaLog::log("AuM",Log::ERROR,oss);
goto auth_failure;
@ -366,7 +342,133 @@ auth_failure:
return false;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool UserPool::authenticate_server(User * user,
const string& token,
int& user_id,
int& group_id,
string& uname,
string& gname)
{
bool result = false;
ostringstream oss;
string server_password;
string auth_driver;
string server_username;
string target_username;
string second_token;
Nebula& nd = Nebula::instance();
AuthManager * authm = nd.get_authm();
server_username = user->name;
server_password = user->password;
auth_driver = user->auth_driver;
AuthRequest ar(user->oid, user->gid);
user->unlock();
// token = target_username:second_token
int rc = User::split_secret(token,target_username,second_token);
if ( rc != 0 )
{
goto wrong_server_token;
}
user = get(target_username,true);
if ( user == 0 )
{
goto auth_failure_user;
}
user_id = user->oid;
group_id = user->gid;
uname = user->name;
gname = user->gname;
result = user->valid_session(second_token);
user->unlock();
if (result)
{
return true;
}
if ( authm == 0 )
{
goto auth_failure_nodriver;
}
//Initialize authentication request and call the driver
ar.add_authenticate(auth_driver,
server_username,
server_password,
second_token);
authm->trigger(AuthManager::AUTHENTICATE,&ar);
ar.wait();
if (ar.result!=true) //User was not authenticated
{
goto auth_failure_driver;
}
user = get(user_id, true);
if (user != 0)
{
user->set_session(second_token, _session_expiration_time);
user->unlock();
}
return true;
wrong_server_token:
oss << "Wrong token format";
NebulaLog::log("AuM",Log::ERROR,oss);
goto auth_failure;
auth_failure_user:
oss << "User: " << target_username
<< " does not exist. Returned by server auth";
NebulaLog::log("AuM",Log::ERROR,oss);
goto auth_failure;
auth_failure_driver:
oss << "Auth Error: " << ar.message;
NebulaLog::log("AuM",Log::ERROR,oss);
goto auth_failure;
auth_failure_nodriver:
NebulaLog::log("AuM",Log::ERROR,
"Auth Error: Authentication driver not enabled. "
"Check AUTH_MAD in oned.conf");
auth_failure:
user_id = -1;
group_id = -1;
uname = "";
gname = "";
return false;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -504,7 +606,16 @@ bool UserPool::authenticate(const string& session,
if (user != 0 ) //User known to OpenNebula
{
ar = authenticate_internal(user,token,user_id,group_id,uname,gname);
string driver = user->get_auth_driver();
if ( fnmatch(UserPool::SERVER_AUTH, driver.c_str(), 0) == 0 )
{
ar = authenticate_server(user,token,user_id,group_id,uname,gname);
}
else
{
ar = authenticate_internal(user,token,user_id,group_id,uname,gname);
}
}
else
{