Projet

Général

Profil

0001-agent-authentic2-add-an-hobo_provision-command-19853.patch

Benjamin Dauvergne, 18 juin 2018 10:47

Télécharger (5,6 ko)

Voir les différences:

Subject: [PATCH] agent/authentic2: add an hobo_provision command (#19853)

To provision all users or roles, the role provisionning is full, i.e. it
removes old roles. The user provisionning is not currently.
 .../management/commands/hobo_provision.py     | 68 +++++++++++++++++++
 tests_authentic/test_provisionning.py         | 29 ++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 hobo/agent/authentic2/management/commands/hobo_provision.py
hobo/agent/authentic2/management/commands/hobo_provision.py
1
import time
2

  
3
from django.core.management.base import BaseCommand
4

  
5
from django_rbac.utils import get_role_model, get_ou_model
6
from django.contrib.auth import get_user_model
7

  
8
from hobo.agent.authentic2.provisionning import Provisionning
9

  
10

  
11
class Command(BaseCommand):
12
    help = 'Provision all roles or users'
13

  
14
    def add_arguments(self, parser):
15
        parser.add_argument('--roles', action='store_true', default=False)
16
        parser.add_argument('--users', action='store_true', default=False)
17
        parser.add_argument('--batch-size', type=int, default=512)
18
        parser.add_argument('--batch-sleep', type=int, default=30)
19

  
20
    def handle(self, *args, **options):
21
        self.verbosity = options['verbosity']
22
        engine = Provisionning()
23
        ous = {ou.id: ou for ou in get_ou_model().objects.all()}
24

  
25
        if options['roles']:
26
            self.provision_roles(engine, ous)
27

  
28
        if options['users']:
29
            self.provision_users(engine, ous, batch_size=options['batch_size'], batch_sleep=options['batch_sleep'], verbosity=options['verbosity'])
30
        if self.verbosity > 0:
31
            self.stdout.write('Done.')
32

  
33
    def provision_roles(self, engine, ous):
34
        roles = get_role_model().objects.all()
35
        if self.verbosity > 0:
36
            self.stdout.write('Provisionning {} roles.'.format(roles.count()))
37
        engine.notify_roles(ous, roles, full=True)
38

  
39
    def provision_users(self, engine, ous, batch_size=512, batch_sleep=30, verbosity=1):
40
        qs = get_user_model().objects.all()
41
        # allow easy pagination by pk
42
        qs = qs.order_by('pk')
43
        # prevent too much select
44
        qs = qs.prefetch_related('attribute_values__attribute')
45

  
46
        def do_provision(qs):
47
            users = list(qs[:batch_size])
48
            while users:
49
                if verbosity > 0:
50
                    self.stdout.write('  batch provisionning %d users and sleeping for %d seconds' % (len(users), batch_sleep))
51
                engine.notify_users(ous, users)
52
                users = list(qs.filter(id__gt=users[-1].pk)[:batch_size])
53
                if users:
54
                    time.sleep(batch_sleep)
55

  
56
        roles_with_attributes = get_role_model().objects.filter(attributes__name='is_superuser').children()
57
        # first those without and admin attribute
58
        normal_users = qs.exclude(roles__in=roles_with_attributes)
59

  
60
        if self.verbosity > 0:
61
            self.stdout.write('Provisionning {} normal users.'.format(normal_users.count()))
62
        do_provision(normal_users)
63
        # then those with an admin attribute, use distinct to prevent
64
        # duplicates caused by join on a m2m relation
65
        admin_users = qs.filter(roles__in=roles_with_attributes).distinct()
66
        if self.verbosity > 0:
67
            self.stdout.write('Provisionning {} admin users.'.format(admin_users.count()))
68
        do_provision(admin_users)
tests_authentic/test_provisionning.py
453 453
        call_command('tenant_command', 'createsuperuser', domain=tenant.domain_url, uuid='coin',
454 454
                     username='coin', email='coin@coin.org', interactive=False)
455 455
        assert notify_agents.call_count == 1
456

  
457

  
458
@patch('hobo.agent.authentic2.provisionning.notify_agents')
459
def test_command_hobo_provision(notify_agents, transactional_db, tenant, caplog):
460
    User = get_user_model()
461
    with tenant_context(tenant):
462
        ou = get_default_ou()
463
        LibertyProvider.objects.create(ou=ou, name='provider',
464
                                       entity_id='http://provider.com',
465
                                       protocol_conformance=lasso.PROTOCOL_SAML_2_0)
466
        for i in range(10):
467
            Role.objects.create(name='role-%s' % i, ou=ou)
468
        for i in range(10):
469
            User.objects.create(username='user-%s' % i, first_name='John',
470
                                last_name='Doe %s' % i, ou=ou,
471
                                email='jone.doe-%s@example.com')
472

  
473
    call_command('tenant_command', 'hobo_provision', domain=tenant.domain_url, roles=True, users=True)
474

  
475
    msg_1 = notify_agents.call_args_list[0][0][0]
476
    msg_2 = notify_agents.call_args_list[1][0][0]
477
    assert msg_1['@type'] == 'provision'
478
    assert msg_1['full'] is True
479
    assert msg_1['objects']['@type'] == 'role'
480
    assert len(msg_1['objects']['data']) == 10
481
    assert msg_2['@type'] == 'provision'
482
    assert msg_2['full'] is False
483
    assert msg_2['objects']['@type'] == 'user'
484
    assert len(msg_2['objects']['data']) == 10
456
-