mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-22 18:50:08 +03:00
M : #~: fix get JWT fireedge with 2fa (#1114)
Signed-off-by: Jorge Lobo <jlobo@opennebula.io> Co-authored-by: Jorge Lobo <jlobo@opennebula.systems>
This commit is contained in:
parent
5a013ee2be
commit
0497d2936e
@ -15,15 +15,15 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function(require) {
|
||||
require('../bower_components/jquery/dist/jquery.min');
|
||||
var OpenNebulaAuth = require('opennebula/auth');
|
||||
var WebAuthnJSON = require('../bower_components/webauthn-json/dist/index');
|
||||
require("../bower_components/jquery/dist/jquery.min");
|
||||
var OpenNebulaAuth = require("opennebula/auth");
|
||||
var WebAuthnJSON = require("../bower_components/webauthn-json/dist/index");
|
||||
|
||||
var showErrorAuth = false;
|
||||
var uid;
|
||||
|
||||
|
||||
var textOpenNebulaNotRunning = "OpenNebula is not running or there was a server exception. Please check the server logs.";
|
||||
var textInvalidUserorPassword = "Invalid username or password";
|
||||
var textInvalidUserorPassword = "Invalid username or password";
|
||||
var textNoAnswerFromServer = "No answer from server. Is it running?";
|
||||
var textTwoFactorTokenInvalid = "Invalid second factor authentication";
|
||||
var idElementTwoFactor = "#two_factor_auth_token";
|
||||
@ -59,11 +59,11 @@ define(function(require) {
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
if (!response) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
if (!navigator.credentials) {
|
||||
$("#webauthn_login_div").hide();
|
||||
console.warn('WebAuthn functionality unavailable. Ask your cloud administrator to enable TLS.');
|
||||
console.warn("WebAuthn functionality unavailable. Ask your cloud administrator to enable TLS.");
|
||||
}
|
||||
$("#webauthn_login_btn").click(function () {
|
||||
WebAuthnJSON.get({ "publicKey": response }).then(authenticate)
|
||||
@ -71,13 +71,13 @@ define(function(require) {
|
||||
$("#error_message").text(e.message);
|
||||
$("#error_box").fadeIn("slow");
|
||||
$("#login_spinner").hide();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
error: function (response) {
|
||||
if (response.status == 501) {
|
||||
$("#webauthn_login_div").hide();
|
||||
console.warn('WebAuthn functionality unavailable. Ask your cloud administrator to upgrade the Ruby version.');
|
||||
console.warn("WebAuthn functionality unavailable. Ask your cloud administrator to upgrade the Ruby version.");
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -116,13 +116,13 @@ define(function(require) {
|
||||
var error_callback;
|
||||
if (publicKeyCredential == undefined) {
|
||||
two_factor_auth_token = $("#two_factor_auth_token").val();
|
||||
error_callback = auth_error
|
||||
error_callback = auth_error;
|
||||
} else {
|
||||
two_factor_auth_token = JSON.stringify(publicKeyCredential);
|
||||
error_callback = function(req, error) {
|
||||
auth_error(req, error);
|
||||
prepareWebAuthn(uid);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$("#error_box").fadeOut("slow");
|
||||
@ -144,7 +144,7 @@ define(function(require) {
|
||||
// Returns the version of Internet Explorer or a -1
|
||||
// (indicating the use of another browser).
|
||||
var rv = -1; // Return value assumes failure.
|
||||
if (navigator.appName == 'Microsoft Internet Explorer') {
|
||||
if (navigator.appName == "Microsoft Internet Explorer") {
|
||||
var ua = navigator.userAgent;
|
||||
var re = new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");
|
||||
if (re.exec(ua) != null)
|
||||
@ -161,19 +161,19 @@ define(function(require) {
|
||||
Please upgrade or use Firefox or Chrome for full compatibility." :
|
||||
"OpenNebula Sunstone is best seen with Chrome or Firefox";
|
||||
$("#error_box").text(msg);
|
||||
$("#error_box").fadeIn('slow');
|
||||
$("#error_box").fadeIn("slow");
|
||||
}
|
||||
}
|
||||
|
||||
function limitToken(){
|
||||
$(idElementTwoFactor).off('input').on('input', function() {
|
||||
$(idElementTwoFactor).off("input").on("input", function() {
|
||||
var element = $(this);
|
||||
if(element.attr("maxlength") && element.attr("maxlength") > 0){
|
||||
var value = element.val().replace(/[^0-9.]/g, '')
|
||||
var value = element.val().replace(/[^0-9.]/g, "");
|
||||
if (value.length > element.attr("maxlength")){
|
||||
element.val(value.substr(0,15))
|
||||
element.val(value.substr(0,15));
|
||||
}else{
|
||||
element.val(value)
|
||||
element.val(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -195,9 +195,9 @@ define(function(require) {
|
||||
|
||||
//compact login elements according to screen height
|
||||
if (screen.height <= 600) {
|
||||
$('div#logo_sunstone').css("top", "15px");
|
||||
$('div#login').css("top", "10px");
|
||||
$('.error_message').css("top", "10px");
|
||||
$("div#logo_sunstone").css("top", "15px");
|
||||
$("div#login").css("top", "10px");
|
||||
$(".error_message").css("top", "10px");
|
||||
};
|
||||
|
||||
$("input#username.box").focus();
|
||||
|
@ -91,16 +91,16 @@ define(function (require) {
|
||||
var error_function = function(error, request=null, notify=true){
|
||||
if (notify)
|
||||
Notifier.onError(request, {error:{ message: "FireEdge public endpoint is not working, please contact your cloud administrator"}});
|
||||
|
||||
|
||||
sunstone_fireedge_active = false;
|
||||
|
||||
if (typeof error === "function")
|
||||
error();
|
||||
}
|
||||
};
|
||||
|
||||
var _check_fireedge_public_url = function (success, aux, error) {
|
||||
var regex = /^(http(s)?:\/\/)(www\.)?[a-z,0-9]+([\-\.]{1}[a-z,0-9]+)*(:[0-9]{1,5})?(\/.*)?$/gm
|
||||
var valid_endpoint = Boolean(fireedge_endpoint.match(regex))
|
||||
var regex = /^(http(s)?:\/\/)(www\.)?[a-z,0-9]+([\-\.]{1}[a-z,0-9]+)*(:[0-9]{1,5})?(\/.*)?$/gm;
|
||||
var valid_endpoint = Boolean(fireedge_endpoint.match(regex));
|
||||
|
||||
if (fireedge_endpoint && valid_endpoint){
|
||||
$.ajax({
|
||||
|
@ -344,7 +344,7 @@ define(function(require) {
|
||||
if (defaults[key] != undefined){
|
||||
attrs.initial = opts.defaults[key];
|
||||
}
|
||||
if(checkItemInArray(attrs, store, 'name')){
|
||||
if(checkItemInArray(attrs, store, "name")){
|
||||
store.push(attrs);
|
||||
}
|
||||
});
|
||||
@ -371,10 +371,10 @@ define(function(require) {
|
||||
var separator = $("<div>");
|
||||
$.each(network_attrs, function(index, vnet_attr) {
|
||||
// 0 type; 1 id; 3(optional) extra
|
||||
var info = vnet_attr.initial.split(":")
|
||||
var info = vnet_attr.initial.split(":");
|
||||
var type = info[0];
|
||||
var id = info[1];
|
||||
var extra = info.slice(2).join('');
|
||||
var extra = info.slice(2).join("");
|
||||
|
||||
var unique_id = "vnet_user_input_" + UniqueId.id();
|
||||
if(type === "reserve_from" || type === "id") {
|
||||
@ -393,10 +393,10 @@ define(function(require) {
|
||||
$("<div>",{class:"columns small-12"}).append(
|
||||
$("<select>",{
|
||||
class: "changePlaceDatatable",
|
||||
wizard_field: 'type_'+vnet_attr.name,
|
||||
'data-nametable': vnet_attr.name,
|
||||
'data-idtable': unique_id,
|
||||
'data-id': index
|
||||
wizard_field: "type_"+vnet_attr.name,
|
||||
"data-nametable": vnet_attr.name,
|
||||
"data-idtable": unique_id,
|
||||
"data-id": index
|
||||
}).append(
|
||||
$("<option>",{ value: "id" }).text(Locale.tr("Existing")
|
||||
).add(
|
||||
@ -426,24 +426,24 @@ define(function(require) {
|
||||
table.idInput().attr("wizard_field", vnet_attr.name).attr("required", "");
|
||||
|
||||
// Fill type, id of vnet/vnet-template and extra
|
||||
$(".changePlaceDatatable[data-id="+index+"]").val(type)
|
||||
table.selectResourceTableSelect({ 'ids': String(id) })
|
||||
$(".changePlaceDatatable[data-id="+index+"]").val(type);
|
||||
table.selectResourceTableSelect({ "ids": String(id) });
|
||||
if (type === "template_id" || type === "reserve_from") {
|
||||
$("#placeDatatable_"+index).append(
|
||||
$("<div/>",{'class': "row addExtra_"+id}).append(
|
||||
$("<div/>",{'class': "columns small-12"}).append(
|
||||
$("<div/>",{"class": "row addExtra_"+id}).append(
|
||||
$("<div/>",{"class": "columns small-12"}).append(
|
||||
$("<label/>").text(Locale.tr("Extra")).add(
|
||||
$("<input/>",{
|
||||
'wizard_field': "extra_"+vnet_attr.name,
|
||||
'type': "text",
|
||||
'name': "extra",
|
||||
'id': "extra",
|
||||
'placeholder': Locale.tr("Extra")
|
||||
"wizard_field": "extra_"+vnet_attr.name,
|
||||
"type": "text",
|
||||
"name": "extra",
|
||||
"id": "extra",
|
||||
"placeholder": Locale.tr("Extra")
|
||||
}).val(extra)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
if(opts && opts.select_networks){
|
||||
@ -551,7 +551,7 @@ define(function(require) {
|
||||
|
||||
//render Vmgroups_attr_values
|
||||
if (vmgroups_attrs.length > 0 && opts.role) {
|
||||
var options = '<option value="">'+Locale.tr("Without VM Group")+'</option>';
|
||||
var options = "<option value=\"\">"+Locale.tr("Without VM Group")+"</option>";
|
||||
vmgroups_attrs.map(function(vmgroup){
|
||||
if(
|
||||
vmgroup &&
|
||||
@ -561,7 +561,7 @@ define(function(require) {
|
||||
vmgroup.VM_GROUP.TEMPLATE
|
||||
){
|
||||
vmGroupDescription = vmgroup.VM_GROUP.TEMPLATE.DESCRIPTION? "("+vmgroup.VM_GROUP.TEMPLATE.DESCRIPTION+")": "";
|
||||
options += "<option value='"+vmgroup.VM_GROUP.ID+"'>"+vmgroup.VM_GROUP.NAME+vmGroupDescription+"</option>"
|
||||
options += "<option value='"+vmgroup.VM_GROUP.ID+"'>"+vmgroup.VM_GROUP.NAME+vmGroupDescription+"</option>";
|
||||
}
|
||||
});
|
||||
|
||||
@ -718,8 +718,8 @@ define(function(require) {
|
||||
if (attr.type == "range"){
|
||||
attr.tick_size = 1024;
|
||||
}
|
||||
var select = '';
|
||||
var selectInput = editUnit? '': 'disabled';
|
||||
var select = "";
|
||||
var selectInput = editUnit? "": "disabled";
|
||||
if(displayUnit){
|
||||
var select = "<select class=\"mb_input_unit\" "+selectInput+">" +
|
||||
"<option value=\"MB\">"+Locale.tr("MB")+"</option>" +
|
||||
@ -733,7 +733,7 @@ define(function(require) {
|
||||
"<div class=\"mb_input input-group-field\">" +
|
||||
_attributeInput(attr) +
|
||||
"</div>"+
|
||||
"<div class=\"input-group-button\">"+
|
||||
"<div class=\"input-group-button\">"+
|
||||
select+
|
||||
"</div>"+
|
||||
"</div>");
|
||||
@ -746,26 +746,27 @@ define(function(require) {
|
||||
var unit = "MB";
|
||||
var valueInMB = 0;
|
||||
var contextElement = $("div.mb_input", context);
|
||||
|
||||
// Fill in the input with your unit the first time
|
||||
$("input, select", contextElement).trigger("input");
|
||||
var element = $("input.uinput-slider-val", contextElement);
|
||||
var value = element.val();
|
||||
var valueInUnit = value;
|
||||
var min = parseInt(element.attr("min"),10);
|
||||
var max = parseInt(element.attr("max"),10);
|
||||
|
||||
if (value == ""){
|
||||
$(".mb_input_unit", context).val("MB").trigger("change");
|
||||
}else{
|
||||
// If you are going to put a new unit you must put it up in the html, here and down in the change
|
||||
if(value / (base**2) >= 1){
|
||||
baseCal = base**2;
|
||||
if(value / (base*base) >= 1){
|
||||
baseCal = base*base;
|
||||
unit = "TB";
|
||||
}else if(value / base >= 1){
|
||||
baseCal = base;
|
||||
unit = "GB";
|
||||
}
|
||||
if (value && value.length > 0) {
|
||||
valueInMB = value
|
||||
valueInMB = value;
|
||||
if(!isNaN(min) && parseInt(min, 10) > valueInMB ){
|
||||
valueInMB = min;
|
||||
}
|
||||
@ -785,11 +786,11 @@ define(function(require) {
|
||||
var valueInUnit = value;
|
||||
var mb_input_unit_val = $(".mb_input_unit :selected", context).val();
|
||||
switch (mb_input_unit_val) {
|
||||
case 'TB':
|
||||
baseCal = base**2;
|
||||
case "TB":
|
||||
baseCal = base*base;
|
||||
unit = "TB";
|
||||
break;
|
||||
case 'GB':
|
||||
case "GB":
|
||||
baseCal = base;
|
||||
unit = "GB";
|
||||
break;
|
||||
@ -836,7 +837,7 @@ define(function(require) {
|
||||
value = TemplateUtils.htmlEncode(attr.initial);
|
||||
}
|
||||
if(attr.visor){
|
||||
clss = "hide"
|
||||
clss = "hide";
|
||||
}
|
||||
switch (attr.type) {
|
||||
case "text64":
|
||||
@ -857,7 +858,7 @@ define(function(require) {
|
||||
input += Locale.tr("NO ") + "<input type='radio' name='bool_" + id + "' value='NO'" + wizard_field + " " + required + "/>";
|
||||
} else if(value == "NO"){
|
||||
input = "<br>" + Locale.tr("YES ") + "<input style='margin-right: 20px' type='radio' name='bool_" + id + "' value='YES'" + wizard_field + " " + required + "/>";
|
||||
input += Locale.tr("NO ") + "<input checked type='radio' name='bool_" + id + "' value='NO'" + wizard_field + " " + required + "/>"
|
||||
input += Locale.tr("NO ") + "<input checked type='radio' name='bool_" + id + "' value='NO'" + wizard_field + " " + required + "/>";
|
||||
} else {
|
||||
input = "<br>" + Locale.tr("YES ") + "<input style='margin-right: 20px' type='radio' name='bool_" + id + "' value='YES'" + wizard_field + " " + required + "/>";
|
||||
input += Locale.tr("NO ") + "<input type='radio' name='bool_" + id + "' value='NO'" + wizard_field + " " + required + "/>";
|
||||
@ -902,7 +903,7 @@ define(function(require) {
|
||||
break;
|
||||
}
|
||||
if(attr.visor){
|
||||
input += '<input type="number" class="visor" value="'+value+'" required>';
|
||||
input += "<input type=\"number\" class=\"visor\" value=\""+value+"\" required>";
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
@ -366,6 +366,30 @@ helpers do
|
||||
}
|
||||
end
|
||||
|
||||
def get_fireedge_token(tfa)
|
||||
response = ""
|
||||
if $conf && $conf[:private_fireedge_endpoint] && !$conf[:private_fireedge_endpoint].empty?
|
||||
begin
|
||||
uri = URI($conf[:private_fireedge_endpoint]+'/fireedge/api/auth')
|
||||
user_pass = Base64.decode64(session[:auth])
|
||||
username = user_pass.split(":")[0]
|
||||
password = user_pass.split(":")[1]
|
||||
params = { :user => username, :token => password }
|
||||
if tfa && !tfa.empty?
|
||||
params[:token2fa] = tfa
|
||||
end
|
||||
fireedge_token = ""
|
||||
res = Net::HTTP.post_form(uri, params)
|
||||
fireedge_token = JSON.parse(res.body)['data']['token'] if res.is_a?(Net::HTTPSuccess)
|
||||
|
||||
response = fireedge_token
|
||||
rescue StandardError => error
|
||||
logger.error { "Cannot connect with fireedge: #{error.message}" }
|
||||
end
|
||||
end
|
||||
return response
|
||||
end
|
||||
|
||||
def build_session
|
||||
begin
|
||||
result = $cloud_auth.auth(request.env, params)
|
||||
@ -391,8 +415,8 @@ helpers do
|
||||
# two factor_auth
|
||||
isHOTPConfigured = (user[TWO_FACTOR_AUTH_SECRET_XPATH] && user[TWO_FACTOR_AUTH_SECRET_XPATH] != "")
|
||||
isWebAuthnConfigured = $conf[:webauthn_avail] && SunstoneWebAuthn.getCredentialIDsForUser(user.id).length > 0
|
||||
two_factor_auth_token = params[:two_factor_auth_token]
|
||||
if isHOTPConfigured || isWebAuthnConfigured
|
||||
two_factor_auth_token = params[:two_factor_auth_token]
|
||||
if !two_factor_auth_token || two_factor_auth_token == ""
|
||||
return [202, { code: "two_factor_auth", uid: user.id }.to_json]
|
||||
end
|
||||
@ -508,6 +532,9 @@ helpers do
|
||||
auth = request.env['HTTP_AUTHORIZATION'].match(/(?<basic>\w+) (?<pass>\w+)/)
|
||||
session[:auth] = auth[:pass]
|
||||
|
||||
#get firedge JWT
|
||||
session[:fireedge_token] = get_fireedge_token(two_factor_auth_token)
|
||||
|
||||
[204, ""]
|
||||
end
|
||||
|
||||
@ -919,24 +946,19 @@ end
|
||||
# GET FireEdge token
|
||||
##############################################################################
|
||||
get '/fireedge' do
|
||||
begin
|
||||
uri = URI($conf[:private_fireedge_endpoint]+'/fireedge/api/auth')
|
||||
user_pass = Base64.decode64(session[:auth])
|
||||
username = user_pass.split(":")[0]
|
||||
password = user_pass.split(":")[1]
|
||||
params = { :user => username, :token => password }
|
||||
|
||||
fireedge_token = ""
|
||||
res = Net::HTTP.post_form(uri, params)
|
||||
fireedge_token = JSON.parse(res.body)['data']['token'] if res.is_a?(Net::HTTPSuccess)
|
||||
if !session[:fireedge_token].empty?
|
||||
response = {:token => session[:fireedge_token]}
|
||||
[200, response.to_json]
|
||||
else
|
||||
fireedge_token = get_fireedge_token("")
|
||||
if !fireedge_token.empty?
|
||||
session[:fireedge_token] = fireedge_token
|
||||
|
||||
response = {:token => fireedge_token}
|
||||
[200, response.to_json]
|
||||
rescue StandardError => error
|
||||
logger.info("FireEdge server is not running. Error: #{error}")
|
||||
response = {:token => session[:fireedge_token]}
|
||||
[200, response.to_json]
|
||||
else
|
||||
response = {:token => ""}
|
||||
[400, response.to_json]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user