Add support for attribute policies in openidp
[cascardo/ipsilon.git] / ipsilon / providers / openidp.py
1 # Copyright (C) 2014  Ipsilon project Contributors, for licensee see COPYING
2
3 from __future__ import absolute_import
4
5 from ipsilon.providers.common import ProviderBase
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.init_idp()
108         self.page = OpenID(site, self)
109         # self.admin = AdminPage(site, self)
110
111         return self.page
112
113     def init_idp(self):
114         self.server = Server(
115             OpenIDStore(self.get_config_value('database url')),
116             op_endpoint=self.endpoint_url)
117
118         # Expose OpenID presence in the root
119         headers = self._root.default_headers
120         headers['X-XRDS-Location'] = self.endpoint_url+'XRDS'
121
122         html_heads = self._root.html_heads
123         HEAD_LINK = '<link rel="%s" href="%s">'
124         openid_heads = [HEAD_LINK % ('openid2.provider', self.endpoint_url),
125                         HEAD_LINK % ('openid.server', self.endpoint_url)]
126         html_heads['openid'] = openid_heads
127
128     def on_enable(self):
129         super(IdpProvider, self).on_enable()
130         self.init_idp()
131         self.extensions.enable(self._config['enabled extensions'].get_value())
132
133
134 class Installer(object):
135
136     def __init__(self, *pargs):
137         self.name = 'openid'
138         self.ptype = 'provider'
139         self.pargs = pargs
140
141     def install_args(self, group):
142         group.add_argument('--openid', choices=['yes', 'no'], default='yes',
143                            help='Configure OpenID Provider')
144
145     def configure(self, opts):
146         if opts['openid'] != 'yes':
147             return
148
149         proto = 'https'
150         if opts['secure'].lower() == 'no':
151             proto = 'http'
152         url = '%s://%s/%s/openid/' % (
153             proto, opts['hostname'], opts['instance'])
154
155         # Add configuration data to database
156         po = PluginObject(*self.pargs)
157         po.name = 'openid'
158         po.wipe_data()
159         po.wipe_config_values()
160         config = {'endpoint url': url,
161                   'identity_url_template': '%sid/%%(username)s' % url}
162         po.save_plugin_config(config)
163
164         # Update global config to add login plugin
165         po.is_enabled = True
166         po.save_enabled_state()