dc47faf7feb42c1df0a47d8888abd5167b9b92f8
[cascardo/ipsilon.git] / ipsilon / providers / openidp.py
1 # Copyright (C) 2014 Ipsilon project Contributors, for license see COPYING
2
3 from __future__ import absolute_import
4
5 from ipsilon.providers.common import ProviderBase, ProviderInstaller
6 from ipsilon.providers.openid.store import OpenIDStore
7 from ipsilon.providers.openid.auth import OpenID
8 from ipsilon.providers.openid.extensions.common import LoadExtensions
9 from ipsilon.util.plugin import PluginObject
10 from ipsilon.util import config as pconfig
11 from ipsilon.info.common import InfoMapping
12
13 from openid.server.server import Server
14
15
16 class IdpProvider(ProviderBase):
17
18     def __init__(self, *pargs):
19         super(IdpProvider, self).__init__('openid', 'openid', *pargs)
20         self.mapping = InfoMapping()
21         self.page = None
22         self.server = None
23         self.basepath = None
24         self.extensions = LoadExtensions()
25         self.description = """
26 Provides OpenID 2.0 authentication infrastructure. """
27
28         self.new_config(
29             self.name,
30             pconfig.String(
31                 'database url',
32                 'Database URL for OpenID temp storage',
33                 'openid.sqlite'),
34             pconfig.String(
35                 'default email domain',
36                 'Used for users missing the email property.',
37                 'example.com'),
38             pconfig.String(
39                 'endpoint url',
40                 'The Absolute URL of the OpenID provider',
41                 'http://localhost:8080/idp/openid/'),
42             pconfig.Template(
43                 'identity url template',
44                 'The templated URL where identities are exposed.',
45                 'http://localhost:8080/idp/openid/id/%(username)s'),
46             pconfig.List(
47                 'trusted roots',
48                 'List of trusted relying parties.'),
49             pconfig.List(
50                 'untrusted roots',
51                 'List of untrusted relying parties.'),
52             pconfig.Choice(
53                 'enabled extensions',
54                 'Choose the extensions to enable',
55                 self.extensions.available().keys()),
56             pconfig.MappingList(
57                 'default attribute mapping',
58                 'Defines how to map attributes before calling extensions',
59                 [['*', '*']]),
60             pconfig.ComplexList(
61                 'default allowed attributes',
62                 'Defines a list of allowed attributes, applied after mapping',
63                 ['*']),
64         )
65
66     @property
67     def endpoint_url(self):
68         url = self.get_config_value('endpoint url')
69         if url.endswith('/'):
70             return url
71         else:
72             return url+'/'
73
74     @property
75     def default_email_domain(self):
76         return self.get_config_value('default email domain')
77
78     @property
79     def identity_url_template(self):
80         url = self.get_config_value('identity url template')
81         if url.endswith('/'):
82             return url
83         else:
84             return url+'/'
85
86     @property
87     def trusted_roots(self):
88         return self.get_config_value('trusted roots')
89
90     @property
91     def untrusted_roots(self):
92         return self.get_config_value('untrusted roots')
93
94     @property
95     def enabled_extensions(self):
96         return self.get_config_value('enabled extensions')
97
98     @property
99     def default_attribute_mapping(self):
100         return self.get_config_value('default attribute mapping')
101
102     @property
103     def default_allowed_attributes(self):
104         return self.get_config_value('default allowed attributes')
105
106     def get_tree(self, site):
107         self.page = OpenID(site, self)
108         # self.admin = AdminPage(site, self)
109
110         return self.page
111
112     def init_idp(self):
113         self.server = Server(
114             OpenIDStore(self.get_config_value('database url')),
115             op_endpoint=self.endpoint_url)
116
117         # Expose OpenID presence in the root
118         headers = self._root.default_headers
119         headers['X-XRDS-Location'] = self.endpoint_url+'XRDS'
120
121         html_heads = self._root.html_heads
122         HEAD_LINK = '<link rel="%s" href="%s">'
123         openid_heads = [HEAD_LINK % ('openid2.provider', self.endpoint_url),
124                         HEAD_LINK % ('openid.server', self.endpoint_url)]
125         html_heads['openid'] = openid_heads
126
127     def on_enable(self):
128         super(IdpProvider, self).on_enable()
129         self.init_idp()
130         self.extensions.enable(self._config['enabled extensions'].get_value())
131
132
133 class Installer(ProviderInstaller):
134
135     def __init__(self, *pargs):
136         super(Installer, self).__init__()
137         self.name = 'openid'
138         self.pargs = pargs
139
140     def install_args(self, group):
141         group.add_argument('--openid', choices=['yes', 'no'], default='yes',
142                            help='Configure OpenID Provider')
143         group.add_argument('--openid-dburi',
144                            help='OpenID database URI')
145         group.add_argument('--openid-extensions', default='',
146                            help='List of OpenID Extensions to enable')
147
148     def configure(self, opts, changes):
149         if opts['openid'] != 'yes':
150             return
151
152         proto = 'https'
153         if opts['secure'].lower() == 'no':
154             proto = 'http'
155         url = '%s://%s/%s/openid/' % (
156             proto, opts['hostname'], opts['instance'])
157
158         # Add configuration data to database
159         po = PluginObject(*self.pargs)
160         po.name = 'openid'
161         po.wipe_data()
162         po.wipe_config_values()
163         config = {'endpoint url': url,
164                   'identity url template': '%sid/%%(username)s' % url,
165                   'database url': opts['openid_dburi'] or
166                   opts['database_url'] % {
167                       'datadir': opts['data_dir'], 'dbname': 'openid'},
168                   'enabled extensions': opts['openid_extensions']}
169         po.save_plugin_config(config)
170
171         # Update global config to add login plugin
172         po.is_enabled = True
173         po.save_enabled_state()