Projet

Général

Profil

0001-provisionning-log-received-provisionning-messages-an.patch

Benjamin Dauvergne, 13 septembre 2021 14:36

Télécharger (11,4 ko)

Voir les différences:

Subject: [PATCH] provisionning: log received provisionning messages and
 actions (#56907)

 .../common/management/commands/hobo_notify.py |  5 ++
 hobo/multitenant/utils.py                     | 15 +++--
 hobo/provisionning/middleware.py              |  6 ++
 hobo/provisionning/utils.py                   | 63 +++++++++++++++----
 4 files changed, 73 insertions(+), 16 deletions(-)
hobo/agent/common/management/commands/hobo_notify.py
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import json
18
import logging
18 19
import os
19 20
import sys
20 21

  
......
24 25
from hobo.multitenant.middleware import TenantMiddleware
25 26
from hobo.provisionning.utils import NotificationProcessing, TryAgain
26 27

  
28
logger = logging.getLogger(__name__)
29

  
27 30

  
28 31
class Command(BaseCommand, NotificationProcessing):
29 32
    requires_system_checks = False
......
60 63
        if entity_id not in audience:
61 64
            return
62 65
        object_type = notification['objects']['@type']
66
        msg = 'received request for %sing %%d %%s objects (Celery)' % action
67
        logger.info(msg, len(notification['objects']['data']), object_type)
63 68
        for i in range(20):
64 69
            try:
65 70
                getattr(cls, 'provision_' + object_type)(
hobo/multitenant/utils.py
12 12
        return
13 13
    logger = logging.getLogger(__name__)
14 14

  
15
    existing_pks = user.groups.values_list('pk', flat=True)
16
    for role in Role.objects.filter(uuid__in=uuids).exclude(pk__in=existing_pks):
15
    existing_pks = set(user.groups.values_list('pk', flat=True))
16
    uuids = set(uuids)
17
    not_found = uuids.copy()
18
    for role in Role.objects.filter(uuid__in=uuids):
19
        not_found.discard(role.uuid)
20
        if role.pk in existing_pks:
21
            continue
17 22
        user.groups.through.objects.get_or_create(group=role, user=user)
18
        logger.info(u'adding role %s to %s (%s)', role, user, user.pk)
23
        logger.info('adding role %s to %s (%s)', role, user, user.pk)
19 24
    qs = user.groups.through.objects.filter(user=user, group__role__isnull=False).exclude(
20 25
        group__role__uuid__in=uuids
21 26
    )
......
26 31
        except DatabaseError:
27 32
            pass
28 33
        else:
29
            logger.info(u'removed role %s from %s (%s)', rel.group, user, user.pk)
34
            logger.info('removed role %s from %s (%s)', rel.group, user, user.pk)
35
    for uuid in not_found:
36
        logger.warning('role %s of user %s does not exist', uuid, user)
hobo/provisionning/middleware.py
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import json
18
import logging
18 19

  
19 20
from django.conf import settings
20 21
from django.http import HttpResponseBadRequest, HttpResponseForbidden, JsonResponse
......
25 26
from hobo.provisionning.utils import NotificationProcessing, TryAgain
26 27
from hobo.rest_authentication import PublikAuthentication, PublikAuthenticationFailed
27 28

  
29
logger = logging.getLogger(__name__)
30

  
28 31

  
29 32
class ProvisionningMiddleware(MiddlewareMixin, NotificationProcessing):
30 33
    def process_request(self, request):
......
51 54
            return HttpResponseBadRequest()
52 55
        full = notification['full'] if 'full' in notification else False
53 56

  
57
        msg = 'received request for %sing %%d %%s objects (HTTP)' % action
58
        logger.info(msg, len(notification['objects']['data']), object_type)
59

  
54 60
        for i in range(20):
55 61
            try:
56 62
                getattr(self, 'provision_' + object_type)(
hobo/provisionning/utils.py
26 26
from hobo.agent.common.models import Role
27 27
from hobo.multitenant.utils import provision_user_groups
28 28

  
29
logger = logging.getLogger(__name__)
30

  
29 31

  
30 32
class TryAgain(Exception):
31 33
    pass
......
72 74
            try:
73 75
                with atomic():
74 76
                    if action == 'provision':
77
                        new = False
75 78
                        assert cls.check_valid_user(o)
76 79
                        try:
77 80
                            mellon_user = UserSAMLIdentifier.objects.get(issuer=issuer, name_id=o['uuid'])
......
85 88
                                # temp user object
86 89
                                random_uid = str(random.randint(1, 10000000000000))
87 90
                                user = User.objects.create(username=random_uid)
91
                                new = True
88 92
                            mellon_user = UserSAMLIdentifier.objects.create(
89 93
                                user=user, issuer=issuer, name_id=o['uuid']
90 94
                            )
......
98 102
                        user.save()
99 103
                        role_uuids = [role['uuid'] for role in o.get('roles', [])]
100 104
                        provision_user_groups(user, role_uuids)
105
                        msg = '%s user %%s' % ('provisionned new' if new else 'updated')
106
                        user_description = ''
107
                        if user.email:
108
                            user_description += user.email + ' '
109
                        user_description += '(%s)' % o['uuid']
110
                        logger.info(msg, user_description)
101 111
                    elif action == 'deprovision':
102 112
                        assert 'uuid' in o
103 113
                uuids.add(o['uuid'])
104 114
            except IntegrityError:
105 115
                raise TryAgain
106 116
        if full and action == 'provision':
107
            for usi in UserSAMLIdentifier.objects.exclude(name_id__in=uuids):
117
            qs = UserSAMLIdentifier.objects.exclude(name_id__in=uuids)
118
            logger.info(
119
                'deprovisionning users %s',
120
                ', '.join(
121
                    ((email + ' ' if email else '') + '(%s)' % username)
122
                    for email, username in qs.values_list('email', 'username')
123
                ),
124
            )
125
            for usi in qs:
108 126
                usi.user.delete()
109 127
        elif action == 'deprovision':
110
            for user in User.objects.filter(saml_identifiers__name_id__in=uuids):
128
            qs = User.objects.filter(saml_identifiers__name_id__in=uuids)
129
            for user in qs:
111 130
                user.delete()
131
            logger.info(
132
                'deprovisionning users %s',
133
                ', '.join(
134
                    ((email + ' ' if email else '') + '(%s)' % username)
135
                    for email, username in qs.values_list('email', 'username')
136
                ),
137
            )
112 138

  
113 139
    group_name_max_length = Group._meta.get_field('name').max_length
114 140

  
......
125 151

  
126 152
    @classmethod
127 153
    def provision_role(cls, issuer, action, data, full=False):
128
        logger = logging.getLogger(__name__)
129 154
        uuids = set()
130 155
        for o in data:
131 156
            assert 'uuid' in o
132 157
            uuids.add(o['uuid'])
133 158
            if action == 'provision':
159
                created = False
160
                save = False
134 161
                assert cls.check_valid_role(o)
135 162
                role_name = cls.truncate_role_name(o['name'])
136 163
                try:
137 164
                    role = Role.objects.get(uuid=o['uuid'])
138
                    created = False
139 165
                except Role.DoesNotExist:
140 166
                    try:
141 167
                        with atomic():
......
144 170
                                defaults={
145 171
                                    'uuid': o['uuid'],
146 172
                                    'description': o['description'],
147
                                    'details': o.get('details', u''),
173
                                    'details': o.get('details', ''),
148 174
                                    'emails': o.get('emails', []),
149 175
                                    'emails_to_members': o.get('emails_to_members', True),
150 176
                                },
151 177
                            )
152 178
                    except IntegrityError:
153 179
                        # Can happen if uuid and name already exist
154
                        logger.error(u'cannot provision role "%s" (%s)', o['name'], o['uuid'])
180
                        logger.error('cannot provision role "%s" (%s)', o['name'], o['uuid'])
155 181
                        continue
156 182
                if not created:
157
                    save = False
158 183
                    if role.name != role_name:
159 184
                        role.name = role_name
160 185
                        save = True
......
164 189
                    if role.description != o['description']:
165 190
                        role.description = o['description']
166 191
                        save = True
167
                    if role.details != o.get('details', u''):
168
                        role.details = o.get('details', u'')
192
                    if role.details != o.get('details', ''):
193
                        role.details = o.get('details', '')
169 194
                        save = True
170 195
                    if role.emails != o.get('emails', []):
171 196
                        role.emails = o.get('emails', [])
......
179 204
                                role.save()
180 205
                        except IntegrityError:
181 206
                            # Can happen if uuid and name already exist
182
                            logger.error(u'cannot provision role "%s" (%s)', o['name'], o['uuid'])
207
                            logger.error('cannot provision role "%s" (%s)', o['name'], o['uuid'])
183 208
                            continue
209
                if created:
210
                    logger.info('provisionned new role %s (%s)', o['name'], o['uuid'])
211
                if save:
212
                    logger.info('updated role %s (%s)', o['name'], o['uuid'])
184 213
        if full and action == 'provision':
185
            for role in Role.objects.exclude(uuid__in=uuids):
214
            qs = Role.objects.exclude(uuid__in=uuids)
215
            logger.info(
216
                'deprovisionning roles %s',
217
                ', '.join('%s (%s)' % (name, uuid) for name, uuid in qs.values_list('name', 'uuid')),
218
            )
219
            for role in qs:
186 220
                role.delete()
187 221
        elif action == 'deprovision':
188
            for role in Role.objects.filter(uuid__in=uuids):
222
            qs = Role.objects.filter(uuid__in=uuids)
223
            logger.info(
224
                'deprovisionning roles %s',
225
                ', '.join('%s (%s)' % (name, uuid) for name, uuid in qs.values_list('name', 'uuid')),
226
            )
227
            for role in qs:
189 228
                role.delete()
190
-