ssp_for_opennebula4.1.patch

patch for enable SAML-based authentication of Sunstone - Milán Unicsovics, 06/14/2013 01:19 PM

Download (26.3 KB)

View differences:

one_patched/install.sh 2013-06-14 14:33:17.485704834 +0200
312 312
               $SUNSTONE_LOCATION/public/vendor/4.0/jdpicker_1.1 \
313 313
               $SUNSTONE_LOCATION/public/vendor/4.0/jdpicker_1.1/images \
314 314
               $SUNSTONE_LOCATION/public/vendor/4.0/datetimepicker \
315
               $SUNSTONE_LOCATION/public/vendor/jQueryCookie \
315 316
               $SUNSTONE_LOCATION/public/images \
316 317
               $SUNSTONE_LOCATION/views"
317 318

  
......
512 513
    SUNSTONE_PUBLIC_NEW_VENDOR_JDPICKER_IMAGES:$SUNSTONE_LOCATION/public/vendor/4.0/jdpicker_1.1/images
513 514
    SUNSTONE_PUBLIC_NEW_VENDOR_TIMEPICKER:$SUNSTONE_LOCATION/public/vendor/4.0/
514 515
    SUNSTONE_PUBLIC_NEW_VENDOR_DATETIMEPICKER:$SUNSTONE_LOCATION/public/vendor/4.0/datetimepicker
516
    SUNSTONE_PUBLIC_VENDOR_JQUERYCOOKIE:$SUNSTONE_LOCATION/public/vendor/jQueryCookie
515 517
    SUNSTONE_PUBLIC_IMAGES_FILES:$SUNSTONE_LOCATION/public/images
516 518
    SUNSTONE_PUBLIC_LOCALE_CA:$SUNSTONE_LOCATION/public/locale/ca
517 519
    SUNSTONE_PUBLIC_LOCALE_CS_CZ:$SUNSTONE_LOCATION/public/locale/cs_CZ
......
1180 1182
                      src/cloud/common/CloudAuth/SunstoneCloudAuth.rb \
1181 1183
                      src/cloud/common/CloudAuth/EC2CloudAuth.rb \
1182 1184
                      src/cloud/common/CloudAuth/X509CloudAuth.rb \
1183
                      src/cloud/common/CloudAuth/OpenNebulaCloudAuth.rb"
1185
                      src/cloud/common/CloudAuth/OpenNebulaCloudAuth.rb \
1186
                      src/cloud/common/CloudAuth/SSPCloudAuth.rb \
1187
                      src/cloud/common/CloudAuth/ssp_helper.rb"
1184 1188

  
1185 1189
#-------------------------------------------------------------------------------
1186 1190
# EC2 Query for OpenNebula
......
1408 1412
SUNSTONE_VIEWS_FILES="src/sunstone/views/index.erb \
1409 1413
                      src/sunstone/views/login.erb \
1410 1414
                      src/sunstone/views/_login_standard.erb \
1411
                      src/sunstone/views/_login_x509.erb"
1415
                      src/sunstone/views/_login_x509.erb \
1416
                      src/sunstone/views/_login_ssp.erb"
1412 1417

  
1413 1418
SUNSTONE_PUBLIC_JS_FILES="src/sunstone/public/js/layout.js \
1414 1419
                        src/sunstone/public/js/login.js \
1420
                        src/sunstone/public/js/login_ssp.js \
1415 1421
                        src/sunstone/public/js/sunstone.js \
1416 1422
                        src/sunstone/public/js/sunstone-util.js \
1417 1423
                        src/sunstone/public/js/opennebula.js \
......
1531 1537
            src/sunstone/public/vendor/4.0/jquery_layout/layout-default-latest.css \
1532 1538
            src/sunstone/public/vendor/4.0/jquery_layout/jquery.layout-latest.min.js"
1533 1539

  
1540
SUNSTONE_PUBLIC_VENDOR_JQUERYCOOKIE="\
1541
            src/sunstone/public/vendor/jQueryCookie/jquery-cookie.js"
1534 1542

  
1535 1543
SUNSTONE_PUBLIC_NEW_VENDOR_FONTAWESOME_CSS="\
1536 1544
  src/sunstone/public/vendor/4.0/fontawesome/css/font-awesome.min.css"
one_patched/src/cloud/common/CloudAuth/SSPCloudAuth.rb 2012-12-21 11:53:07.000000000 +0100
1
# -------------------------------------------------------------------------- #
2
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org)             #
3
#                                                                            #
4
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
5
# not use this file except in compliance with the License. You may obtain    #
6
# a copy of the License at                                                   #
7
#                                                                            #
8
# http://www.apache.org/licenses/LICENSE-2.0                                 #
9
#                                                                            #
10
# Unless required by applicable law or agreed to in writing, software        #
11
# distributed under the License is distributed on an "AS IS" BASIS,          #
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
13
# See the License for the specific language governing permissions and        #
14
# limitations under the License.                                             #
15
#--------------------------------------------------------------------------- #
16

  
17
DIR=File.dirname(__FILE__)
18
$: << DIR
19

  
20
require 'ssp_helper.rb'
21
require 'xmlrpc/client'
22
require 'rubygems'
23
require 'nokogiri'
24
require 'json'
25
require 'net/http'
26

  
27
# @mainpage  SSP Cloud Auth module for OpenNebula Sunstone
28
#
29
# @section desc Description
30
# This is a new authentication module for OpenNebula Sunstone. In its name SSP means 
31
# Simple SAML PHP (http://simplesamlphp.org/).
32
# SSP Cloud Auth module is useful, when a SingleSignOn is login needed, which service is realised 
33
# with SimpleSAMLphp. In this case, login handled by SimpleSAMLphp and so the Sunstone 
34
# auth module (this one) makes only the identification of the users. \n
35
# If new user wants to login, this module creates a new account for the user.
36
# 
37
# @section conf Configuration
38
# Configuration file is at the end of the main Sunstone configuration file (sunstone-server.conf).
39
module SSPCloudAuth
40

  
41
    attr_accessor :sessionid, :session
42
    
43
    @sessionid=''
44
    @session=''
45

  
46
    # original do_auth function
47
    # gets login datas from SimpleSAMLphp and authenticates the user
48
    # if new user wants to login, then creates its user
49
    # updates user's group
50
    # @param params['ssp_sessionid'] SSP session id from cookie
51
    # @return username if authentication success
52
    def do_auth(env, params={})
53
        auth = Rack::Auth::Basic::Request.new(env)
54

  
55
        # initialize some variable
56
        @sessionid=params['ssp_sessionid']
57

  
58
        if auth.provided? && auth.basic?
59

  
60
            # create helper
61
            ssp=SSP_Helper.new
62

  
63
            # get login datas from ssp
64
            @session=ssp.get_ssp_session(@sessionid)
65

  
66
            # test if user is authorized
67
            if (@session['is_auth']!=true)
68
                return nil
69
            end
70

  
71
            # get name from session
72
            @username=@session['data']['eduPersonPrincipalName'].join
73

  
74
            # if any privilege was sent then get it; if it was not sent and strict auth needed then deny login
75
            if @session['data'].has_key?('eduPersonEntitlement')
76
                @groupname=@session['data']['eduPersonEntitlement'].join
77
            else
78
                @groupname=''
79
            end
80

  
81
            # if new user wants to login then create it
82
            if ssp.get_userid(@username).empty?
83
                ssp.create_user(@username)
84
            end
85

  
86
            # update user's group
87
            ssp.update_group(@username,@groupname)
88

  
89
            return @username
90
        end
91

  
92
        return nil
93
    end
94
end
one_patched/src/cloud/common/CloudAuth/ssp_helper.rb 2012-12-21 11:53:54.000000000 +0100
1
# -------------------------------------------------------------------------- #
2
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org)             #
3
#                                                                            #
4
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
5
# not use this file except in compliance with the License. You may obtain    #
6
# a copy of the License at                                                   #
7
#                                                                            #
8
# http://www.apache.org/licenses/LICENSE-2.0                                 #
9
#                                                                            #
10
# Unless required by applicable law or agreed to in writing, software        #
11
# distributed under the License is distributed on an "AS IS" BASIS,          #
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
13
# See the License for the specific language governing permissions and        #
14
# limitations under the License.                                             #
15
#--------------------------------------------------------------------------- #
16

  
17
# Helper class to call methods in SSPCloudAuth module
18
class SSP_Helper
19

  
20
    attr_accessor :one_xmlrpc, :one_auth, :one_location, :config
21

  
22
    # initalize some instance variable
23
    def initialize
24
        @one_location=''
25
        
26
        # get ssp configuration
27
        if @one_location.empty?
28
            etc_location="/etc/one"
29
        else
30
            etc_location=@one_location+"/etc"
31
        end
32

  
33
        configuration_file=etc_location+"/sunstone-server.conf"
34

  
35
        begin
36
            @config = YAML.load_file(configuration_file)
37
        rescue Exception => e
38
            STDERR.puts "Error parsing config file #{configuration_file}: #{e.message}"
39
            exit 1
40
        end
41

  
42
        @one_xmlrpc=@config[:one_xmlrpc]
43
        @one_auth=@config[:one_auth_for_ssp]
44
    end 
45

  
46
    # creating new user
47
    # @param username username of user to be created
48
    def create_user(username)
49
        server=XMLRPC::Client.new2(@one_xmlrpc)
50
        
51
        session_string=self.get_credential["username"]+":"+self.get_credential["password"]
52
        
53
        begin
54
            response=server.call("one.user.allocate",session_string,username,self.generate_password,'')
55
        rescue Exception => e
56
            [false, e.message]
57
        end
58
    end
59

  
60
    # update user's group or create it's group
61
    # @param username username's group will be updated
62
    # @param groupname user's group
63
    def update_group(username,groupname)
64
        server=XMLRPC::Client.new2(@one_xmlrpc)
65
        
66
        session_string=self.get_credential["username"]+":"+self.get_credential["password"]
67

  
68
        if groupname.empty?
69
            groupname='users'
70
        end
71

  
72
        if self.get_groupid(groupname).empty?
73
            self.create_group(groupname)
74
        end
75

  
76
        begin
77
            response=server.call("one.user.chgrp",session_string,self.get_userid(username).to_i,self.get_groupid(groupname).to_i)
78
        rescue Exception => e
79
            [false, e.message]
80
        end
81
    end
82

  
83
    # get username and password from $ONE_AUTH file
84
    # @return username and password in a Hash
85
    def get_credential
86
        credential=Hash.new
87
        
88
        if File.readable?(@one_auth)
89
            File.open(@one_auth, 'r') do |line| 
90
                auth_line=line.gets.strip
91
                auth_line=auth_line.split(':')
92

  
93
                credential["username"]=auth_line[0]
94
                credential["password"]=auth_line[1]
95
            end
96
        else
97
            # TODO: write error into log (SSP_Helper ERROR: $ONE_AUTH file is not readable)
98
            raise "one auth file not readable"
99
        end
100
        return credential
101
    end
102

  
103
    # get user's ID
104
    # @param username username
105
    # @return user's ID
106
    def get_userid(username)
107
        server=XMLRPC::Client.new2(@one_xmlrpc)
108
        
109
        session_string=self.get_credential["username"]+":"+self.get_credential["password"]
110
        
111
        begin
112
            response=server.call("one.userpool.info",session_string)
113
        rescue Exception => e
114
            [false, e.message]
115
        end
116

  
117
        xml=Nokogiri::XML(response[1])
118
        return xml.xpath('//USER[NAME=\''+username+'\']/ID').inner_text
119
    end
120

  
121
    # get group ID of a group
122
    # @param groupname groupname
123
    # @return group's ID
124
    def get_groupid(groupname)
125
        server=XMLRPC::Client.new2(@one_xmlrpc)
126
        
127
        session_string=self.get_credential["username"]+":"+self.get_credential["password"]
128
        
129
        begin
130
            response=server.call("one.grouppool.info",session_string)
131
        rescue Exception => e
132
            [false, e.message]
133
        end
134

  
135
        xml=Nokogiri::XML(response[1])
136
        return xml.xpath('//GROUP[NAME=\''+groupname+'\']/ID').inner_text
137
    end
138

  
139
    # creating new group
140
    # @param groupname groupname of group to be created
141
    def create_group(groupname)
142
        server=XMLRPC::Client.new2(@one_xmlrpc)
143
        
144
        session_string=self.get_credential["username"]+":"+self.get_credential["password"]
145
        
146
        begin
147
            response=server.call("one.group.allocate",session_string,groupname)
148
        rescue Exception => e
149
            [false, e.message]
150
        end
151
    end
152

  
153
    # create random password for new users
154
    # @return random password
155
    def generate_password
156
        return rand(36**20).to_s(36)
157
    end
158

  
159
    # get ssp session variable in JSON format
160
    # @param sessionid ssp session id from cookie
161
    # @return ssp_session ssp session in JSON format
162
    def get_ssp_session(sessionid)
163
        url=URI.parse(@config[:ssp_host])
164
        http=Net::HTTP.new(url.host,url.port)
165
        req=Net::HTTP::Get.new(@config[:ssp_loginvalidator]+sessionid)
166
        if url.scheme=='https'
167
            http.use_ssl=true
168
            http.verify_mode=OpenSSL::SSL::VERIFY_NONE
169
        end
170
        res=http.request(req)
171
        ssp_session_json=res.body
172
        ssp_session=JSON.parse(ssp_session_json)
173
        return ssp_session
174
    end
175

  
176
    # is user authorized in ssp?
177
    # @param sessionid ssp session id from cookie
178
    # @return true if user is authorized
179
    def authorized?(sessionid)
180
        if sessionid.nil? or get_ssp_session(sessionid)['is_auth']!=true
181
            return false
182
        else
183
            return true
184
        end
185
    end
186

  
187
end
one_patched/src/cloud/common/CloudAuth.rb 2013-06-14 13:56:56.527881665 +0200
21 21
    AUTH_MODULES = {
22 22
        "occi"       => 'OCCICloudAuth',
23 23
        "sunstone"   => 'SunstoneCloudAuth' ,
24
        "ssp"        => 'SSPCloudAuth' ,
24 25
        "ec2"        => 'EC2CloudAuth',
25 26
        "x509"       => 'X509CloudAuth',
26 27
        "opennebula" => 'OpenNebulaCloudAuth'
one_patched/src/sunstone/etc/sunstone-server.conf 2013-06-14 13:58:07.563681523 +0200
124 124
#:routes:
125 125
#    - custom
126 126
#    - other
127

  
128
################################################################################
129
## SSP Auth module
130
#################################################################################
131
#
132
## ssp_sessionid:        Simple SAML PHP session ID cookie name.
133
## ssp_host:             Simple SAML PHP host url.
134
## ssp_loginpage:        Simple SAML PHP login page.
135
## ssp_loginvalidator:   Simple SAML PHP login validator script path. This
136
##                       script authenticates users in Simple SAML PHP and
137
##                       gets login data in JSON format.
138
## ssp_logoutpage:       Simple SAML PHP logout page.
139
## one_auth_for_ssp:     one_auth file location
140
:ssp_sessionid: PHPSESSID
141
:ssp_host: http://192.168.204.100
142
:ssp_loginpage: /simplesaml/module.php/core/as_login.php?AuthId=default-sp&ReturnTo=/one/
143
:ssp_loginvalidator: /simplesaml/module.php/getSession/index.php?sessid=
144
:ssp_logoutpage: /simplesaml/module.php/core/as_logout.php?AuthId=default-sp&ReturnTo=/simplesaml/logout.php
145
:one_auth_for_ssp: /var/lib/one/.one/one_auth
one_patched/src/sunstone/public/js/login_ssp.js 2013-06-14 14:36:43.630852892 +0200
1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs        */
3
/*                                                                            */
4
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
5
/* not use this file except in compliance with the License. You may obtain    */
6
/* a copy of the License at                                                   */
7
/*                                                                            */
8
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
9
/*                                                                            */
10
/* Unless required by applicable law or agreed to in writing, software        */
11
/* distributed under the License is distributed on an "AS IS" BASIS,          */
12
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
13
/* See the License for the specific language governing permissions and        */
14
/* limitations under the License.                                             */
15
/* -------------------------------------------------------------------------- */
16

  
17
function auth_success(req, response){
18
    window.location.href = ".";
19
}
20

  
21
function auth_error(req, error){
22

  
23
    var status = error.error.http_status;
24

  
25
    switch (status){
26
    case 401:
27
        $("#error_message").text("Invalid username or password");
28
        break;
29
    case 500:
30
        $("#error_message").text("OpenNebula is not running or there was a server exception. Please check the server logs.");
31
        break;
32
    case 0:
33
        $("#error_message").text("No answer from server. Is it running?");
34
        break;
35
    default:
36
        $("#error_message").text("Unexpected error. Status "+status+". Check the server logs.");
37
    };
38
    $("#error_box").fadeIn("slow");
39
}
40

  
41
function authenticate(){
42
    var username = '';
43
    var password = '';
44
    var remember = true;
45

  
46
    $("#error_box").fadeOut("slow");
47

  
48
    OpenNebula.Auth.login({ data: {username: username
49
                                    , password: password}
50
                            , remember: remember
51
                            , success: auth_success
52
                            , error: auth_error
53
                        });
54
}
55

  
56
function getInternetExplorerVersion(){
57
// Returns the version of Internet Explorer or a -1
58
// (indicating the use of another browser).
59
    var rv = -1; // Return value assumes failure.
60
    if (navigator.appName == 'Microsoft Internet Explorer')
61
    {
62
        var ua = navigator.userAgent;
63
        var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
64
        if (re.exec(ua) != null)
65
            rv = parseFloat( RegExp.$1 );
66
    }
67
    return rv;
68
}
69

  
70
function checkVersion(){
71
    var ver = getInternetExplorerVersion();
72

  
73
    if ( ver > -1 ){
74
        msg = ver <= 7.0 ? "You are using an old version of IE. \
75
Please upgrade or use Firefox or Chrome for full compatibility." :
76
        "OpenNebula Sunstone is best seen with Chrome or Firefox";
77
        $("#error_box").text(msg);
78
        $("#error_box").fadeIn('slow');
79
    }
80
}
81

  
82
$(document).ready(function(){
83
    var pathname=$(location).attr('href');
84
    $.ajax({
85
       type: 'GET',
86
       url:pathname,
87
       complete: function(XMLHttpRequest,textStatus){
88
            authenticate();
89
            return false;
90
       }
91
    });
92

  
93
    //compact login elements according to screen height
94
    if (screen.height <= 600){
95
        $('div#logo_sunstone').css("top","15px");
96
        $('.error_message').css("top","10px");
97
    };
98

  
99
    checkVersion();
100
});
one_patched/src/sunstone/public/js/sunstone.js 2013-06-14 14:06:50.331896879 +0200
444 444
    //This variables can be used anywhere
445 445
    switch(whichUI()){
446 446
    case "sunstone":
447
        username = cookie["one-user"];
447
        username = decodeURIComponent(cookie["one-user"]);
448 448
        uid = cookie["one-user_id"];
449 449
        gid = cookie["one-user_gid"];
450 450
        break;
451 451
    case "ozones":
452
        username = cookie["ozones-user"];
452
        username = decodeURIComponent(cookie["ozones-user"]);
453 453
        break;
454 454
    case "selfservice":
455
        username = cookie["occi-user"];
455
        username = decodeURIComponent(cookie["occi-user"]);
456 456
        uid = cookie["occi-user-id"];
457 457
        break;
458 458
    };
one_patched/src/sunstone/public/vendor/jQueryCookie/jquery-cookie.js 2012-12-11 18:20:46.000000000 +0100
1
/*jshint eqnull:true */
2
/*!
3
 * jQuery Cookie Plugin v1.1
4
 * https://github.com/carhartl/jquery-cookie
5
 *
6
 * Copyright 2011, Klaus Hartl
7
 * Dual licensed under the MIT or GPL Version 2 licenses.
8
 * http://www.opensource.org/licenses/mit-license.php
9
 * http://www.opensource.org/licenses/GPL-2.0
10
 */
11
(function($, document) {
12

  
13
	var pluses = /\+/g;
14
	function raw(s) {
15
		return s;
16
	}
17
	function decoded(s) {
18
		return decodeURIComponent(s.replace(pluses, ' '));
19
	}
20

  
21
	$.cookie = function(key, value, options) {
22

  
23
		// key and at least value given, set cookie...
24
		if (arguments.length > 1 && (!/Object/.test(Object.prototype.toString.call(value)) || value == null)) {
25
			options = $.extend({}, $.cookie.defaults, options);
26

  
27
			if (value == null) {
28
				options.expires = -1;
29
			}
30

  
31
			if (typeof options.expires === 'number') {
32
				var days = options.expires, t = options.expires = new Date();
33
				t.setDate(t.getDate() + days);
34
			}
35

  
36
			value = String(value);
37

  
38
			return (document.cookie = [
39
				encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
40
				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
41
				options.path    ? '; path=' + options.path : '',
42
				options.domain  ? '; domain=' + options.domain : '',
43
				options.secure  ? '; secure' : ''
44
			].join(''));
45
		}
46

  
47
		// key and possibly options given, get cookie...
48
		options = value || $.cookie.defaults || {};
49
		var decode = options.raw ? raw : decoded;
50
		var cookies = document.cookie.split('; ');
51
		for (var i = 0, parts; (parts = cookies[i] && cookies[i].split('=')); i++) {
52
			if (decode(parts.shift()) === key) {
53
				return decode(parts.join('='));
54
			}
55
		}
56
		return null;
57
	};
58

  
59
	$.cookie.defaults = {};
60

  
61
})(jQuery, document);
62

  
one_patched/src/sunstone/sunstone-server.rb 2013-06-14 14:18:14.552098832 +0200
43 43

  
44 44
$: << RUBY_LIB_LOCATION
45 45
$: << RUBY_LIB_LOCATION+'/cloud'
46
$: << RUBY_LIB_LOCATION+'/cloud/CloudAuth'
46 47
$: << SUNSTONE_ROOT_DIR
47 48
$: << SUNSTONE_ROOT_DIR+'/models'
48 49

  
......
60 61
require 'SunstoneServer'
61 62
require 'SunstoneViews'
62 63

  
64
require 'ssp_helper'
63 65

  
64 66
##############################################################################
65 67
# Configuration
......
139 141

  
140 142
    def build_session
141 143
        begin
144
            if $conf[:auth]=='ssp'
145
                response.set_cookie('ssp_logoutpage',$conf[:ssp_host]+$conf[:ssp_logoutpage])
146
                params['ssp_sessionid']=request.cookies[$conf[:ssp_sessionid]]
147
            end
142 148
            result = $cloud_auth.auth(request.env, params)
143 149
        rescue Exception => e
144 150
            logger.error { e.message }
......
247 253
##############################################################################
248 254
get '/' do
249 255
    content_type 'text/html', :charset => 'utf-8'
256

  
257
    if $conf[:auth]=='ssp'
258
        ssp_sessionid=request.cookies[$conf[:ssp_sessionid]]
259
        ssp=SSP_Helper.new
260
        if not ssp.authorized?(ssp_sessionid)
261
            redirect $conf[:ssp_host]+$conf[:ssp_loginpage], 302
262
        end
263
    end
264

  
250 265
    if !authorized?
251 266
        return erb :login
252 267
    end
one_patched/src/sunstone/views/index.erb 2013-06-14 14:19:15.459626923 +0200
8 8
    <script src="vendor/4.0/jquery-migrate-1.1.0.js" type="text/javascript"></script>
9 9
    <script src="vendor/4.0/jgrowl/jquery.jgrowl.js" type="text/javascript"></script>
10 10
    <script src="vendor/4.0/jquery_layout/jquery.layout-latest.min.js" type="text/javascript"></script>
11
    <script type="text/javascript" src="vendor/jQueryCookie/jquery-cookie.js"></script>
11 12
    <script src="vendor/4.0/foundation/modernizr.foundation.js" type="text/javascript"></script>
12 13
    <script src="vendor/4.0/datatables/jquery.dataTables.min.js" type="text/javascript"></script>
13 14
    <script src="vendor/4.0/foundation_datatables/responsive-tables.js" type="text/javascript"></script>
one_patched/src/sunstone/views/login.erb 2013-06-14 14:21:30.916023544 +0200
11 11
    <![endif]-->
12 12

  
13 13
    <script type="text/javascript" src="js/opennebula.js"></script>
14
    <script type="text/javascript" src="js/login.js"></script>
14
    <% if settings.config[:auth] == "ssp" %>
15
        <script type="text/javascript" src="js/login_ssp.js"></script>
16
    <% else %>
17
        <script type="text/javascript" src="js/login.js"></script>
18
    <% end %>
15 19

  
16 20
</head>
17 21

  
......
20 24

  
21 25
<% if settings.config[:auth] == "x509" %>
22 26
  <%= erb :_login_x509 %>
27
<% elsif settings.config[:auth] == "ssp" %>
28
  <%= erb :_login_ssp %>
23 29
<% else %>
24 30
  <%= erb :_login_standard %>
25 31
<% end %>
one_patched/src/sunstone/views/_login_ssp.erb 2013-06-14 14:24:23.678352259 +0200
1
<div id="wrapper">
2
      <div id="logo_sunstone" style="
3
    background: url(<%=$views_config.logo%>) no-repeat center;
4
    background-size: 355px;">
5
      </div>
6

  
7
    <div id="error_box" class="hidden alert-box alert" style="display: none">
8
      <span id="error_message"></span>
9
    </div>
10

  
11
</div>