diff --git a/src/sunstone/public/app/login.js b/src/sunstone/public/app/login.js index f12f5ca107..36fa9647b3 100644 --- a/src/sunstone/public/app/login.js +++ b/src/sunstone/public/app/login.js @@ -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(); diff --git a/src/sunstone/public/app/utils/fireedge-validator.js b/src/sunstone/public/app/utils/fireedge-validator.js index 477b3d5d6f..22e80138d0 100644 --- a/src/sunstone/public/app/utils/fireedge-validator.js +++ b/src/sunstone/public/app/utils/fireedge-validator.js @@ -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({ diff --git a/src/sunstone/public/app/utils/user-inputs.js b/src/sunstone/public/app/utils/user-inputs.js index 674f19e0b3..45750f6654 100644 --- a/src/sunstone/public/app/utils/user-inputs.js +++ b/src/sunstone/public/app/utils/user-inputs.js @@ -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 = $("
"); $.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) { $("
",{class:"columns small-12"}).append( $("",{ - '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 = ''; + var options = ""; 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 += "" + options += ""; } }); @@ -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 = ""; } else if(value == "NO"){ input = "
" + Locale.tr("YES ") + ""; - input += Locale.tr("NO ") + "" + input += Locale.tr("NO ") + ""; } else { input = "
" + Locale.tr("YES ") + ""; input += Locale.tr("NO ") + ""; @@ -902,7 +903,7 @@ define(function(require) { break; } if(attr.visor){ - input += ''; + input += ""; } return input; } diff --git a/src/sunstone/sunstone-server.rb b/src/sunstone/sunstone-server.rb index 642b67c6be..a5d8573626 100755 --- a/src/sunstone/sunstone-server.rb +++ b/src/sunstone/sunstone-server.rb @@ -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(/(?\w+) (?\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