Project

General

Profile

Revision ddbaec88

IDddbaec886274cfe4c6b7eb09b14f5baa774e0fdf
Parent 98760d1b
Child fc43af7e

Added by Francois POIROTTE almost 13 years ago

Activation du cache des permissions (#577)

Modifie l'ordre des middlewares WSGI afin que les couches apportées par
Beaker (gestion du cache et gestion des sessions) soient disponibles
depuis les couches d'authentification/autorisations (repoze.who et
repoze.what).

Ceci permet d'activer réellement le cache des permissions au niveau du
plugin Kerberos (auparavant, la fonctionnalité était présent, mais
inutilisable car Beaker ne se trouvait pas dans la pile de couches).

Ce changeset remplace également le plugin d'authentification Kerberos
pour supprimer les méthodes responsables de l'identification et de
l'authentification de l'utilisateur par une unique méthode d'ajout de
méta-données (mdprovider).
De fait, le plugin sera correctement appelé avec le nouveau code pour la
pile d'authentification (afin de créer l'utilisateur dans Vigilo
correspondant à l'utilisateur externe).
Le plugin a été renommé (nom plus explicite/réaliste) et déplacé à cet
endroit : `vigilo.turbogears.repoze.plugins.mdldapsync`.
Ceci introduit une dépendance sur python-ldap dans vigilo.turbogears.

Ce changement centralise tout ce qui concerne repoze.wh(o|at) dans
vigilo.turbogears.repoze.
Le classifier a été modifié pour identifier spécifiquement les requêtes
authentifiée par un mécanisme externe (ex: Kerberos).
Les plugins ont vu leur nom changer radicalement et se trouvent
désormais chacun dans un fichier séparé (sqlauth, mduser, mdgroups).

Un nouveau module (d'identification) pour repoze.who a été ajouté dans
`vigilo.turbogears.repoze.plugins.externalid`. Ce module permet de
pré-authentifier un utilisateur à partir du contenu d'une session
Beaker. Il sera utilisé avec `mdldapsync` qui mémorise déjà l'identité
d'un utilisateur authentifié via un mécanisme externe dans la session
Beaker.

Les fichiers .ini des différentes IHM ont été mis à jour en conséquence.

Les méthodes liées à l'authentification dans les contrôleurs !TurboGears
ont été mises en commun dans `vigilo.turbogears.controllers.auth`.

Refs: #577.
Change-Id: Ia2d600622fd623e1a4474a4ea24fef3b3b503c12
Reviewed-on: https://vigilo-dev.si.c-s.fr/review/377
Tested-by: Build system <>
Reviewed-by: Aurelien BOMPARD <>

View differences:

deployment/who.ini
5 5

  
6 6
[plugin:basicauth]
7 7
use = repoze.who.plugins.basicauth:make_plugin
8
realm=Vigilo
8
realm = Vigilo
9 9

  
10 10
[plugin:friendlyform]
11 11
use = repoze.who.plugins.friendlyform:FriendlyFormPlugin
......
16 16
post_login_url = /post_login
17 17
post_logout_url = /post_logout
18 18

  
19
[plugin:sqlauth]
20
use = vigilo.turbogears.repoze_plugins:auth_plugin
21

  
22 19
[general]
23
;request_classifier = repoze.who.classifiers:default_request_classifier
24
request_classifier = vigilo.turbogears.repoze_plugins:vigilo_api_classifier
20
request_classifier = vigilo.turbogears.repoze.classifier:vigilo_classifier
25 21
challenge_decider = repoze.who.classifiers:default_challenge_decider
26 22

  
27 23
[identifiers]
......
32 28

  
33 29
[authenticators]
34 30
plugins =
35
    sqlauth
31
    vigilo.turbogears.repoze.plugins.sqlauth:plugin
36 32

  
37 33
[challengers]
38 34
plugins =
......
41 37

  
42 38
[mdproviders]
43 39
plugins =
44
    vigilo.turbogears.repoze_plugins:md_plugin
45
    vigilo.turbogears.repoze_plugins:md_group_plugin
40
    vigilo.turbogears.repoze.plugins.mduser:plugin
41
    vigilo.turbogears.repoze.plugins.mdgroups:plugin
test.ini
17 17

  
18 18
[app:main]
19 19
sqlalchemy.url = sqlite:///:memory:
20
;sqlalchemy.url = sqlite:////tmp/test-vigiboard.sqlite
21 20
db_basename = vigilo_
22
use_kerberos = False
23 21
vigiboard_items_per_page = 10
24 22
use = config:development.ini
25 23

  
26 24
[app:main_without_authn]
27 25
use = main
28 26
skip_authentication = True
29

  
vigiboard/config/middleware.py
26 26
from pkg_resources import resource_filename
27 27
from paste.cascade import Cascade
28 28
from paste.urlparser import StaticURLParser
29
from vigilo.turbogears.repoze_who import make_middleware_with_config
30
from logging import getLogger
31 29

  
32 30
__all__ = ['make_app']
33 31

  
......
56 54
    """
57 55
    app = make_base_app(global_conf, full_stack=full_stack, **app_conf)
58 56

  
59
    # Ajout du middleware d'authentification.
60
    app = make_middleware_with_config(
61
        app, global_conf,
62
        app_conf.get('auth.config', 'who.ini'),
63
        None,
64
        None,
65
        app_conf.get('skip_authentication')
66
    )
67
    # On force l'utilisation d'un logger nommé "auth"
68
    # pour la compatibilité avec TurboGears.
69
    app.logger = getLogger('auth')
70

  
71 57
    # On définit 2 middlewares pour fichiers statiques qui cherchent
72 58
    # les fichiers dans le thème actuellement chargé.
73 59
    # Le premier va les chercher dans le dossier des fichiers spécifiques
vigiboard/controllers/root.py
48 48
from vigilo.models.tables.secondary_tables import EVENTSAGGREGATE_TABLE, \
49 49
        USER_GROUP_TABLE, SUPITEM_GROUP_TABLE
50 50

  
51
from vigilo.turbogears.controllers.auth import AuthController
52
from vigilo.turbogears.controllers.error import ErrorController
51 53
from vigilo.turbogears.controllers.autocomplete import AutoCompleteController
52 54
from vigilo.turbogears.controllers.proxy import ProxyController
53 55
from vigilo.turbogears.controllers.api.root import ApiRootController
54 56
from vigilo.turbogears.helpers import get_current_user
55 57

  
56 58
from vigiboard.controllers.vigiboardrequest import VigiboardRequest
57
from vigiboard.controllers.vigiboard_controller import VigiboardRootController
58 59
from vigiboard.controllers.feeds import FeedsController
59 60

  
60 61
from vigiboard.widgets.edit_event import edit_event_status_options, \
......
68 69
           'date_to_timestamp')
69 70

  
70 71
# pylint: disable-msg=R0201
71
class RootController(VigiboardRootController):
72
class RootController(AuthController):
72 73
    """
73 74
    Le controller général de vigiboard
74 75
    """
76
    error = ErrorController()
75 77
    autocomplete = AutoCompleteController()
76 78
    nagios = ProxyController('nagios', '/nagios/',
77 79
        not_anonymous(l_('You need to be authenticated')))
......
621 623
                                    'address': request.remote_addr,
622 624
                                    'idevent': event.idcause,
623 625
                                })
624
 
626

  
625 627
                history = EventHistory(
626 628
                        type_action=u"Acknowledgement change state",
627 629
                        idevent=event.idcause,
vigiboard/controllers/vigiboard_controller.py
1
# -*- coding: utf-8 -*-
2
# vim:set expandtab tabstop=4 shiftwidth=4:
3
################################################################################
4
#
5
# Copyright (C) 2007-2011 CS-SI
6
#
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License version 2 as
9
# published by the Free Software Foundation.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
################################################################################
20

  
21
"""
22
Controller for authentification
23
"""
24
import logging
25
from tg import expose, flash, request, redirect
26
from pylons.i18n import ugettext as _
27

  
28
from vigilo.turbogears.controllers import BaseController
29
from vigilo.turbogears.controllers.error import ErrorController
30

  
31
LOGGER = logging.getLogger(__name__)
32

  
33
# pylint: disable-msg=R0201
34
class VigiboardRootController(BaseController):
35
    """
36
    The root controller for the vigiboard application.
37

  
38
    All the other controllers and WSGI applications should be mounted on this
39
    controller. For example::
40

  
41
        panel = ControlPanelController()
42
        another_app = AnotherWSGIApplication()
43

  
44
    Keep in mind that WSGI applications shouldn't be mounted directly: They
45
    must be wrapped around with :class:`tg.controllers.WSGIAppController`.
46
    """
47

  
48
    error = ErrorController()
49

  
50
    @expose('login.html')
51
    def login(self, came_from='/'):
52
        """Start the user login."""
53
        login_counter = request.environ['repoze.who.logins']
54
        if login_counter > 0:
55
            flash(_('Wrong credentials'), 'warning')
56
        return dict(page='login', login_counter=str(login_counter),
57
                    came_from=came_from)
58

  
59
    @expose()
60
    def post_login(self, came_from='/'):
61
        """
62
        Redirect the user to the initially requested page on successful
63
        authentication or redirect her back to the login page if login failed.
64
        """
65
        if not request.identity:
66
            login_counter = request.environ['repoze.who.logins'] + 1
67
            redirect('/login', came_from=came_from, __logins=login_counter)
68
        userid = request.identity['repoze.who.userid']
69
        LOGGER.info(_('"%(username)s" logged in (from %(IP)s)') % {
70
                'username': userid,
71
                'IP': request.remote_addr,
72
            })
73
        flash(_('Welcome back, %s!') % userid)
74
        redirect(came_from)
75

  
76
    @expose()
77
    def post_logout(self, came_from='/'):
78
        """
79
        Redirect the user to the initially requested page on logout and say
80
        goodbye as well.
81
        """
82
        LOGGER.info(_('Some user logged out (from %(IP)s)') % {
83
                'IP': request.remote_addr,
84
            })
85
        flash(_('We hope to see you soon!'))
86
        redirect(came_from)
vigiboard/tests/functional/test_group_selection_tree.py
51 51
            json, {'items': [], 'groups': []}
52 52
        )
53 53

  
54
    def test_get_group_when_not_allowed(self):
55
        """Récupération de l'étage de l'arbre sans les droits"""
56

  
54
    def test_get_group_anonymous(self):
55
        """Récupération de l'étage de l'arbre en anonyme"""
57 56
        # Récupération du groupe utilisé lors de ce test.
58 57
        group2 = SupItemGroup.by_group_name(u'group2')
59 58

  
......
62 61
        response = self.app.get('/get_groups?parent_id=%d' % group2.idgroup,
63 62
            status=401)
64 63

  
64
    def test_get_group_when_not_allowed(self):
65
        """Récupération de l'étage de l'arbre sans les droits"""
66

  
67
        # Récupération du groupe utilisé lors de ce test.
68
        group2 = SupItemGroup.by_group_name(u'group2')
69

  
65 70
        # L'utilisateur est authentifié avec des permissions
66 71
        # restreintes. Il cherche à obtenir la liste des groupes fils
67 72
        # d'un groupe auquel il n'a pas accès, même indirectement.
......
93 98
        # bien les groupes fils de ce groupe parent
94 99
        self.assertEqual(
95 100
            json, {
96
                'items': [], 
101
                'items': [],
97 102
                'groups': [
98 103
                    {'id': maingroup.idgroup, 'name': maingroup.name, 'type': 'group'}
99 104
                ]
......
111 116
        # bien les groupes fils de ce groupe parent
112 117
        self.assertEqual(
113 118
            json, {
114
                'items': [], 
119
                'items': [],
115 120
                'groups': [
116 121
                    {'id': maingroup.idgroup, 'name': maingroup.name, 'type': 'group'}
117 122
                ]
......
127 132
        # On s'assure que la liste retournée contient
128 133
        # bien les groupes fils de ce groupe parent.
129 134
        self.assertEqual(json, {
130
                'items': [], 
135
                'items': [],
131 136
                'groups': [
132 137
                    {'id': group1.idgroup, 'name': group1.name, 'type': 'group'},
133 138
                    {'id': group2.idgroup, 'name': group2.name, 'type': 'group'}
......
145 150
        # On s'assure que la liste retournée contient bien ce groupe fils.
146 151
        self.assertEqual(
147 152
            json, {
148
                'items': [], 
153
                'items': [],
149 154
                'groups': [
150 155
                    {'id': group1.idgroup, 'name': group1.name, 'type': 'group'}
151 156
                ]
......
162 167
        # le groupe parent du groupe auquel il a accès.
163 168
        self.assertEqual(
164 169
            json, {
165
                'items': [], 
170
                'items': [],
166 171
                'groups': [
167 172
                    {'id': maingroup.idgroup, 'name': maingroup.name, 'type': 'group'}
168 173
                ]
......
184 189
        # On s'assure que la liste retournée contient bien le groupe racine.
185 190
        self.assertEqual(
186 191
            json, {
187
                'items': [], 
192
                'items': [],
188 193
                'groups': [
189 194
                    {'id': root.idgroup, 'name': root.name, 'type': 'group'}
190 195
                ]
......
201 206
        # groupe racine, auquel cet utilisateur a directement accès.
202 207
        self.assertEqual(
203 208
            json, {
204
                'items': [], 
209
                'items': [],
205 210
                'groups': [
206 211
                    {'id': root.idgroup, 'name': root.name, 'type': 'group'}
207 212
                ]
......
218 223
        # groupe racine, auquel cet utilisateur a indirectement accès.
219 224
        self.assertEqual(
220 225
            json, {
221
                'items': [], 
226
                'items': [],
222 227
                'groups': [
223 228
                    {'id': root.idgroup, 'name': root.name, 'type': 'group'}
224 229
                ]
225 230
            }
226 231
        )
227 232

  
233
    def test_get_root_group_anonymous(self):
234
        """Récupération des groupes racines de l'arbre en anonyme"""
235
        # L'utilisateur n'est pas authentifié, et cherche
236
        # à obtenir la liste des groupes racines de l'arbre.
237
        response = self.app.get('/get_groups', status=401)
238

  
239

  
228 240
    def test_get_root_group_when_not_allowed(self):
229 241
        """Récupération des groupes racines de l'arbre sans les droits"""
230

  
231 242
        # Récupération du groupe utilisé lors de ce test.
232 243
        root = SupItemGroup.by_group_name(u'root')
233 244

  
234
        # L'utilisateur n'est pas authentifié, et cherche
235
        # à obtenir la liste des groupes racines de l'arbre.
236
        response = self.app.get('/get_groups', status=401)
237

  
238 245
        # Création d'un nouvel utilisateur et d'un nouveau groupe
239 246
        usergroup = UserGroup(group_name=u'new_users')
240 247
        vigiboard_perm = Permission.by_permission_name(u'vigiboard-access')
......
246 253
        )
247 254
        user.usergroups.append(usergroup)
248 255
        DBSession.add(user)
256
        DBSession.flush()
257
        transaction.commit()
249 258

  
250 259
        # L'utilisateur est authentifié mais n'a aucun accès. Il
251 260
        # cherche à obtenir la liste des groupes racines de l'arbre.
......
256 265
        # On s'assure que la liste retournée est bien vide.
257 266
        self.assertEqual(
258 267
            json, {
259
                'items': [], 
268
                'items': [],
260 269
                'groups': []
261 270
            }
262 271
        )
263

  
who.ini
5 5

  
6 6
[plugin:basicauth]
7 7
use = repoze.who.plugins.basicauth:make_plugin
8
realm=Vigilo
8
realm = Vigilo
9 9

  
10 10
[plugin:friendlyform]
11 11
use = repoze.who.plugins.friendlyform:FriendlyFormPlugin
......
16 16
post_login_url = /post_login
17 17
post_logout_url = /post_logout
18 18

  
19
[plugin:sqlauth]
20
use = vigilo.turbogears.repoze_plugins:auth_plugin
21

  
22 19
;[plugin:kerberos]
23 20
;use = repoze.who.plugins.vigilo.kerberos:VigiloKerberosAuthenticator
24 21
;ldap_url = ldap://ldap.example.com
......
30 27
;bindpw = mybindpassword
31 28

  
32 29
[general]
33
request_classifier = vigilo.turbogears.repoze_plugins:vigilo_api_classifier
30
request_classifier = vigilo.turbogears.repoze.classifier:vigilo_classifier
34 31
challenge_decider = repoze.who.classifiers:default_challenge_decider
35 32

  
36 33
[identifiers]
......
41 38

  
42 39
[authenticators]
43 40
plugins =
44
    sqlauth
41
    vigilo.turbogears.repoze.plugins.sqlauth:plugin
45 42

  
46 43
[challengers]
47 44
plugins =
......
50 47

  
51 48
[mdproviders]
52 49
plugins =
53
    vigilo.turbogears.repoze_plugins:md_plugin
54
    vigilo.turbogears.repoze_plugins:md_group_plugin
50
    vigilo.turbogears.repoze.plugins.mduser:plugin
51
    vigilo.turbogears.repoze.plugins.mdgroups:plugin

Also available in: Unified diff