OpenNebulaOpenID-4.4.diff

VIVOSS company, 01/24/2014 11:20 AM

Download (32.5 KB)

View differences:

src/sunstone/etc/sunstone-server.conf
145 145

  
146 146
:routes:
147 147
    - oneflow
148

  
149
#new: openid support
150
#openid->enabled
151
#  turns openid on or off
152
#openid->auto_register
153
#  global setting for auto registering new users
154
#  if false, user who is not registered (not in OpenNebula user base)
155
#  will be refused in authorization
156
#  if true, OpenNebula user will be created
157
#openid->case_sensitive
158
#  global setting for case sensivity
159
#  if true, same user written in different case will be treated as different users
160
#  different OpenID servers might have different settings on their side
161
#  better check it beforehand and make server-specific settings
162
#openid->servers
163
#  list of servers to show in OpenID dropdown list
164
#  server-specific settings also go here
165
#openid->servers->addr
166
#  url of OpenID server
167
#  precisely, all that goes before user name
168
#openid->servers->auto_register
169
#openid->servers->case_sensitive
170
#  same as above, but server-specific
171
#openid->enforce_serverlist
172
#  if true, only users from servers listed in openid->servers are allowed
173
#  all other OpenID authorities are forbidden
174
#  if false, "Other" option appears in OpenID dropdown list and any authority is allowed
175
#openid->autocheck_servers
176
#  list of servers for which claimed identities are checked
177
#  immediate OpenID requests are sent to listed authorities
178
#  if any identity is claimed on the server and available in immediate mode,
179
#  it appears on the claimed identities list
180

  
181
:openid:
182
    :enabled: true
183
    :servers:
184
        - :addr: http://openid.mail.ru/
185
          :case_sensitive: true
186
          :auto_register: false
187
        - :addr: http://openid.yandex.ru/
188
          :case_sensitive: false
189
          :auto_register: true
190
    :auto_register: false
191
    :case_sensitive: false
192
    :autocheck_servers:
193
        - http://openid.mail.ru/
194
        - http://openid.yandex.ru/
195
    :enforce_serverlist: true
src/sunstone/public/css/login.css
21 21

  
22 22
}
23 23

  
24

  
25 24
#header {
26 25
    height: 30px;
27 26
    background-color: #353735;
......
74 73
    vertical-align: center;
75 74
}
76 75

  
77
div#login {
76
#login_tabs
77
{
78
    width: 400px;
79
    min-height: 300px;
80
    font-size: 1em;
81
    margin-left: auto;
82
    margin-right: auto;
83
    position: relative;
84
    top: 30px;
85
}
86

  
87
#login_tabs div.content
88
{
89
    margin-left: 30px;
90
    padding-top: 0px;
91
}
92

  
93
#login_tabs input#login_btn, #login_tabs input#openid_login_btn {
94
    margin-right: 20px;
95
}
96

  
97
div#login, div#openid_login {
78 98
    width: 400px;
79 99
    height: 300px;
80 100
    position: relative;
......
87 107
    background: url(../images/panel.png) no-repeat center ;
88 108

  
89 109
    vertical-align: center;
110

  
111
    margin-bottom: 40px;
90 112
}
91 113

  
114
#openid_serverlist {
115
    text-align: left;
116
    line-height: 150%;
117
}
92 118

  
93 119
.box {
94
    font-size:0.8em;
120
    font-size:0.8em !important;
95 121
    width: 300px;
96 122
    height: 25px;
97 123
    background: #FFFFFF;
......
121 147
    -moz-border-radius-bottomleft: 5px;
122 148
}
123 149

  
124

  
125

  
126
div#login input#login_btn {
150
input#login_btn, input#openid_login_btn {
127 151
    width: 130px;
128 152
    height: 45px;
129 153
    cursor: pointer;
......
136 160
    background:  url(../images/login.png) no-repeat center ;
137 161
}
138 162

  
139
div#login input#login_btn:hover {
163
input#login_btn:hover, input#openid_login_btn:hover {
140 164
  width: 130px;
141 165
  height: 45px;
142 166
  cursor: pointer;
......
217 241

  
218 242
#error_box {
219 243
  margin-top:70px;
220
}
244
}
src/sunstone/public/js/openid.js
1
var identities_found;
2
function oidResponse(identity, error)
3
{
4
    if (!error) {
5
        $("#openid_serverlist").append("<li><a href='#' onclick='openidLogin(" + '"' + identity + '"' + "); return false'>" + decodeURIComponent(identity) + "</a></li>");
6
        if (!identities_found) {
7
            identities_found = true;
8
            $("#identities_none").hide();
9
            $("#identities_link").click();
10
        }
11
    }
12
}
13

  
14
function openidLogin(identity)
15
{
16
    $("#openid_url").val(identity);
17
    $("#openid_form").submit();
18
}
19

  
20
function loadIdentList(count_resp)
21
{
22
    $("#openid_serverlist").empty();
23
    if(count_resp["error"] == true) {
24
        alert("Error occured");
25
        return;
26
    }
27
    var servercnt = count_resp["count"];
28
    var tab_ident = document.getElementById("tab_auth_identities");
29
    for(var i = 0; i < servercnt; i++) {
30
        var openid_frame = document.createElement("iframe");
31
        openid_frame.style = "width: 0px; height: 0px; display: none;";
32
        tab_ident.appendChild(openid_frame);
33
        openid_frame.src = "openid_info?action=getserver&id=" + i;
34
    }
35
}
36

  
37
$(document).ready(function() {
38
    $("#openid_login_btn").click(function () {
39
    var openid_prefix = "";
40
    var openid_pref_sel = $("#openid_prefix");
41
    if(openid_pref_sel.length) {
42
        openid_prefix = openid_pref_sel.val();
43
        if(openid_prefix.toLowerCase() == "other")
44
                openid_prefix = "";
45
    }
46
        $("#openid_url").val(openid_prefix + $("#openid_ident").val());
47
        $("#openid_form").submit();
48
        return false;
49
    });
50

  
51
    $("#login_tabs").tabs();
52

  
53
    $.ajax({
54
        url: "openid_info",
55
        data: { action: "servercount" },
56
        type: "GET",
57
        dataType : "json",
58
        success: loadIdentList,
59
        error: function( jqXHR, textStatus, errorThrown ) {
60
            alert( "Error occured getting OpenID identity list. " + textStatus + "\nAdditional information: " + errorThrown);
61
        }
62
    });
63
});
src/sunstone/public/js/plugins/users-tab.js
734 734
    $.each(users_list,function(){
735 735
        //if (this.USER.ID == uid)
736 736
        //    dashboardQuotasHTML(this.USER);
737
        if(this.USER.AUTH_DRIVER == "openid_stub"){
738
            this.USER.AUTH_DRIVER = "OpenID";
739
            this.USER.NAME = decodeURIComponent(this.USER.NAME); //unescape(this.USER.NAME);
740
        }
737 741
        user_list_array.push(userElementArray(this));
738 742
    });
739 743
    updateView(user_list_array,dataTable_users);
src/sunstone/sunstone-openid.rb
1
require 'sinatra'
2
require 'omniauth'
3
require 'omniauth-openid'
4
require 'openid/store/filesystem'
5
require 'openid/store/memory'
6
require 'uri'
7
require 'securerandom'
8

  
9
module OmniAuth
10
    module Strategies
11
        class OpenID
12
            def identifier
13
                i = options.identifier ||
14
                    request.params[options.identifier_param.to_s]
15
                return nil if i.empty?
16

  
17
                if $settings.config[:openid][:enforce_serverlist] == false ||
18
                   $settings.config[:openid][:servers].nil? ||
19
                   $settings.config[:openid][:servers].empty?
20
                    srv_in_list = true
21
                else
22
                    srv_in_list = $settings.config[:openid][:servers].any? { |srv| i.start_with?(srv[:addr])}
23
                end
24

  
25
                srv_in_list ? i : nil
26
            end
27
        end
28
    end
29
end
30

  
31
helpers do
32
    def openid_consumer
33
        #@openid_consumer ||= OpenID::Consumer.new(session, OpenID::Store::Filesystem.new("#{File.dirname(__FILE__)}/tmp/openid"))  
34
        @openid_consumer ||= OpenID::Consumer.new(session, OpenID::Store::Memory.new)   
35
    end
36
    def root_url
37
        request.url.match(/(^.*\/{2}[^\/]*)/)[1]
38
    end
39
end
40

  
41
use OmniAuth::Builder do
42
  #provider :open_id, :store => OpenID::Store::Filesystem.new('/tmp')
43
  provider :open_id
44
end
45

  
46
post '/auth/open_id/callback' do
47
    #Defaults
48
    srv_case = false
49
    srv_autoreg = true
50
    #Get OmniAuth OpenID auth data and settings from config
51
    auth = request.env['omniauth.auth']
52
    #Extract claimed identity, make server-specific settings, if possible
53
    username = auth['uid']
54
    username = URI.decode_www_form_component(username)
55
    username_friendly = username
56
    srv_case ||= settings.config[:openid][:case_sensitive]
57
    srv_autoreg = settings.config[:openid][:auto_register] unless settings.config[:openid][:auto_register].nil?
58
    #Delete server name and slashes to get friendly display name
59
    if settings.config[:openid][:servers] &&
60
       (srv = settings.config[:openid][:servers].detect { |srv| username.start_with?(srv[:addr]) })
61
        username_friendly = username[srv[:addr].length..-1].chomp '/'
62
        srv_case = srv[:case_sensitive] unless srv[:case_sensitive].nil?
63
        srv_autoreg = srv[:auto_register] unless srv[:auto_register].nil?
64
    end
65
    #encode username to store as OpenNebula user
66
    username.downcase! unless srv_case
67
    username_encoded = URI.encode_www_form_component(username)
68
    #Check if user exists
69
    client = OpenNebula::Client.new
70
    userpool = OpenNebula::UserPool.new(client)
71
    userpool.info
72
    user_id = userpool["/USER_POOL/USER[NAME='#{username_encoded}']/ID"]
73
    #If it does, get user and pass to session constructor
74
    #Otherwise - create user first
75
    if user_id.nil?
76
        if srv_autoreg
77
            xml = OpenNebula::User.build_xml
78
            user = OpenNebula::User.new(xml, client)
79
            user.allocate(username_encoded, SecureRandom.hex, 'openid_stub')
80
        else
81
            user = nil
82
            err_msg = "This OpenID user can't access system"
83
            redirect "/?openid_error=#{err_msg}"
84
        end
85
    else
86
        user = OpenNebula::User.new_with_id(user_id.to_i, client)
87
    end
88
    #Build session with found or newly created user
89
    build_session(user, username_friendly)
90
    redirect '/'
91
end
92

  
93
get '/auth/failure' do
94
    #Redirect to login page with OpenID error box displayed
95
    redirect "/?openid_error=#{params['message']}"
96
end
97

  
98
get '/openid_info' do
99
    case request["action"].downcase
100
    when "servercount" then
101
        unless settings.config[:openid][:autocheck_servers].nil?
102
            response = {"count" => settings.config[:openid][:autocheck_servers].length, "error" => false}
103
        else
104
            response = {"error" => true}
105
        end
106
    when "getserver" then
107
        unless settings.config[:openid][:autocheck_servers].nil? || request["id"].nil? || settings.config[:openid][:autocheck_servers][request["id"].to_i].nil?
108
              openid = params[:openid_identifier]
109
              begin
110
                  oidreq = openid_consumer.begin(settings.config[:openid][:autocheck_servers][request["id"].to_i])
111
              rescue OpenID::DiscoveryFailure => why
112
                  content_type 'text/html', :charset => 'utf-8'
113
                  return erb :_openid_check, :locals => {:openid_error => true, :identifier => why}
114
              else
115
                  redirect oidreq.redirect_url(root_url, root_url + "/openid_info/return", true)
116
              end
117
        else
118
            content_type 'text/html', :charset => 'utf-8'
119
            return erb :_openid_check, :locals => {:openid_error => true, :identifier => "No server found"}
120
        end
121
    else
122
        response = {"error" => true}
123
    end
124
    response.to_json
125
end
126

  
127
get '/openid_info/return' do
128
    content_type 'text/html', :charset => 'utf-8'
129
    oidresp = openid_consumer.complete(params, request.url)
130
    ident = oidresp.display_identifier
131
    unless oidresp.status == OpenID::Consumer::SUCCESS
132
        openid_error = true
133
        ident = oidresp.status.to_s
134
    else
135
        openid_error = false
136
    end
137
    erb :_openid_check, :locals => {:openid_error => openid_error, :identifier => ident}
138
end
src/sunstone/sunstone-server.rb
1 1
#!/usr/bin/env ruby
2 2
# -*- coding: utf-8 -*-
3 3

  
4

  
4 5
# -------------------------------------------------------------------------- #
5 6
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs        #
6 7
#                                                                            #
......
101 102
    exit(-1)
102 103
end
103 104

  
105
# Enable OpenID, if required
106
if settings.config[:openid][:enabled]
107
  require 'sunstone-openid'
108
  require 'opennebula'
109

  
110
  include OpenNebula
111
end
112
$settings = settings
104 113
# Enable logger
105 114

  
106 115
include CloudLogger
......
139 148
        session[:ip] && session[:ip]==request.ip ? true : false
140 149
    end
141 150

  
142
    def build_session
143
        begin
144
            result = $cloud_auth.auth(request.env, params)
145
        rescue Exception => e
146
            logger.error { e.message }
147
            return [500, ""]
148
        end
149

  
150
        if result.nil?
151
            logger.info { "Unauthorized login attempt" }
152
            return [401, ""]
151
    def build_session(openid_user = nil, openid_display_name = nil)
152
        if openid_user
153
            user = openid_user
153 154
        else
155
            begin
156
                result = $cloud_auth.auth(request.env, params)
157
            rescue Exception => e
158
                logger.error { e.message }
159
                return [500, ""]
160
            end
161

  
162
            if result.nil?
163
                logger.info { "Unauthorized login attempt" }
164
                return [401, ""]
165
            end
154 166
            client  = $cloud_auth.client(result)
155 167
            user_id = OpenNebula::User::SELF
156 168

  
157 169
            user    = OpenNebula::User.new_with_id(user_id, client)
158
            rc = user.info
159
            if OpenNebula.is_error?(rc)
160
                logger.error { rc.message }
161
                return [500, ""]
162
            end
170
        end
163 171

  
164
            session[:user]         = user['NAME']
165
            session[:user_id]      = user['ID']
166
            session[:user_gid]     = user['GID']
167
            session[:user_gname]   = user['GNAME']
168
            session[:ip]           = request.ip
169
            session[:remember]     = params[:remember]
170
            session[:display_name] = user[DISPLAY_NAME_XPATH] || user['NAME']
172
        rc = user.info
173
        if OpenNebula.is_error?(rc)
174
            logger.error { rc.message }
175
            return [500, ""]
176
        end
171 177

  
172
            #User IU options initialization
173
            #Load options either from user settings or default config.
174
            # - LANG
175
            # - WSS CONECTION
176
            # - TABLE ORDER
178
        session[:user]         = user['NAME']
179
        session[:user_id]      = user['ID']
180
        session[:user_gid]     = user['GID']
181
        session[:user_gname]   = user['GNAME']
182
        session[:ip]           = request.ip
183
        session[:remember]     = params[:remember]
184
        if openid_display_name
185
            session[:display_name] = openid_display_name
186
        else
187
            session[:display_name] = user[DISPLAY_NAME_XPATH] || user['NAME']
188
        end
177 189

  
178
            if user['TEMPLATE/LANG']
179
                session[:lang] = user['TEMPLATE/LANG']
180
            else
181
                session[:lang] = $conf[:lang]
182
            end
190
        #User IU options initialization
191
        #Load options either from user settings or default config.
192
        # - LANG
193
        # - WSS CONECTION
194
        # - TABLE ORDER
183 195

  
184
            if user['TEMPLATE/VNC_WSS']
185
                session[:vnc_wss] = user['TEMPLATE/VNC_WSS']
186
            else
187
                wss = $conf[:vnc_proxy_support_wss]
188
                #limit to yes,no options
189
                session[:vnc_wss] = (wss == true || wss == "yes" || wss == "only" ?
190
                                 "yes" : "no")
191
            end
196
        if user['TEMPLATE/LANG']
197
            session[:lang] = user['TEMPLATE/LANG']
198
        else
199
            session[:lang] = $conf[:lang]
200
        end
192 201

  
193
            if user['TEMPLATE/TABLE_ORDER']
194
                session[:table_order] = user['TEMPLATE/TABLE_ORDER']
195
            else
196
                session[:table_order] = $conf[:table_order]
197
            end
202
        if user['TEMPLATE/VNC_WSS']
203
            session[:vnc_wss] = user['TEMPLATE/VNC_WSS']
204
        else
205
            wss = $conf[:vnc_proxy_support_wss]
206
            #limit to yes,no options
207
            session[:vnc_wss] = (wss == true || wss == "yes" || wss == "only" ?
208
                             "yes" : "no")
209
        end
198 210

  
199
            if user['TEMPLATE/DEFAULT_VIEW']
200
                session[:default_view] = user['TEMPLATE/DEFAULT_VIEW']
201
            else
202
                session[:default_view] = $views_config.available_views(session[:user], session[:user_gname]).first
203
            end
211
        if user['TEMPLATE/TABLE_ORDER']
212
            session[:table_order] = user['TEMPLATE/TABLE_ORDER']
213
        else
214
            session[:table_order] = $conf[:table_order]
215
        end
204 216

  
205
            #end user options
217
        if user['TEMPLATE/DEFAULT_VIEW']
218
            session[:default_view] = user['TEMPLATE/DEFAULT_VIEW']
219
        else
220
            session[:default_view] = $views_config.available_views(session[:user], session[:user_gname]).first
221
        end
206 222

  
207
            if params[:remember] == "true"
208
                env['rack.session.options'][:expire_after] = 30*60*60*24-1
209
            end
223
        #end user options
210 224

  
211
            return [204, ""]
225
        if params[:remember] == "true"
226
            env['rack.session.options'][:expire_after] = 30*60*60*24-1
212 227
        end
228

  
229
        return [204, ""]
213 230
    end
214 231

  
215 232
    def destroy_session
......
221 238
before do
222 239
    cache_control :no_store
223 240
    content_type 'application/json', :charset => 'utf-8'
224
    unless request.path=='/login' || request.path=='/' || request.path=='/vnc'
241
    unless request.path=='/login' || request.path=='/' || request.path=='/vnc' || (settings.config[:openid][:enabled] && (request.path == '/auth/open_id' || request.path == '/auth/open_id/callback' || request.path == '/auth/failure' || request.path == '/openid_info' || request.path == '/openid_info/return'))
225 242
        halt 401 unless authorized?
226 243

  
227 244
        @SunstoneServer = SunstoneServer.new(
......
257 274
##############################################################################
258 275
get '/' do
259 276
    content_type 'text/html', :charset => 'utf-8'
277

  
260 278
    if !authorized?
261 279
        return erb :login
262 280
    end
......
449 467
                                   request.body.read)
450 468
end
451 469

  
452
Sinatra::Application.run! if(!defined?(WITH_RACKUP))
453 470

  
471
Sinatra::Application.run! if(!defined?(WITH_RACKUP))
src/sunstone/views/_login_standard_new.erb
1
<form id="login_form">
2
    <div class="content">
3
        Username
4
        <input type="text" size="15" name="username" id="username" class="box"/>
5
        Password
6
        <input type="password" size="15" name="password" id="password" class="box"/>
7
        <br />
8
        <input type="checkbox" id="check_remember" />
9
        <label id="label_remember" for="check_remember">Keep me logged in</label>
10
        <input type="submit" id="login_btn" value="" />
11
        <img src="images/ajax-loader.gif" alt="retrieving" id="login_spinner" />
12
    </div>
13
    <div id="error_box" class="hidden alert-box alert" style="display: none">
14
        <span id="error_message"></span>
15
    </div>
16
</form>
src/sunstone/views/_openid.erb
1
<%openid_error = params["openid_error"]?'style="margin-top: 100px"':'style="display: none"'%>
2

  
3
<form id="openid_form" method="POST" action="/auth/open_id">
4
      <div class="content" >
5
          <% if settings.config[:openid][:servers] && settings.config[:openid][:servers].any? %>
6
              OpenID server
7
              <br />
8
              <select class="box" id="openid_prefix">
9
                  <% settings.config[:openid][:servers].each do |openid_server| %>
10
                      <option><%=openid_server[:addr]%></option>
11
                  <% end %>
12
                  <% unless settings.config[:openid][:enforce_serverlist] %>
13
                <option>Other</option>
14
                  <% end %>
15
              </select>
16
    <% end %>
17
          Identity
18
          <input type="text" size="15" id="openid_ident" class="box"/>
19
          <input type="hidden" name="openid_url" id="openid_url">
20
          <br />
21
          <input type="submit" id="openid_login_btn" value="" />
22
      </div>
23
  <div id="openid_error_box" class="hidden alert-box alert" <%=openid_error%>>
24
    <span id="openid_error_message">OpenID error: <%=params["openid_error"]%></span>
25
  </div>
26
</form>
src/sunstone/views/_openid_check.erb
1
<!DOCTYPE html><head><script type="text/javascript">
2
    parent.oidResponse(<%="'#{identifier}'"%>, <%=openid_error.to_s%>);
3
</script></head></html>
src/sunstone/views/login.erb
5 5
    <title>OpenNebula Sunstone Login</title>
6 6
    <link rel="stylesheet" type="text/css" href="css/login.css" />
7 7
    <script type="text/javascript" src="vendor/4.0/jquery-1.9.1.min.js"></script>
8

  
9
    <script type="text/javascript" src="vendor/4.0/jquery-ui-1.10.3/js/jquery-ui-1.10.3.custom.min.js"></script>
10
    <link rel="stylesheet" type="text/css" href="vendor/4.0/jquery-ui-1.10.3/css/smoothness/jquery-ui-1.10.3.custom.min.css" />
11

  
12
    <script type="text/javascript" src="js/openid.js"></script>
8 13
    <!--[if IE]>
9 14
    <script type="text/javascript" src="vendor/crypto-js/core-min.js"></script>
10 15
    <script type="text/javascript" src="vendor/crypto-js/enc-base64-min.js"></script>
......
12 17

  
13 18
    <script type="text/javascript" src="js/opennebula.js"></script>
14 19
    <script type="text/javascript" src="js/login.js"></script>
15

  
16 20
</head>
17 21

  
18

  
19 22
<body>
20

  
21
<% if settings.config[:auth] == "x509" %>
22
  <%= erb :_login_x509 %>
23
<% unless settings.config[:openid][:enabled] %>
24
  <% if settings.config[:auth] == "x509" %>
25
    <%= erb :_login_x509 %>
26
  <% else %>
27
    <%= erb :_login_standard %>
28
  <% end %>
23 29
<% else %>
24
  <%= erb :_login_standard %>
25
<% end %>
30
  <div id="wrapper">
31
    <div id="logo_sunstone" style="background: url(<%=$views_config.logo%>) no-repeat center; background-size: 355px;"></div>
26 32

  
33
    <div id="login_tabs">
34
      <ul>
35
        <li><a href="#tab_auth_local">Local auth</a></li>
36
        <li><a href="#tab_auth_openid">OpenID</a></li>
37
        <li><a id="identities_link" href="#tab_auth_identities">Claimed Identities</a></li>
38
      </ul>
39
      <div id="tab_auth_local">
40
        <%= erb :_login_standard_new %>
41
      </div>
42
      <div id="tab_auth_openid">
43
        <%= erb :_openid %>
44
      </div>
45
      <div id="tab_auth_identities">
46
        <span id="identities_none">No identities</span>
47
        <ul id="openid_serverlist"></ul>
48
      </div>
49
    </div>
50
  </div>
51
<% end %>
27 52

  
28 53
<div id="footer" style="overflow:visible;">
29 54
    <a href="http://opennebula.org" target="_blank">OpenNebula 4.4.0</a> by <a href="http://c12g.com" target="_blank">C12G Labs</a>.