Add ability to strip domain/realm per provider
[cascardo/ipsilon.git] / ipsilon / providers / saml2 / provider.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2014  Simo Sorce <simo@redhat.com>
4 #
5 # see file 'COPYING' for use and warranty information
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 import cherrypy
21 import lasso
22
23
24 NAMEID_MAP = {
25     'email': lasso.SAML2_NAME_IDENTIFIER_FORMAT_EMAIL,
26     'encrypted': lasso.SAML2_NAME_IDENTIFIER_FORMAT_ENCRYPTED,
27     'entity': lasso.SAML2_NAME_IDENTIFIER_FORMAT_ENTITY,
28     'kerberos': lasso.SAML2_NAME_IDENTIFIER_FORMAT_KERBEROS,
29     'persistent': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
30     'transient': lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT,
31     'unspecified': lasso.SAML2_NAME_IDENTIFIER_FORMAT_UNSPECIFIED,
32     'windows': lasso.SAML2_NAME_IDENTIFIER_FORMAT_WINDOWS,
33     'x509': lasso.SAML2_NAME_IDENTIFIER_FORMAT_X509,
34 }
35
36
37 class InvalidProviderId(Exception):
38
39     def __init__(self, message):
40         msg = 'Invalid Provider ID: %s' % message
41         super(InvalidProviderId, self).__init__(msg)
42         self.message = msg
43
44     def __str__(self):
45         return repr(self.message)
46
47
48 class NameIdNotAllowed(Exception):
49
50     def __init__(self):
51         message = 'The specified Name ID is not allowed'
52         super(NameIdNotAllowed, self).__init__(message)
53         self.message = message
54
55     def __str__(self):
56         return repr(self.message)
57
58
59 class ServiceProvider(object):
60
61     def __init__(self, config, provider_id):
62         self.cfg = config
63         data = self.cfg.get_data(name='id', value=provider_id)
64         if len(data) != 1:
65             raise InvalidProviderId('multiple matches')
66         idval = data.keys()[0]
67         data = self.cfg.get_data(idval=idval)
68         self._properties = data[idval]
69
70     @property
71     def provider_id(self):
72         return self._properties['id']
73
74     @property
75     def name(self):
76         return self._properties['name']
77
78     @property
79     def allowed_namedids(self):
80         if 'allowed nameid' in self._properties:
81             return self._properties['allowed nameid']
82         else:
83             return self.cfg.default_allowed_nameids
84
85     @property
86     def default_nameid(self):
87         if 'default nameid' in self._properties:
88             return self._properties['default nameid']
89         else:
90             return self.cfg.default_nameid
91
92     def get_valid_nameid(self, nip):
93         self._debug('Requested NameId [%s]' % (nip.format,))
94         if nip.format == None:
95             return NAMEID_MAP[self.default_nameid]
96         elif nip.format == lasso.SAML2_NAME_IDENTIFIER_FORMAT_UNSPECIFIED:
97             return NAMEID_MAP[self.default_nameid]
98         else:
99             allowed = self.allowed_namedids
100             self._debug('Allowed NameIds %s' % (repr(allowed)))
101             for nameid in allowed:
102                 if nip.format == NAMEID_MAP[nameid]:
103                     return nip.format
104         raise NameIdNotAllowed()
105
106     def _debug(self, fact):
107         if cherrypy.config.get('debug', False):
108             cherrypy.log(fact)
109
110     def normalize_username(self, username):
111         if 'strip domain' in self._properties:
112             return username.split('@', 1)[0]
113         return username