Projet

Général

Profil

0001-WIP-ldap_backend-groups-to-A2-roles-mapping-16523.patch

Paul Marillonnet, 04 décembre 2017 18:00

Télécharger (7,52 ko)

Voir les différences:

Subject: [PATCH] WIP ldap_backend: groups to A2 roles mapping (#16523)

 src/authentic2/backends/ldap_backend.py | 56 +++++++++++++++++----------------
 tests/test_ldap.py                      | 46 +++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 27 deletions(-)
src/authentic2/backends/ldap_backend.py
221 221
        'sync_ldap_users_filter': None,
222 222
        'user_basedn': None,
223 223
        'group_dn_template': None,
224
        'member_of_attribute': None,
224
        'member_of_attribute': None,  # DEPRECATED
225
        'group_member_of_attribute': None,
225 226
        'group_filter': '(&(member={user_dn})(objectClass=groupOfNames))',
226 227
        'group': None,
227 228
        'groupsu': None,
228 229
        'groupstaff': None,
229 230
        'groupactive': None,
230
        'group_mapping': (),
231
        'group_mapping': (),  # DEPRECATED
232
        'group_to_role_mapping': (),
231 233
        'replicas': True,
232 234
        'email_field': 'mail',
233 235
        'fname_field': 'givenName',
......
521 523
                setattr(user, attr, v)
522 524
                user._changed = True
523 525

  
524
    def populate_groups_by_mapping(self, user, dn, conn, block, group_dns):
525
        '''Assign group to user based on a mapping from group DNs'''
526
        group_mapping = block['group_mapping']
527
        if not group_mapping:
526
    def populate_roles_by_mapping(self, user, dn, conn, block, role_dns):
527
        '''Assign role to user based on a mapping from group DNs'''
528
        group_to_role_mapping = block.get('group_to_role_mapping')
529
        if not group_to_role_mapping:
528 530
            return
529 531
        if not user.pk:
530 532
            user.save()
531 533
            user._changed = False
532
        groups = user.groups.all()
533
        for dn, group_names in group_mapping:
534
            for group_name in group_names:
535
                group = self.get_group_by_name(block, group_name)
536
                if group is None:
534
        roles = user.roles.all()
535
        for dn, role_names in group_to_role_mapping:
536
            for role_name in role_names:
537
                role = self.get_role_by_name(block, role_name)
538
                if role is None:
537 539
                    continue
538
                # Add missing groups
539
                if dn in group_dns and group not in groups:
540
                    user.groups.add(group)
541
                # Remove extra groups
542
                elif dn not in group_dns and group in groups:
543
                    user.groups.remove(group)
540
                # Add missing roles
541
                if dn in role_dns and role not in roles:
542
                    user.roles.add(role)
543
                # Remove extra roles
544
                elif dn not in role_dns and role in roles:
545
                    user.roles.remove(role)
544 546

  
545 547
    def get_ldap_group_dns(self, user, dn, conn, block, attributes):
546 548
        '''Retrieve group DNs from the LDAP by attributes (memberOf) or by
547 549
           filter.
548 550
        '''
549 551
        group_base_dn = block.get('group_basedn', block['basedn'])
550
        member_of_attribute = block['member_of_attribute']
552
        group_member_of_attribute = block['group_member_of_attribute']
551 553
        group_filter = block['group_filter']
552 554
        group_dns = set()
553
        if member_of_attribute:
554
            member_of_attribute = str(member_of_attribute)
555
            results = conn.search_s(dn, ldap.SCOPE_BASE, '', [member_of_attribute])
556
            group_dns.update(results[0][1].get(member_of_attribute, []))
555
        if group_member_of_attribute:
556
            group_member_of_attribute = str(group_member_of_attribute)
557
            results = conn.search_s(dn, ldap.SCOPE_BASE, '', [group_member_of_attribute])
558
            group_dns.update(results[0][1].get(group_member_of_attribute, []))
557 559
        if group_filter:
558 560
            group_filter = str(group_filter)
559 561
            params = attributes.copy()
......
568 570
                group_dns.update(dn for dn, attributes in results if dn)
569 571
        return group_dns
570 572

  
571
    def populate_user_groups(self, user, dn, conn, block, attributes):
573
    def populate_user_roles(self, user, dn, conn, block, attributes):
572 574
        group_dns = self.get_ldap_group_dns(user, dn, conn, block, attributes)
573
        log.debug('groups for dn %r: %r', dn, group_dns)
574
        self.populate_admin_flags_by_group(user, block, group_dns)
575
        self.populate_groups_by_mapping(user, dn, conn, block, group_dns)
575
        log.debug('roles for dn %r: %r', dn, group_dns)
576
        # Admin flags by roles ?
577
        self.populate_roles_by_mapping(user, dn, conn, block, group_dns)
576 578

  
577 579
    def get_group_by_name(self, block, group_name, create=None):
578 580
        '''Obtain a Django group'''
......
648 650
        self.update_user_identifiers(user, username, block, attributes)
649 651
        self.populate_mandatory_groups(user, block)
650 652
        self.populate_mandatory_roles(user, block)
651
        self.populate_user_groups(user, dn, conn, block, attributes)
653
        self.populate_user_roles(user, dn, conn, block, attributes)
652 654

  
653 655
    def populate_user_ou(self, user, dn, conn, block, attributes):
654 656
        '''Assign LDAP user to an ou, the default one if ou_slug setting is
tests/test_ldap.py
272 272

  
273 273

  
274 274
@pytest.mark.django_db
275
def test_group_to_role_mapping(slapd, settings, client):
276
    from authentic2.a2_rbac.models import Role
277

  
278
    settings.LDAP_AUTH_SETTINGS = [{
279
        'url': [slapd.ldap_url],
280
        'basedn': 'o=orga',
281
        'use_tls': False,
282
        'create_role': True,
283
        'group_to_role_mapping': [
284
            ('cn=group1,o=orga', ['Group1']),
285
        ],
286
    }]
287
    assert Role.objects.filter(name='Group1').count() == 0
288
    response = client.post('/login/', {'login-password-submit': '1',
289
                                       'username': USERNAME,
290
                                       'password': PASS}, follow=True)
291
    assert Role.objects.filter(name='Group1').count() == 1
292
    assert response.context['user'].username == u'%s@ldap' % USERNAME
293
    assert response.context['user'].roles.count() == 1
294

  
295

  
296
@pytest.mark.django_db
297
def test_posix_group_to_role_mapping(slapd, settings, client):
298
    from authentic2.a2_rbac.models import Role
299

  
300
    settings.LDAP_AUTH_SETTINGS = [{
301
        'url': [slapd.ldap_url],
302
        'basedn': 'o=orga',
303
        'use_tls': False,
304
        'create_role': True,
305
        'group_to_role_mapping': [
306
            ('cn=group2,o=orga', ['Group2']),
307
        ],
308
        'group_filter': '(&(memberUid={uid})(objectClass=posixGroup))',
309
    }]
310
    assert Role.objects.filter(name='Group2').count() == 0
311
    response = client.post('/login/', {'login-password-submit': '1',
312
                                       'username': USERNAME,
313
                                       'password': PASS}, follow=True)
314
    assert Role.objects.filter(name='Group2').count() == 1
315
    assert response.context['user'].username == u'%s@ldap' % USERNAME
316
    assert response.context['user'].roles.count() == 1
317

  
318

  
319

  
320
@pytest.mark.django_db
275 321
def test_group_su(slapd, settings, client):
276 322
    from django.contrib.auth.models import Group
277 323

  
278
-