Projet

Général

Profil

Télécharger (13,9 ko) Statistiques
| Branche: | Révision:

root / larpe / tags / release-1.1.1 / larpe / admin / settings.ptl @ d03cb81c

1
import cStringIO
2
import cPickle
3
import re
4
import os
5
import lasso
6
import glob
7
import zipfile
8

    
9
from quixote import get_publisher, get_request, get_response, redirect
10
from quixote.directory import Directory, AccessControlled
11

    
12
from qommon.form import *
13
from qommon.misc import get_abs_path
14
from qommon.admin.cfg import cfg_submit
15
from qommon.admin.menu import html_top, error_page
16
from qommon.admin.emails import EmailsDirectory as QommonEmailsDirectory
17
from qommon.admin.settings import SettingsDirectory as QommonSettingsDirectory
18

    
19
from larpe import misc
20
from larpe.hosts import Host
21
from larpe.admin.liberty_utils import *
22

    
23
class LibertyIDPDir(Directory):
24
    _q_exports = ['', ('metadata.xml', 'metadata')]
25

    
26
    def _q_index [html] (self):
27
        form = Form(enctype="multipart/form-data")
28
        form.add(FileWidget, "metadata", title = _("Metadata"), required=True)
29
        form.add(FileWidget, "publickey", title = _("Public Key"), required=False)
30
        form.add(FileWidget, "cacertchain", title = _("CA Certificate Chain"), required=False)
31
        form.add_submit("submit", _("Submit"))
32

    
33
        if not form.is_submitted() or form.has_errors():
34
            html_top('settings', title = _('New Identity Provider'))
35
            "<h2>%s</h2>" % _('New Identity Provider')
36
            form.render()
37
        else:
38
            self.submit_new(form)
39

    
40
    def submit_new(self, form, key_provider_id = None):
41
        metadata, publickey, cacertchain = None, None, None
42
        if form.get_widget('metadata').parse():
43
            metadata = form.get_widget('metadata').parse().fp.read()
44
        if form.get_widget('publickey').parse():
45
            publickey = form.get_widget('publickey').parse().fp.read()
46
        if form.get_widget('cacertchain').parse():
47
            cacertchain = form.get_widget('cacertchain').parse().fp.read()
48

    
49
        if not key_provider_id:
50
            try:
51
                provider_id = re.findall(r'(provider|entity)ID="(.*?)"', metadata)[0][1]
52
            except IndexError:
53
                return error_page('settings', _('Bad metadata'))
54
            key_provider_id = provider_id.replace(str('://'), str('-')).replace(str('/'), str('-'))
55

    
56
        dir = get_abs_path(os.path.join('idp', key_provider_id))
57
        if not os.path.isdir(dir):
58
            os.makedirs(dir)
59

    
60
        if metadata:
61
            metadata_fn = os.path.join(dir, 'metadata.xml')
62
            open(metadata_fn, 'w').write(metadata)
63
        if publickey:
64
            publickey_fn = os.path.join(dir, 'public_key')
65
            open(publickey_fn, 'w').write(publickey)
66
        else:
67
            publickey_fn = None
68
        if cacertchain:
69
            cacertchain_fn = os.path.join(dir, 'ca_cert_chain.pem')
70
            open(cacertchain_fn, 'w').write(cacertchain)
71
        else:
72
            cacertchain_fn = None
73

    
74
        p = lasso.Provider(lasso.PROVIDER_ROLE_IDP, metadata_fn, publickey_fn, None)
75

    
76
        try:
77
            misc.get_provider_label(p)
78
            get_publisher().cfg['idp'] = key_provider_id
79
            get_publisher().write_cfg()
80
        except TypeError:
81
            if metadata:
82
                os.unlink(metadata_fn)
83
            if publickey:
84
                os.unlink(publickey_fn)
85
            if cacertchain:
86
                os.unlink(cacertchain_fn)
87
            return error_page('settings', _('Bad metadata'))
88

    
89
        redirect('..')
90

    
91
    def metadata(self):
92
        response = get_response()
93
        response.set_content_type('text/xml', 'utf-8')
94
        get_publisher().reload_cfg()
95
        if get_publisher().cfg['idp']:
96
            idp_metadata = os.path.join(get_abs_path('idp'), get_publisher().cfg['idp'], 'metadata.xml')
97
            return unicode(open(idp_metadata).read(), 'utf-8')
98
        return 'No IDP is configured'
99

    
100

    
101
class EmailsDirectory(QommonEmailsDirectory):
102
    def _q_index [html] (self):
103
        # Don't use custom emails
104
        html_top('settings', title = _('Emails'))
105
        '<h2>%s</h2>' % _('Emails')
106

    
107
        '<ul>'
108
        '<li><a href="options">%s</a></li>' % _('General Options')
109
        '</ul>'
110

    
111
        '<p>'
112
        '<a href="..">%s</a>' % _('Back')
113
        '</p>'
114

    
115

    
116
class SettingsDirectory(QommonSettingsDirectory):
117
    _q_exports = ['', 'liberty_sp', 'liberty_idp', 'domain_names', 'apache2_configuration_generation',
118
                  'proxy', 'language', 'emails', 'debug_options' ]
119

    
120
    liberty_idp = LibertyIDPDir()
121
    emails = EmailsDirectory()
122

    
123
    def _q_index [html] (self):
124
        get_publisher().reload_cfg()
125
        html_top('settings', title = _('Settings'))
126

    
127
        if lasso.SAML2_SUPPORT:
128
            '<h2>%s</h2>' % _('Liberty Alliance & SAML 2.0 Service Provider')
129
        else:
130
            '<h2>%s</h2>' % _('Liberty Alliance Service Provider')
131
        '<dl> <dt><a href="liberty_sp">%s</a></dt> <dd>%s</dd>' % (
132
                _('Service Provider'), _('Configure Larpe as a Service Provider'))
133

    
134
        hosts = Host.select(lambda x: x.name == 'larpe')
135
        if hosts:
136
            self.host = hosts[0]
137

    
138
            if lasso.SAML2_SUPPORT and self.host.saml2_metadata is not None:
139
                metadata_url = '%s/metadata.xml' % self.host.saml2_base_url
140
                '<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % (
141
                        metadata_url,
142
                        _('SAML 2.0 Metadata'),
143
                        _('Download SAML 2.0 metadata file for Larpe'))
144

    
145
            if self.host.metadata is not None:
146
                metadata_url = '%s/metadata.xml' % self.host.base_url
147
                '<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % (
148
                        metadata_url,
149
                        _('ID-FF 1.2 Metadata'),
150
                        _('Download ID-FF 1.2 metadata file for Larpe'))
151

    
152
            if self.host.public_key is not None:
153
                public_key_url = '%s/public_key' % self.host.base_url
154
                '<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % (
155
                        public_key_url,
156
                        _('Public key'),
157
                        _('Download SSL Public Key file'))
158

    
159
        if lasso.SAML2_SUPPORT:
160
            '<h2>%s</h2>' % _('Liberty Alliance & SAML 2.0 Identity Provider')
161
        else:
162
            '<h2>%s</h2>' % _('Liberty Alliance Identity Provider')
163

    
164
        '<dl>'
165

    
166
        '<dt><a href="liberty_idp/">%s</a></dt> <dd>%s</dd>' % (
167
               _('Identity Provider'), _('Configure an identity provider'))
168

    
169
        if get_publisher().cfg.has_key('idp'):
170
            '<dt><a href="liberty_idp/metadata.xml">%s</a></dt> <dd>%s</dd>' % (
171
                    _('Identity Provider metadatas'), _('See current identity provider metadatas'))
172

    
173
        '</dl>'
174

    
175
        '<h2>%s</h2>' % _('Global parameters for the sites')
176

    
177
        '<dl>'
178
        '<dt><a href="domain_names">%s</a></dt> <dd>%s</dd>' % (
179
                _('Domain name'), _('Configure the base domain name for the sites'))
180
        '<dt><a href="apache2_configuration_generation">%s</a></dt> <dd>%s</dd>' % (
181
                _('Apache 2 configuration generation'), _('Customise Apache 2 configuration generation'))
182
        '<dt><a href="proxy">%s</a></dt> <dd>%s</dd>' % (
183
                _('Proxy'), _('Connect to the sites through a web proxy'))
184
        '</dl>'
185

    
186
        '<h2>%s</h2>' % _('Customisation')
187

    
188
        '<dl>'
189
        '<dt><a href="language">%s</a></dt> <dd>%s</dd>' % (
190
                _('Language'), _('Configure site language'))
191
        '<dt><a href="emails/">%s</a></dt> <dd>%s</dd>' % (
192
                _('Emails'), _('Configure email settings'))
193
        '</dl>'
194

    
195
        '<h2>%s</h2>' % _('Misc')
196

    
197
        '<dl>'
198
        '<dt><a href="debug_options">%s</a></dt> <dd>%s</dd>' % (
199
                _('Debug Options'), _('Configure options useful for debugging'))
200
        '</dl>'
201

    
202

    
203
    def liberty_sp [html] (self):
204
        get_publisher().reload_cfg()
205

    
206
        # Get the host object for the reverse proxy
207
        hosts = Host.select(lambda x: x.name == 'larpe')
208
        if hosts:
209
            self.host = hosts[0]
210
        else:
211
            self.host = Host()
212
            self.host.reversed_hostname = get_publisher().cfg[str('proxy_hostname')]
213

    
214
        form = Form(enctype='multipart/form-data')
215
        form.add(StringWidget, 'organization_name', title=_('Organisation Name'), size=50,
216
                required = True, value = self.host.organization_name)
217
        form.add_submit('submit', _('Submit'))
218
        form.add_submit('cancel', _('Cancel'))
219
        if form.get_widget('cancel').parse():
220
            return redirect('.')
221
        if not form.is_submitted() or form.has_errors():
222
            html_top('settings', title = _('Service Provider Configuration'))
223
            '<h2>%s</h2>' % _('Service Provider Configuration')
224
            form.render()
225
        else:
226
            self.liberty_sp_submit(form)
227
            redirect('.')
228

    
229
    def liberty_sp_submit(self, form):
230
        get_publisher().reload_cfg()
231
        metadata_cfg = {}
232

    
233
        f = 'organization_name'
234
        if form.get_widget(f):
235
            setattr(self.host, f, form.get_widget(f).parse())
236

    
237
        metadata_cfg['organization_name'] = self.host.organization_name
238

    
239
        self.host.name = 'larpe'
240

    
241
        # Liberty Alliance / SAML parameters
242
        base_url = '%s/liberty/%s/liberty' % (misc.get_root_url(), self.host.name)
243
        metadata_cfg['base_url'] = base_url
244
        self.host.base_url = base_url
245

    
246
        if lasso.SAML2_SUPPORT:
247
            saml2_base_url = '%s/liberty/%s/saml' % (misc.get_root_url(), self.host.name)
248
            metadata_cfg['saml2_base_url'] = saml2_base_url
249
            self.host.saml2_base_url = saml2_base_url
250

    
251
        provider_id = '%s/metadata' % base_url
252
        metadata_cfg['provider_id'] = provider_id
253
        self.host.provider_id = provider_id
254

    
255
        if lasso.SAML2_SUPPORT:
256
            saml2_provider_id = '%s/metadata' % saml2_base_url
257
            metadata_cfg['saml2_provider_id'] = saml2_provider_id
258
            self.host.saml2_provider_id = saml2_provider_id
259

    
260
        # Storage directories
261
        site_dir = os.path.join(get_publisher().app_dir, 'sp',
262
                    self.host.reversed_hostname, self.host.name)
263
        user_dir = os.path.join(site_dir, 'users')
264
        token_dir = os.path.join(site_dir, 'tokens')
265
        for dir in (site_dir, user_dir, token_dir):
266
            if not os.path.isdir(dir):
267
                os.makedirs(dir)
268
        metadata_cfg['site_dir'] = site_dir
269
        self.host.site_dir = site_dir
270

    
271
        # Generate SSL keys
272
        private_key_path = os.path.join(site_dir, 'private_key.pem')
273
        public_key_path = os.path.join(site_dir, 'public_key')
274
        if not os.path.isfile(private_key_path) or not os.path.isfile(public_key_path):
275
            set_provider_keys(private_key_path, public_key_path)
276
        self.host.private_key = private_key_path
277
        metadata_cfg['signing_public_key'] = open(public_key_path).read()
278
        self.host.public_key = public_key_path
279

    
280
        # Write metadatas
281
        metadata_path = os.path.join(site_dir, 'metadata.xml')
282
        open(metadata_path, 'w').write(get_metadata(metadata_cfg))
283
        self.host.metadata = metadata_path
284

    
285
        if hasattr(self.host, 'saml2_provider_id'):
286
            saml2_metadata_path = os.path.join(site_dir, 'saml2_metadata.xml')
287
            open(saml2_metadata_path, 'w').write(get_saml2_metadata(metadata_cfg))
288
            self.host.saml2_metadata = saml2_metadata_path
289

    
290
        self.host.root_url = '%s/' % misc.get_root_url()
291
        self.host.return_url = '%s/admin/' % misc.get_root_url()
292

    
293
        self.host.store()
294

    
295
    def domain_names [html] (self):
296
        form = self.form_domain_name()
297

    
298
        if form.get_widget('cancel').parse():
299
            return redirect('.')
300

    
301
        if not form.is_submitted() or form.has_errors():
302
            html_top('settings', title = _('Domain name'))
303
            '<h2>%s</h2>' % _('Domain name')
304
            form.render()
305
        else:
306
            self.submit_domain_name(form)
307
            redirect('.')
308

    
309
    def form_domain_name(self):
310
        get_publisher().reload_cfg()
311
        if get_cfg('domain_names'):
312
            domain_name = get_cfg('domain_names')[0]
313
        else:
314
            domain_name = None
315

    
316
        form = Form(enctype='multipart/form-data')
317
        form.add(StringWidget, 'domain_name',
318
            title=_('Domain name for the sites'),
319
            value = domain_name)
320
        # TODO: Add the option "Both" and handle it in hosts configuration
321
        form.add(SingleSelectWidget, 'sites_url_scheme', title = _('Use HTTP or HTTPS'),
322
                value = get_cfg('sites_url_scheme'),
323
                options = [ (None, _('Same as the site')),
324
                            ('http', 'HTTP'),
325
                            ('https', 'HTTPS') ] )
326
        form.add_submit('submit', _('Submit'))
327
        form.add_submit('cancel', _('Cancel'))
328
        return form
329

    
330
    def submit_domain_name(self, form):
331
        get_publisher().reload_cfg()
332
        get_publisher().cfg['domain_names'] = [ form.get_widget('domain_name').parse() ]
333
        get_publisher().cfg['sites_url_scheme'] = form.get_widget('sites_url_scheme').parse()
334
        get_publisher().write_cfg()
335

    
336
    def apache2_configuration_generation [html] (self):
337
        get_publisher().reload_cfg()
338

    
339
        form = Form(enctype='multipart/form-data')
340
        form.add(CheckboxWidget, 'allow_config_generation',
341
                title=_('Automatically generate Apache 2 configuration for new hosts and reload Apache 2 after changes'),
342
                value = get_publisher().cfg.get(str('allow_config_generation'), True))
343
        form.add_submit('submit', _('Submit'))
344
        form.add_submit('cancel', _('Cancel'))
345
        if form.get_widget('cancel').parse():
346
            return redirect('.')
347
        if not form.is_submitted() or form.has_errors():
348
            html_top('settings', title = _('Apache 2 configuration generation'))
349
            '<h2>%s</h2>' % _('Apache 2 configuration generation')
350
            form.render()
351
        else:
352
            self.apache2_configuration_generation_submit(form)
353
            redirect('.')
354

    
355
    def apache2_configuration_generation_submit(self, form):
356
        get_publisher().reload_cfg()
357

    
358
        f = 'allow_config_generation'
359
        get_publisher().cfg[f] = form.get_widget(f).parse()
360

    
361
        get_publisher().write_cfg()
(8-8/9)