Projet

Général

Profil

0001-ozwillo-add-script-for-synchronization-of-ozwillo-us.patch

Benjamin Dauvergne, 07 août 2017 17:06

Télécharger (5,96 ko)

Voir les différences:

Subject: [PATCH] ozwillo: add script for synchronization of ozwillo users

It needs robobrowser to be installed using pip in /usr/local.

You need to add the following line in a crontab (every 20 minutes as a
baseline):

   authentic2-multitenant-manage runscript hobo.contrib.ozwillo.scripts.synchronize_ozwillo_users
 hobo/contrib/ozwillo/scripts/__init__.py           |   0
 .../ozwillo/scripts/synchronize_ozwillo_users.py   | 127 +++++++++++++++++++++
 2 files changed, 127 insertions(+)
 create mode 100644 hobo/contrib/ozwillo/scripts/__init__.py
 create mode 100644 hobo/contrib/ozwillo/scripts/synchronize_ozwillo_users.py
hobo/contrib/ozwillo/scripts/synchronize_ozwillo_users.py
1
import json
2
import datetime
3
import logging
4
import urlparse
5
from urllib import urlencode
6
import pprint
7
import os
8

  
9
import requests
10
from robobrowser.browser import RoboBrowser
11

  
12
from hobo.multitenant.middleware import TenantMiddleware
13
from tenant_schemas.utils import tenant_context
14

  
15

  
16
def run_on_all_tenants(f):
17
    for tenant in TenantMiddleware.get_tenants():
18
        with tenant_context(tenant):
19
            try:
20
                f(tenant)
21
            except:
22
                logging.exception('unable to provision')
23

  
24
def provision_users(tenant):
25
    from django.conf import settings
26
    
27
    if not getattr(settings, 'OZWILLO_ADMIN', None):
28
        logging.warning('No OZWILLO_ADMIN setting found')
29
        return
30

  
31
    logger = logging.getLogger('ozwillo_synchro')
32
    from authentic2_auth_oidc.models import OIDCProvider
33
    for provider in OIDCProvider.objects.all():
34
        if 'ozwillo' in provider.issuer:
35
            auth_url = provider.authorization_endpoint
36
            token_url = provider.token_endpoint
37
            client_id = provider.client_id
38
            client_secret = provider.client_secret
39
            redirect_uri = urlparse.urljoin(tenant.get_base_url(), '/accounts/oidc/callback/')
40
            instance_users_url = urlparse.urljoin(token_url.replace('accounts', 'kernel'), '/apps/acl/instance/')
41
            break
42
    else:
43
        logger.warning('No ozwillo OIDC provider found for %s', tenant.get_base_url())
44
        return
45

  
46
    session = requests.Session()
47
    session.verify = False
48

  
49
    br = RoboBrowser(user_agent='Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0',
50
                     session=session)
51

  
52
    query = urlencode({
53
        'client_id': client_id,
54
        'response_type': 'code',
55
        'scope': 'openid offline_access',
56
        'prompt': 'consent',
57
        'redirect_uri': redirect_uri
58
    })
59
    response = br.open(auth_url + '?%s' % query)
60
    response = br._states[-1].response
61
    if br._states[-1].response.status_code != 200:
62
        logger.warning(u'OIDC authorization request failed: %s %r', response.status_code, response._content[:1000])
63
        return
64
    referer = br.response.request.url
65
    br.session.headers['Referer'] = referer
66
    form = br.get_form(action='/a/login')
67
    form['u'] = settings.OZWILLO_ADMIN[0]
68
    form['pwd'] = settings.OZWILLO_ADMIN[1]
69
    br.submit_form(form=form)
70
    referer = br.response.request.url
71
    br.session.headers['Referer'] = referer
72
    form = br.get_form()
73
    br.submit_form(form=form, allow_redirects=False)
74

  
75
    cb_url = urlparse.urlparse(br.response.headers['location'])
76

  
77
    code = urlparse.parse_qs(cb_url.query)['code'][0]
78

  
79
    logger.info('Getting token from %s', token_url)
80
    response = requests.post(token_url, auth=(client_id, client_secret),
81
                             data={
82
                                 'code': code,
83
                                 'redirect_uri': redirect_uri,
84
                                 'grant_type': 'authorization_code'})
85
    logger.info('Got %s', response.json())
86
    access_token = response.json()['access_token']
87
    logger.info('Getting instance users from %s', instance_users_url + client_id)
88
    response = requests.get(instance_users_url + client_id,
89
                            headers={'Authorization': 'Bearer %s' % access_token})
90
    logger.info('Got %s', response.json())
91

  
92
    from django.contrib.auth import get_user_model
93
    from authentic2_auth_oidc.models import OIDCAccount
94

  
95
    User = get_user_model()
96

  
97
    for user in response.json():
98
        logging.info('Provisionning email %s with sub %s', user['user_email_address'], user['user_id'])
99
        while True:
100
            new_user = User.objects.create()
101
            oidc_account, created = OIDCAccount.objects.select_related().get_or_create(provider=provider, sub=user['user_id'], defaults={'user': new_user})
102
            if created:
103
                if OIDCAccount.objects.filter(provider=provider, sub=user['user_id']).count() > 1:
104
                   oidc_account.delete()
105
                   new_user.delete()
106
                   continue
107
                logging.info('provisionned with uuid %s', new_user.uuid)
108
                break
109
            else:
110
                new_user.delete()
111
                new_user = oidc_account.user
112
                break
113
        save = False
114
        if new_user.username != user['user_name']:
115
            new_user.username = user['user_name']
116
            save = True
117
        if new_user.email != user['user_email_address']:
118
            new_user.email = user['user_email_address']
119
            save = True
120
        if new_user.ou != provider.ou:
121
            new_user.ou = provider.ou
122
            save = True
123
        if save:
124
            new_user.save()
125

  
126

  
127
run_on_all_tenants(provision_users)
0
-