Projet

Général

Profil

0001-ozwillo-create-ozwillo-app-in-contrib-14935.patch

Jean-Baptiste Jaillet, 09 juin 2017 10:19

Télécharger (30 ko)

Voir les différences:

Subject: [PATCH] ozwillo: create ozwillo app in contrib (#14935)

 hobo/contrib/__init__.py                           |   0
 hobo/contrib/ozwillo/README.txt                    |  34 +++
 hobo/contrib/ozwillo/__init__.py                   |   0
 .../ozwillo/examples/import-site-agents.json       |  30 +++
 .../ozwillo/examples/import-site-template.json     | 169 +++++++++++++
 hobo/contrib/ozwillo/examples/template_recipe.json |  66 +++++
 hobo/contrib/ozwillo/migrations/0001_initial.py    |  21 ++
 hobo/contrib/ozwillo/migrations/__init__.py        |   0
 hobo/contrib/ozwillo/models.py                     |  26 ++
 .../contrib/ozwillo/scripts/create_user_ozwillo.py |  55 +++++
 hobo/contrib/ozwillo/urls.py                       |  25 ++
 hobo/contrib/ozwillo/views.py                      | 275 +++++++++++++++++++++
 hobo/urls.py                                       |   4 +
 13 files changed, 705 insertions(+)
 create mode 100644 hobo/contrib/__init__.py
 create mode 100644 hobo/contrib/ozwillo/README.txt
 create mode 100644 hobo/contrib/ozwillo/__init__.py
 create mode 100644 hobo/contrib/ozwillo/examples/import-site-agents.json
 create mode 100644 hobo/contrib/ozwillo/examples/import-site-template.json
 create mode 100644 hobo/contrib/ozwillo/examples/template_recipe.json
 create mode 100644 hobo/contrib/ozwillo/migrations/0001_initial.py
 create mode 100644 hobo/contrib/ozwillo/migrations/__init__.py
 create mode 100644 hobo/contrib/ozwillo/models.py
 create mode 100644 hobo/contrib/ozwillo/scripts/create_user_ozwillo.py
 create mode 100644 hobo/contrib/ozwillo/urls.py
 create mode 100644 hobo/contrib/ozwillo/views.py
hobo/contrib/ozwillo/README.txt
1
To run this plugin well, you have to set some files in /etc/hobo/ozwillo :
2
- the files are in the folder examples. (don't forget to replace the instance name in the combo import-site-template.json by 'instance_name').
3
- it's a common recipe for your publik, and two extracts of user and agent combo.
4
- hobo has to be in the sudoers
5

  
6
You have to set several var in a settings.json too :
7
-OZWILLO_SECRET
8
-OZWILLO_ENV_DOMAIN (e.g: sictiam.dev.entrouvert.org)
9
-OZWILLO_DESTRUCTION_URI
10
-OZWILLO_DESTRUCTION_SECRET
11
-OZWILLO_PLATEFORM (https://dev.entrouvert.org/projects/sictiam/wiki/Raccordement_OpenID_Connect_%C3%A0_Ozwillo for the values)
12
-OZWILLO_SERVICES (use only for the destruction, explained down)
13

  
14
And finally you have to enable in INSTALLED_APPS hobo.contrib.ozwillo.
15

  
16
The views create-publik-instance receive an ozwillo request with some clients informations (secret and id), the ozwillo user sending the request, the organization name (which is the collectivity's name to deploy) and the registration uri (where you're supposed to POST when the job's done).
17
The script modify a template_recipe by replacing every 'instance_name' by the actual organization name, and same for the combo user extract (rewritting all the url_redirect fields).
18
The script then launch a cook and three commands :
19
- the import of the combo user with the modified extract
20
- the import of the combo agent
21
- a runscript creating a role (same as the one in wcs linked to the form sve 'agents sve'), a provider (the details are in the page linked for the parameter OZWILLO_PLATEFORM) and an admin User in Authentic who is the ozwillo user sending the request.
22
In the final acknolegment response, the script sends a 'services' dictionnary for ozillo to set some links and parameters in its backoffice about the app deployed).
23

  
24
OZWILLO_SERVICES is a dict following this pattern: 'service_user': ['service_prefix', 'service_command_manager']. E.G:
25
{
26
"authentic-multitenant": ["connexion-", "authentic2-multitenant-manage"],
27
"combo_agent": ["agents-", "combo-manage"],
28
"combo_usager": ["", "combo-manage"],
29
"fargo": ["porte-documents-", "fargo-manage"],
30
"hobo": ["hobo-", "hobo-manage"],
31
"passerelle": ["passerelle-", "passerelle-manage"],
32
"wcs-au-quotidien": ["demarches-", "wcsctl"]
33
}
34

  
hobo/contrib/ozwillo/examples/import-site-agents.json
1
[
2
    {
3
        "cells": [
4
            {
5
                "fields": {
6
                    "extra_css_class": "",
7
                    "groups": [],
8
                    "order": 1,
9
                    "placeholder": "content",
10
                    "public": true,
11
                    "restricted_to_unlogged": false,
12
                    "slug": "services",
13
                    "text": "<h2>Bienvenue</h2>\r\n"
14
                },
15
                "model": "data.textcell"
16
            }
17
        ],
18
        "fields": {
19
            "exclude_from_navigation": false,
20
            "groups": [],
21
            "order": 1,
22
            "parent": null,
23
            "public": false,
24
            "redirect_url": "",
25
            "slug": "index",
26
            "template_name": "standard",
27
            "title": "Accueil"
28
        }
29
    }
30
]
hobo/contrib/ozwillo/examples/import-site-template.json
1
[
2
    {
3
        "cells": [
4
            {
5
                "fields": {
6
                    "extra_css_class": "",
7
                    "groups": [],
8
                    "order": 0,
9
                    "placeholder": "content",
10
                    "public": true,
11
                    "restricted_to_unlogged": true,
12
                    "slug": "",
13
                    "text": "<h2>Bienvenue</h2>\r\n\r\n<p>Bienvenue sur votre compte usager.</p>\r\n\r\n<p>Pour suivre vos d&eacute;marches en cours, cr&eacute;ez votre compte personnel ou identifiez-vous depuis <a href=\"/login/\">la page de connexion</a>.</p>\r\n"
14
                },
15
                "model": "data.textcell"
16
            },
17
            {
18
                "fields": {
19
                    "extra_css_class": "",
20
                    "groups": [],
21
                    "order": 1,
22
                    "placeholder": "content",
23
                    "public": false,
24
                    "restricted_to_unlogged": false,
25
                    "slug": "",
26
                    "text": "<h2>Bienvenue</h2>\r\n\r\n<p>Bienvenue sur votre compte usager.</p>\r\n"
27
                },
28
                "model": "data.textcell"
29
            },
30
            {
31
                "fields": {
32
                    "extra_css_class": "",
33
                    "groups": [],
34
                    "order": 2,
35
                    "placeholder": "right",
36
                    "public": true,
37
                    "restricted_to_unlogged": false,
38
                    "slug": "",
39
                    "wcs_site": ""
40
                },
41
                "model": "wcs.trackingcodeinputcell"
42
            },
43
            {
44
                "fields": {
45
                    "extra_css_class": "",
46
                    "groups": [],
47
                    "order": 3,
48
                    "placeholder": "right",
49
                    "public": true,
50
                    "restricted_to_unlogged": true,
51
                    "slug": "",
52
                    "text": "<h2>Demandes en cours</h2>\r\n\r\n<p>Connectez-vous pour voir vos demandes en cours.</p>\r\n"
53
                },
54
                "model": "data.textcell"
55
            },
56
            {
57
                "fields": {
58
                    "current_forms": true,
59
                    "done_forms": false,
60
                    "extra_css_class": "",
61
                    "groups": [],
62
                    "order": 4,
63
                    "placeholder": "right",
64
                    "public": false,
65
                    "restricted_to_unlogged": false,
66
                    "slug": "",
67
                    "wcs_site": ""
68
                },
69
                "model": "wcs.wcscurrentformscell"
70
            },
71
            {
72
                "fields": {
73
                    "extra_css_class": "",
74
                    "groups": [],
75
                    "order": 5,
76
                    "placeholder": "footer",
77
                    "public": true,
78
                    "restricted_to_unlogged": false,
79
                    "slug": "",
80
                    "text": "<p>Ce service est propos&eacute; par le <a href=\"http://www.sictiam.fr/\">SICTIAM</a>.</p>\r\n"
81
                },
82
                "model": "data.textcell"
83
            },
84
            {
85
                "fields": {
86
                    "category_reference": "eservices:nous-contacter",
87
                    "extra_css_class": "",
88
                    "groups": [],
89
                    "limit": null,
90
                    "manual_order": {
91
                        "data": []
92
                    },
93
                    "order": 6,
94
                    "ordering": "popularity",
95
                    "placeholder": "content",
96
                    "public": true,
97
                    "restricted_to_unlogged": false,
98
                    "slug": ""
99
                },
100
                "model": "wcs.wcsformsofcategorycell"
101
            }
102
        ],
103
        "fields": {
104
            "exclude_from_navigation": false,
105
            "groups": [],
106
            "order": 1,
107
            "parent": null,
108
            "public": true,
109
            "redirect_url": "",
110
            "slug": "index",
111
            "template_name": "two-columns",
112
            "title": "Accueil"
113
        }
114
    },
115
    {
116
        "cells": [
117
            {
118
                "fields": {
119
                    "extra_css_class": "",
120
                    "groups": [],
121
                    "order": 0,
122
                    "placeholder": "footer",
123
                    "public": true,
124
                    "restricted_to_unlogged": false,
125
                    "slug": ""
126
                },
127
                "model": "data.parentcontentcell"
128
            }
129
        ],
130
        "fields": {
131
            "exclude_from_navigation": false,
132
            "groups": [],
133
            "order": 2,
134
            "parent": null,
135
            "public": true,
136
            "redirect_url": "[idp_url]accounts/",
137
            "slug": "mon-compte",
138
            "template_name": "standard",
139
            "title": "Mon compte"
140
        }
141
    },
142
    {
143
        "cells": [
144
            {
145
                "fields": {
146
                    "extra_css_class": "",
147
                    "groups": [],
148
                    "order": 0,
149
                    "placeholder": "footer",
150
                    "public": true,
151
                    "restricted_to_unlogged": false,
152
                    "slug": ""
153
                },
154
                "model": "data.parentcontentcell"
155
            }
156
        ],
157
        "fields": {
158
            "exclude_from_navigation": false,
159
            "groups": [],
160
            "order": 3,
161
            "parent": null,
162
            "public": true,
163
            "redirect_url": "[eservices_url]",
164
            "slug": "nous-contacter",
165
            "template_name": "standard",
166
            "title": "Nous contacter"
167
        }
168
    }
169
]
hobo/contrib/ozwillo/examples/template_recipe.json
1
{
2
    "steps": [
3
        {
4
            "create-hobo": {
5
                "url": "https://${hobo}/"
6
            }
7
        },
8
        {
9
            "create-authentic": {
10
                "title": "Connexion",
11
                "url": "https://${authentic}/"
12
            }
13
        },
14
        {
15
            "set-idp": {}
16
        },
17
        {
18
            "create-combo": {
19
                "template_name": "portal-user",
20
                "title": "Compte citoyen",
21
                "url": "https://${combo}/"
22
            }
23
        },
24
        {
25
            "create-combo": {
26
                "slug": "portal-agent",
27
                "template_name": "portal-agent",
28
                "title": "Portail agent",
29
                "url": "https://${combo_agent}/"
30
            }
31
        },
32
        {
33
            "create-wcs": {
34
                "template_name": "export.zip",
35
                "title": "D\u00e9marches",
36
                "url": "https://${wcs}/"
37
            }
38
        },
39
        {
40
            "create-fargo": {
41
                "title": "Porte documents",
42
                "url": "https://${fargo}/"
43
            }
44
        },
45
        {
46
            "create-passerelle": {
47
                "title": "Passerelle",
48
                "url": "https://${passerelle}/"
49
            }
50
        },
51
        {
52
            "set-theme": {
53
                "theme": "publik"
54
            }
55
        }
56
    ],
57
    "variables": {
58
        "authentic": "connexion-instance_name.sictiam.dev.entrouvert.org",
59
        "combo": "instance_name.sictiam.dev.entrouvert.org",
60
        "combo_agent": "agents-instance_name.sictiam.dev.entrouvert.org",
61
        "fargo": "porte-documents-instance_name.sictiam.dev.entrouvert.org",
62
        "hobo": "hobo-instance_name.sictiam.dev.entrouvert.org",
63
        "passerelle": "passerelle-instance_name.sictiam.dev.entrouvert.org",
64
        "wcs": "demarches-instance_name.sictiam.dev.entrouvert.org"
65
    }
66
}
hobo/contrib/ozwillo/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4
from django.db import models, migrations
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
    ]
11

  
12
    operations = [
13
        migrations.CreateModel(
14
            name='OzwilloInstance',
15
            fields=[
16
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
17
                ('domain_slug', models.CharField(unique=True, max_length=250)),
18
                ('external_ozwillo_id', models.CharField(max_length=450)),
19
            ],
20
        ),
21
    ]
hobo/contrib/ozwillo/models.py
1
# Ozwillo plugin to deploy Publik
2
# Copyright (C) 2017  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.db import models
18

  
19

  
20
class OzwilloInstance(models.Model):
21
    domain_slug = models.CharField(max_length=250, unique=True)
22
    external_ozwillo_id = models.CharField(max_length=450)
23

  
24
    def __unicode__(self):
25
        return 'external ozwillo id: %s, domain slug: %s' % (self.external_ozwillo_id,
26
                                                             self.domain_slug)
hobo/contrib/ozwillo/scripts/create_user_ozwillo.py
1
import sys
2
import logging
3

  
4
from django.contrib.auth import get_user_model
5

  
6
from authentic2_auth_oidc.models import OIDCAccount
7
from authentic2_auth_oidc.models import OIDCProvider
8
from authentic2.a2_rbac.models import Role, OrganizationalUnit
9

  
10

  
11
def create_user(user_id, email_addressi, user_name, provider):
12
    while True:
13
        new_user = User.objects.create()
14
        oidc_account, created = OIDCAccount.objects.select_related().get_or_create(provider=provider, sub=user_id, defaults={'user': new_user})
15
        if created:
16
            if OIDCAccount.objects.filter(provider=provider, sub=user_id).count() > 1:
17
                oidc_account.delete()
18
                new_user.delete()
19
                continue
20
            break
21
        else:
22
            new_user.delete()
23
            new_user = oidc_account.user
24
            break
25

  
26
    new_user.email = email_address
27
    new_user.ou = provider.ou
28
    new_user.is_superuser = True
29
    new_user.is_staff = True
30
    new_user.first_name = 'admin'
31
    new_user.last_name = user_name
32
    new_user.save()
33

  
34
    return new_user
35

  
36

  
37
# create agent_sve role
38
ou = OrganizationalUnit.objects.get(default=True)
39
role, created = Role.objects.get_or_create(uuid='3f3367d817bb4a9aa98e7ed6c83b5b09',
40
                                           defaults={'name': u'Agents SVE',
41
                                                     'ou': ou})
42

  
43
# set the provider for the user creation
44
provider = OIDCProvider.objects.get(name='Ozwillo')
45

  
46
# get user info from args sent to the script
47
args = sys.argv
48
email_address = args[1]
49
user_id = args[2]
50
user_name = args[3]
51

  
52
# create admin user in Publik from Ozwillo
53
User = get_user_model()
54
user = create_user(user_id, email_address, user_name, provider)
55
logging.info('owzillo provisionning: user created with uuid: %s', user.uuid)
hobo/contrib/ozwillo/urls.py
1
# Ozwillo plugin to deploy
2
# Copyright (C) 2017  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.conf.urls import patterns, url, include
18

  
19
from . import views
20

  
21

  
22
urlpatterns = patterns('',
23
    url(r'create-publik-instance', views.create_publik_instance, name='ozwillo-create-publik-instance'),
24
    url(r'delete-publik-instance', views.delete_publik_instance, name='ozwillo-delete-publik-instance'),
25
)
hobo/contrib/ozwillo/views.py
1
# Ozwillo plugin to deploy Publik
2
# Copyright (C) 2017  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
import os
18
import logging
19
import requests
20
import json
21
import subprocess
22
import hmac
23
import threading
24
import tempfile
25
from hashlib import sha1
26

  
27
from django.views.decorators.csrf import csrf_exempt
28
from django.conf import settings
29
from django.http import (HttpResponseForbidden, HttpResponseBadRequest,
30
                         HttpResponseNotFound, HttpResponse)
31
from django.core.management import call_command
32
from django.utils.text import slugify
33

  
34
from .models import OzwilloInstance
35

  
36
logger = logging.getLogger(__name__)
37

  
38

  
39
def valid_signature_required(func):
40
    '''Validate Ozwillo signatures'''
41

  
42
    signature_header_name = 'HTTP_X_HUB_SIGNATURE'
43
    api_secret = settings.OZWILLO_SECRET
44

  
45
    def wrapper(request):
46
        if signature_header_name in request.META:
47
            if request.META[signature_header_name].startswith('sha1='):
48
                algo, received_hmac = request.META[signature_header_name].rsplit('=')
49
                computed_hmac = hmac.new(api_secret, request.body, sha1).hexdigest()
50
                # the received hmac is uppercase according to
51
                # http://doc.ozwillo.com/#ref-3-2-1
52
                if received_hmac.lower() != computed_hmac:
53
                logger.error(u'ozwillo: invalid HMAC')
54
                    return HttpResponseForbidden('invalid HMAC')
55
            else:
56
            logger.error(u'ozwillo: invalid HMAC algo')
57
                return HttpResponseForbidden('invalid HMAC algo')
58
        else:
59
        logger.error(u'ozwillo: no HMAC in the header')
60
            return HttpResponseForbidden('no HMAC in the header')
61
        return func(request)
62
    return wrapper
63

  
64

  
65
def is_ozwillo_enabled(func):
66
    def wrapper(request):
67
        if not getattr(settings, 'OZWILLO_ENABLED', False):
68
            return HttpResponseNotFound('owillo providing is not active here.')
69
        return func(request)
70
    return wrapper
71

  
72

  
73
@csrf_exempt
74
@is_ozwillo_enabled
75
@valid_signature_required
76
def create_publik_instance(request):
77
    try:
78
        data = json.loads(request.body)
79
    except ValueError:
80
        logger.warning(u'ozwillo: received non JSON request')
81
        return HttpResponseBadRequest('invalid JSON content')
82

  
83
    logger.debug(u'ozwillo: create publik instance request, %r', data)
84

  
85
    if 'organization_name' not in data.keys():
86
        return HttpResponseBadRequest('missing parameter "organization_name"')
87

  
88
    org_name = slugify(data['organization_name'])
89
    if OzwilloInstance.objects.filter(domain_slug=org_name):
90
        return HttpResponseBadRequest('instance %s already exists' % org_name)
91

  
92
    OzwilloInstance.objects.create(external_ozwillo_id=data['instance_id'], domain_slug=org_name)
93

  
94
    def thread_function(data):
95
        try:
96
            ozwillo_deploy_thread(data)
97
        except Exception:
98
            logger.exception(u'ozwillo: error occured while deploying instance %s',
99
                             data['organization_name'])
100

  
101
    thread = threading.Thread(target=thread_function, args=(data,))
102
    thread.start()
103

  
104
    return HttpResponse()
105

  
106

  
107
def ozwillo_deploy_thread(data):
108
    # Request parsing
109
    client_id = data['client_id']
110
    client_secret = data['client_secret']
111
    instance_id = data['instance_id']
112
    instance_name = data['organization_name']
113
    instance_name = slugify(instance_name)
114
    registration_uri = data['instance_registration_uri']
115
    user = data['user']
116

  
117
    # Cook new platform
118
    template_recipe = json.load(open('/etc/hobo/ozwillo/template_recipe.json', 'rb'))
119
    var = template_recipe['variables']
120
    for key, value in var.items():
121
        var[key] = value.replace('instance_name', instance_name)
122

  
123
    template_recipe['variables'] = var
124
    domain = var['combo']
125
    domain_agent = var['combo_agent']
126
    domain_passerelle = var['passerelle']
127

  
128
    recipe_file_handle, recipe_file_path = tempfile.mkstemp()
129

  
130
    json.dump(template_recipe, open(recipe_file_path, 'w'))
131

  
132
    call_command('cook', recipe_file_path, timeout=1000, verbosity=0)
133

  
134
    # Load user portal template
135
    subprocess.check_call([
136
        'sudo', '-u', 'combo',
137
        'combo-manage', 'tenant_command', 'import_site',
138
        '/etc/hobo/ozwillo/import-site-template.json',
139
        '-d', domain
140
    ])
141

  
142
    # Load agent portal template
143
    subprocess.check_call([
144
        'sudo', '-u', 'combo',
145
        'combo-manage', 'tenant_command', 'import_site',
146
        '/etc/hobo/ozwillo/import-site-agents.json',
147
        '-d', domain_agent
148
    ])
149

  
150
    # Configure OIDC Ozwillo authentication
151
    domain_name = 'connexion-%s.%s' % (instance_name, settings.OZWILLO_ENV_DOMAIN)
152
    subprocess.check_call([
153
        'sudo', '-u', 'authentic-multitenant',
154
        'authentic2-multitenant-manage', 'tenant_command', 'oidc-register-issuer',
155
        '-d', domain_name,
156
        '--scope', 'profile',
157
        '--scope', 'email',
158
        '--issuer', settings.OZWILLO_PLATEFORM,
159
        '--client-id', client_id,
160
        '--client-secret', client_secret,
161
        '--claim-mapping', '"given_name first_name always_verified"',
162
        '--claim-mapping', '"family_name last_name always_verified"',
163
        '--ou-slug', 'default',
164
        '--claim-mapping', '"email email required"',
165
        'Ozwillo'
166
    ])
167

  
168
    # Create admin user
169
    create_user_script = os.path.dirname(__file__) + '/scripts/create_user_ozwillo.py'
170
    subprocess.check_call([
171
        'sudo', '-u', 'authentic-multitenant',
172
        'authentic2-multitenant-manage', 'tenant_command', 'runscript', '-d', domain_name,
173
        create_user_script, user['email_address'], user['id'], user['name']
174
    ])
175

  
176
    # Load passerelle template
177
    subprocess.check_call([
178
        'sudo', '-u', 'passerelle',
179
        'passerelle-manage', 'tenant_command', 'import_site',
180
        '/etc/hobo/ozwillo/import-site-passerelle.json',
181
        '--import-user', '-d', domain_passerelle
182
    ])
183

  
184
    os.remove(recipe_file_path)
185

  
186
    # Sending done event to Ozwillo
187
    services = {
188
        'services': [{
189
            'local_id': 'publik',
190
            'name': 'Publik - %s' % (instance_name),
191
            'service_uri': 'https://connexion-%s.%s/accounts/oidc/login?iss=%s'
192
                           % (instance_name, settings.OZWILLO_ENV_DOMAIN,
193
                              settings.OZWILLO_PLATEFORM),
194
            'description': 'Gestion de la relation usagers',
195
            'tos_uri': 'https://publik.entrouvert.com/',
196
            'policy_uri': 'https://publik.entrouvert.com/',
197
            'icon': 'https://publik.entrouvert.com/static/img/logo-publik.png',
198
            'payment_option': 'FREE',
199
            'target_audience': ['PUBLIC_BODIES',
200
                                'CITIZENS',
201
                                'COMPANIES'],
202
            'contacts': ['https://publik.entrouvert.com/'],
203
            'redirect_uris': ['https://connexion-%s.%s/accounts/oidc/callback/'
204
                              % (instance_name, settings.OZWILLO_ENV_DOMAIN)],
205
        }],
206
        'instance_id': instance_id,
207
        'destruction_uri': settings.OZWILLO_DESTRUCTION_URI,
208
        'destruction_secret': settings.OZWILLO_DESTRUCTION_SECRET,
209
        'needed_scopes': []
210
    }
211
    logger.debug(u'ozwillo: sending registration request, %r', services)
212
    headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
213
    response = requests.post(
214
        registration_uri,
215
        data=json.dumps(services),
216
        auth=(client_id, client_secret),
217
        headers=headers)
218
    logger.debug(u'ozwillo: registration response, %r', response.content)
219

  
220

  
221
@csrf_exempt
222
@is_ozwillo_enabled
223
@valid_signature_required
224
def delete_publik_instance(request):
225
    try:
226
        data = json.loads(request.body)
227
    except ValueError:
228
        logger.warning(u'ozwillo: received non JSON request')
229
        return HttpResponseBadRequest('invalid JSON content')
230

  
231
    logger.debug(u'ozwillo: delete publik instance request, %r', data)
232

  
233
    try:
234
        instance = OzwilloInstance.objects.get(external_ozwillo_id=data['instance_id'])
235
    except OzwilloInstance.DoesNotExist:
236
        return HttpResponseBadRequest('no instance with id %s' % data['instance_id'])
237

  
238
    def thread_function(data):
239
        try:
240
            ozwillo_destroy_thread(instance)
241
            logger.debug(u'ozwillo: instance %s destroyed', instance.domain_slug)
242
        except Exception:
243
            logger.exception('ozwillo: error occured while destroying instance %s',
244
                             instance.domain_slug)
245
    thread = threading.Thread(target=ozwillo_destroy_thread, args=(instance,))
246
    thread.start()
247

  
248
    return HttpResponse(status=200)
249

  
250

  
251
def ozwillo_destroy_thread(instance):
252
    instance_slug = instance.domain_slug
253
    services = settings.OZWILLO_SERVICES
254
    wcs = services['wcs-au-quotidien']
255

  
256
    for s, infos in services.items():
257
        # to get the two combo instances which have same service
258
        service_user = s.split('_')[0]
259

  
260
        tenant = '%s%s.%s' % (infos[0], instance_slug, settings.OZWILLO_ENV_DOMAIN)
261

  
262
        subprocess.check_call([
263
            'sudo', '-u', service_user, infos[1],
264
            'delete_tenant', '--force-drop', tenant
265
        ])
266

  
267
    tenant = '%s%s.%s' % (wcs[0], instance_slug, settings.OZWILLO_ENV_DOMAIN)
268
    subprocess.check_call([
269
        'sudo', '-u', 'wcs-au-quotidien',
270
        wcs[1], '-f', '/etc/wcs/wcs-au-quotidien.cfg',
271
        'delete_tenant', '--force-drop', tenant
272
    ])
273

  
274
    instance.delete()
275
    return instance_slug
hobo/urls.py
32 32
    url(r'^login/local/$', login_local), # to be used as backup, in case of idp down
33 33
    url(r'^accounts/mellon/', include('mellon.urls')),
34 34
)
35
if 'hobo.contrib.ozwillo' in settings.INSTALLED_APPS:
36
    urlpatterns += patterns('',
37
        url(r'ozwillo/', include('hobo.contrib.ozwillo.urls')),
38
    )
35
-