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

F #5241: Guacamole SSH authentication with private key (#1320)

(cherry picked from commit b380d157abb0202e755d7f748e16f25c6afdd5ad)
This commit is contained in:
Frederick Borges 2021-06-21 13:03:34 +02:00 committed by Tino Vazquez
parent 81ed84f2b4
commit 6a59839515
6 changed files with 159 additions and 20 deletions

View File

@ -312,7 +312,7 @@ class SunstoneServer < CloudServer
########################################################################
# Guacamole
########################################################################
def startguac(id, type_connection, guac)
def startguac(id, type_connection, guac, client=nil)
resource = retrieve_resource("vm", id)
if OpenNebula.is_error?(resource)
return [404, resource.to_json]
@ -334,7 +334,7 @@ class SunstoneServer < CloudServer
exit -1
end
return guac.proxy(resource, type_connection)
return guac.proxy(resource, type_connection, client)
end
########################################################################

View File

@ -42,7 +42,7 @@ class SunstoneGuac < SunstoneRemoteConnections
super
end
def proxy(vm_resource, type_connection = 'vnc')
def proxy(vm_resource, type_connection = 'vnc', client = nil)
# Check configurations and VM attributes
if !allowed_console_states.include?(vm_resource['LCM_STATE'])
error_message = "Wrong state (#{vm_resource['LCM_STATE']})
@ -66,7 +66,7 @@ class SunstoneGuac < SunstoneRemoteConnections
case type_connection.downcase
when 'vnc' then settings = get_config_vnc(vm_resource)
when 'rdp' then settings = get_config_rdp(vm_resource)
when 'ssh' then settings = get_config_ssh(vm_resource)
when 'ssh' then settings = get_config_ssh(vm_resource, client)
else {
:error => error(400, 'Type connection not supported by Guacamole')
}
@ -157,7 +157,7 @@ class SunstoneGuac < SunstoneRemoteConnections
)
end
def get_config_ssh(vm_resource)
def get_config_ssh(vm_resource, client)
hostname =
vm_resource["TEMPLATE/NIC[SSH='YES'][1]/EXTERNAL_IP"] ||
vm_resource["TEMPLATE/NIC[SSH='YES'][1]/IP"] ||
@ -184,19 +184,47 @@ class SunstoneGuac < SunstoneRemoteConnections
return { :error => error(400, error_message) }
end
hash = {
'hostname' => hostname,
'port' => port || vm_resource['TEMPLATE/CONTEXT/SSH_PORT']
}
if vm_resource['TEMPLATE/CONTEXT/USERNAME']
hash['username'] = vm_resource['TEMPLATE/CONTEXT/USERNAME']
end
if vm_resource['TEMPLATE/CONTEXT/PASSWORD']
hash['password'] = vm_resource['TEMPLATE/CONTEXT/PASSWORD']
end
if vm_resource['TEMPLATE/CONTEXT/SSH_PUBLIC_KEY']
user = User.new_with_id(OpenNebula::User::SELF, client)
rc = user.info
if OpenNebula.is_error?(rc)
error_message = "VMID:#{vmid} user.info error: #{rc.message}"
return { :error => error(400, error_message) }
end
private_key = user['TEMPLATE/SSH_PRIVATE_KEY']
if private_key.nil?
error_message = "SSH_PRIVATE_KEY not present in the USER:#{OpenNebula::User::SELF} TEMPLATE"
return { :error => error(400, error_message) }
end
passphrase = user['TEMPLATE/SSH_PASSPHRASE']
if !passphrase.nil?
hash['passphrase'] = passphrase
end
hash['private-key'] = private_key
end
{
'hostname' => 'localhost',
'port' => '22',
'username' => nil,
'password' => nil
}.merge(
{
'hostname' => hostname,
'port' => port || vm_resource['TEMPLATE/CONTEXT/SSH_PORT'],
'username' => vm_resource['TEMPLATE/CONTEXT/USERNAME'],
'password' => vm_resource['TEMPLATE/CONTEXT/PASSWORD']
}
)
'port' => '22'
}.merge(hash)
end
def encrypt_data(data)

View File

@ -35,7 +35,7 @@ define(function(require) {
var CONFIRM_DIALOG_ID = require('utils/dialogs/generic-confirm/dialogId');
var RESOURCE = "User";
var XML_ROOT = "USER";
var REGEX_HIDDEN_ATTRS = /^(SUNSTONE|SSH_PUBLIC_KEY)$/
var REGEX_HIDDEN_ATTRS = /^(SUNSTONE|SSH_PUBLIC_KEY|SSH_PRIVATE_KEY|SSH_PASSPHRASE)$/
/* CONSTRUCTOR */
@ -165,7 +165,7 @@ define(function(require) {
}
});
// SSH input
// Public SSH input
context.off("click", ".user_ssh_public_key_edit");
context.on("click", ".user_ssh_public_key_edit", function() {
@ -188,6 +188,55 @@ define(function(require) {
$("#user_ssh_public_key_text", context).show();
$("#user_ssh_public_key_textarea", context).hide();
// Private SSH input
context.off("click", ".user_ssh_private_key_edit");
context.on("click", ".user_ssh_private_key_edit", function() {
$("#user_ssh_private_key_text", context).hide();
$("#user_ssh_private_key_textarea", context).show().focus();
});
context.off("change", "#user_ssh_private_key_textarea");
context.on("change", "#user_ssh_private_key_textarea", function() {
var template_str = 'SSH_PRIVATE_KEY = "'+TemplateUtils.escapeDoubleQuotes($(this).val())+'"';
Sunstone.runAction("User.append_template", that.element.ID, template_str);
});
context.off("focusout", "#user_ssh_private_key_textarea");
context.on("focusout", "#user_ssh_private_key_textarea", function() {
$("#user_ssh_private_key_text", context).show();
$("#user_ssh_private_key_textarea", context).hide();
});
$("#user_ssh_private_key_text", context).show();
$("#user_ssh_private_key_textarea", context).hide();
// Private SSH Passphrases input
context.off("click", ".user_ssh_passphrase_edit");
context.on("click", ".user_ssh_passphrase_edit", function() {
$("#user_ssh_passphrase_text", context).hide();
$("#user_ssh_passphrase_textarea", context).show().focus();
});
context.off("change", "#user_ssh_passphrase_textarea");
context.on("change", "#user_ssh_passphrase_textarea", function() {
var template_str = 'SSH_PASSPHRASE = "'+TemplateUtils.escapeDoubleQuotes($(this).val())+'"';
Sunstone.runAction("User.append_template", that.element.ID, template_str);
});
context.off("focusout", "#user_ssh_passphrase_textarea");
context.on("focusout", "#user_ssh_passphrase_textarea", function() {
$("#user_ssh_passphrase_text", context).show();
$("#user_ssh_passphrase_textarea", context).hide();
});
$("#user_ssh_passphrase_text", context).show();
$("#user_ssh_passphrase_textarea", context).hide();
return false;
}
});

View File

@ -98,5 +98,57 @@
</td>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<table class="dataTable" cellpadding="0" cellspacing="0" border="0">
<thead>
<tr>
<th>{{tr "Private SSH Key"}}</th>
<th>
<a class="user_ssh_private_key_edit right" href="#"><i class="fas fa-edit"></i></a>
</th>
</tr>
</thead>
</table>
<td>
<textarea rows="6" type="text" id="user_ssh_private_key_textarea" name="ssh_private_key" hidden>
{{~element.TEMPLATE.SSH_PRIVATE_KEY~}}
</textarea>
<p id="user_ssh_private_key_text" class="ellipsis" name="ssh_private_key">
{{#if element.TEMPLATE.SSH_PRIVATE_KEY}}
{{element.TEMPLATE.SSH_PRIVATE_KEY}}
{{else}}
{{tr "You can provide a Private SSH Key for this User clicking on the edit button"}}
{{/if}}
</p>
</td>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<table class="dataTable" cellpadding="0" cellspacing="0" border="0">
<thead>
<tr>
<th>{{tr "Private SSH Key Passphrase"}}</th>
<th>
<a class="user_ssh_passphrase_edit right" href="#"><i class="fas fa-edit"></i></a>
</th>
</tr>
</thead>
</table>
<td>
<textarea rows="6" type="text" id="user_ssh_passphrase_textarea" name="ssh_passphrase" hidden>
{{~element.TEMPLATE.SSH_PASSPHRASE~}}
</textarea>
<p id="user_ssh_passphrase_text" class="ellipsis" name="ssh_passphrase">
{{#if element.TEMPLATE.SSH_PASSPHRASE}}
{{element.TEMPLATE.SSH_PASSPHRASE}}
{{else}}
{{tr "You can provide a Private SSH Key Passphrase for this User clicking on the edit button"}}
{{/if}}
</p>
</td>
</div>
</div>
</div>
</div>

View File

@ -38,7 +38,7 @@ define(function(require) {
var RESOURCE = "User";
var XML_ROOT = "USER";
var REGEX_HIDDEN_ATTRS = /^(SSH_PUBLIC_KEY|SUNSTONE|FIREEDGE)$/
var REGEX_HIDDEN_ATTRS = /^(|SSH_PUBLIC_KEY|SSH_PRIVATE_KEY|SSH_PASSPHRASE|SUNSTONE|FIREEDGE)$/
/*
CONSTRUCTOR

View File

@ -1194,8 +1194,18 @@ end
post '/vm/:id/guac/:type' do
vm_id = params[:id]
type_connection = params[:type]
user = OpenNebula::User.new_with_id(
OpenNebula::User::SELF,
$cloud_auth.client(session[:user], session[:active_zone_endpoint]))
@SunstoneServer.startguac(vm_id, type_connection, $guac)
rc = user.info
if OpenNebula.is_error?(rc)
logger.error { rc.message }
error 500, ""
end
@SunstoneServer.startguac(vm_id, type_connection, $guac, user)
end
##############################################################################