Projet

Général

Profil

0001-new-notify-command-to-handle-role-provisionning-depr.patch

Benjamin Dauvergne, 09 septembre 2015 10:51

Télécharger (4,91 ko)

Voir les différences:

Subject: [PATCH] new notify command to handle role
 provisionning/deprovisionning messages (fixes #8219)

It gets wcs roles from uuid or slug of the authentic2 role; if role is
using a slug it's replaced by the uuid. It handles rename by using uuid
as the slug of roles.

Targetted tenants are identified through their SAML entity id.
 wcs/ctl/notify.py | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)
 create mode 100644 wcs/ctl/notify.py
wcs/ctl/notify.py
1
# w.c.s. - web application for online forms
2
# Copyright (C) 2005-2014  Entr'ouvert
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16

  
17
import os
18
import sys
19
import json
20

  
21
from wcs.roles import Role
22
from qommon.ctl import Command
23
from qommon.publisher import get_cfg
24

  
25

  
26
class CmdNotify(Command):
27
    name = 'notify'
28

  
29
    def load_notification(args):
30
        if args[1] == '-':
31
            # get environment definition from stdin
32
            return json.load(sys.stdin)
33
        else:
34
            return json.load(file(args[1]))
35

  
36
    def execute(self, base_options, sub_options, args):
37
        import publisher
38

  
39
        self.base_options = base_options
40
        if sub_options.extra:
41
            if not self.config.has_section('extra'):
42
                self.config.add_section('extra')
43
            for i, extra in enumerate(sub_options.extra):
44
                self.config.set('extra', 'cmd_line_extra_%d' % i, extra)
45
        publisher.WcsPublisher.configure(self.config)
46
        pub = publisher.WcsPublisher.create_publisher()
47

  
48
        global_app_dir = pub.app_dir
49

  
50
        notification = self.load_notification(args)
51

  
52
        if not isinstance(notification, dict) \
53
            or '@type' not in notification \
54
            or notification['@type'] not in ['provision', 'deprovision'] \
55
            or 'objects' not in notification \
56
            or 'audience' not in notification \
57
            or not isinstance(notification['audience'], list) \
58
                or not isinstance(notification['objects'], list):
59
            sys.exit(1)
60
        action = notification['@type']
61
        audience = notification['audience']
62
        full = notification['full'] if 'full' in notification else False
63
        for hostname in os.listdir(global_app_dir):
64
            pub.app_dir = os.path.join(global_app_dir, hostname)
65
            pub.set_config()
66
            # Verify tenant is in audience
67
            entity_id = get_cfg('sp', {}).get('saml2_providerid')
68
            if not entity_id or entity_id not in audience:
69
                continue
70

  
71
            uuids = set()
72
            # Now provision/deprovision
73
            for o in notification['objects']:
74
                t = o['@type']
75
                if t != 'role' \
76
                   or 'uuid' not in o \
77
                   or 'name' not in o \
78
                   or 'slug' not in o:
79
                    continue
80
                uuid = o['uuid'].encode(publisher.site_charset)
81
                uuids.add(uuid)
82
                slug = o['slug'].encode(publisher.site_charset)
83
                name = o['name'].encode(publisher.site_charset)
84
                # Find existing role
85
                try:
86
                    role = Role.get_on_index(uuid, 'slug')
87
                except KeyError:
88
                    try:
89
                        role = Role.get_on_index(slug, 'slug')
90
                    except KeyError:
91
                        # New role
92
                        if action != 'provision':
93
                            continue
94
                        role = Role(name=name)
95
                if action == 'provision':
96
                    # Provision/rename
97
                    role.name = name
98
                    role.slug = uuid
99
                    role.store()
100
                elif action == 'deprovision':
101
                    # Deprovision
102
                    role.remove_self()
103
            # All roles have been sent
104
            if full:
105
                for role in Role.select():
106
                    if role.slug not in uuids:
107
                        role.remove_self()
0
-