source: TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/pip/ndg.py @ 6597

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/pip/ndg.py@6597
Revision 6597, 14.0 KB checked in by pjkersha, 11 years ago (diff)

New Policy Information Point class ndg.security.common.authz.pip.esg.PIP for ESG Authorisation Service.

Line 
1"""PIP with interface to the NDG2 Attribute Authority.  This uses a SOAP/WSDL
2based client interface and handles the NDG Attribute Certificate format.
3
4This interface is superceded by the SAML 2.0 based Attribute Query interface
5used with ESG.
6
7NERC DataGrid Project
8"""
9__author__ = "P J Kershaw"
10__date__ = "19/02/10"
11__copyright__ = "(C) 2010 Science and Technology Facilities Council"
12__contact__ = "Philip.Kershaw@stfc.ac.uk"
13__license__ = "BSD - see LICENSE file in top-level directory"
14__contact__ = "Philip.Kershaw@stfc.ac.uk"
15__revision__ = "$Id: $"
16import traceback
17import logging
18log = logging.getLogger(__name__)
19
20from ndg.security.common.wssecurity import WSSecurityConfig
21       
22from ndg.security.common.AttCert import (AttCertInvalidSignature, 
23    AttCertNotBeforeTimeError, AttCertExpired, AttCertError)
24     
25from ndg.security.common.sessionmanager import (SessionManagerClient, 
26    SessionNotFound, SessionCertTimeError, SessionExpired, InvalidSession, 
27    AttributeRequestDenied)
28
29from ndg.security.common.attributeauthority import (AttributeAuthorityClient, 
30    NoTrustedHosts, NoMatchingRoleInTrustedHosts, 
31    InvalidAttributeAuthorityClientCtx)
32from ndg.security.common.attributeauthority import AttributeRequestDenied as \
33    AA_AttributeRequestDenied
34   
35from ndg.security.common.authz import SubjectBase, SubjectRetrievalError
36from ndg.security.common.authz.pip import (PIPAttributeQuery, 
37                                           PIPAttributeResponse)         
38from ndg.security.common.authz.pdp import PDPUserAccessDenied
39
40
41class Subject(SubjectBase):
42    '''Subject designator'''
43    namespaces = (
44        "urn:ndg:security:authz:1.0:attr:subject:userId",
45        "urn:ndg:security:authz:1.0:attr:subject:sessionId",
46        "urn:ndg:security:authz:1.0:attr:subject:sessionManagerURI",
47    ) + SubjectBase.namespaces
48    (USERID_NS, SESSIONID_NS, SESSIONMANAGERURI_NS, ROLES_NS) = namespaces
49
50   
51class InvalidAttributeCertificate(SubjectRetrievalError):
52    "The certificate containing authorisation roles is invalid"
53    def __init__(self, msg=None):
54        SubjectRetrievalError.__init__(self, msg or 
55                                       InvalidAttributeCertificate.__doc__)
56
57
58class AttributeCertificateInvalidSignature(SubjectRetrievalError):
59    ("There is a problem with the signature of the certificate containing "
60     "authorisation roles")
61    def __init__(self, msg=None):
62        SubjectRetrievalError.__init__(self, msg or 
63                                AttributeCertificateInvalidSignature.__doc__)
64
65             
66class AttributeCertificateNotBeforeTimeError(SubjectRetrievalError):
67    ("There is a time issuing error with certificate containing authorisation "
68    "roles")
69    def __init__(self, msg=None):
70        SubjectRetrievalError.__init__(self, msg or 
71                                AttributeCertificateNotBeforeTimeError.__doc__)
72       
73class AttributeCertificateExpired(SubjectRetrievalError):
74    "The certificate containing authorisation roles has expired"
75    def __init__(self, msg=None):
76        SubjectRetrievalError.__init__(self, msg or 
77                                       AttributeCertificateExpired.__doc__)
78
79           
80class SessionExpiredMsg(SubjectRetrievalError):
81    'Session has expired.  Please re-login at your home organisation'
82    def __init__(self, msg=None):
83        SubjectRetrievalError.__init__(self, msg or SessionExpiredMsg.__doc__)
84
85
86class SessionNotFoundMsg(SubjectRetrievalError):
87    'No session was found.  Please try re-login with your home organisation'
88    def __init__(self, msg=None):
89        SubjectRetrievalError.__init__(self, msg or 
90                                       SessionNotFoundMsg.__doc__)
91
92
93class InvalidSessionMsg(SubjectRetrievalError):
94    'Session is invalid.  Please try re-login with your home organisation'
95    def __init__(self, msg=None):
96        SubjectRetrievalError.__init__(self, msg or 
97                                       InvalidSessionMsg.__doc__)
98
99
100class InitSessionCtxError(SubjectRetrievalError):
101    'A problem occurred initialising a session connection'
102    def __init__(self, msg=None):
103        SubjectRetrievalError.__init__(self, msg or 
104                                       InitSessionCtxError.__doc__)
105
106
107class AttributeCertificateRequestError(SubjectRetrievalError):
108    'A problem occurred requesting a certificate containing authorisation roles'
109    def __init__(self, msg=None):
110        SubjectRetrievalError.__init__(self, msg or 
111                                    AttributeCertificateRequestError.__doc__)
112       
113       
114class PIP(PIPBase):
115    """Policy Information Point - this implementation enables the PDP to
116    retrieve attributes about the Subject"""
117    wsseSectionName = 'wssecurity'
118   
119    def __init__(self, prefix='', **cfg):
120        '''Set-up WS-Security and SSL settings for connection to an
121        Attribute Authority
122       
123        @type **cfg: dict
124        @param **cfg: keywords including 'sslCACertFilePathList' used to set a
125        list of CA certificates for an SSL connection to the Attribute
126        Authority if used and also WS-Security settings as used by
127        ndg.security.common.wssecurity.WSSecurityConfig
128        '''
129        self.wssecurityCfg = WSSecurityConfig()
130        wssePrefix = prefix + PIP.wsseSectionName
131        self.wssecurityCfg.update(cfg, prefix=wssePrefix)
132                 
133        # List of CA certificates used to verify peer certificate with SSL
134        # connections to Attribute Authority
135        self.sslCACertFilePathList = cfg.get(prefix+'sslCACertFilePathList', [])
136       
137        # List of CA certificates used to verify the signatures of
138        # Attribute Certificates retrieved
139        self.caCertFilePathList = cfg.get(prefix + 'caCertFilePathList', [])
140
141    def attributeQuery(self, attributeQuery):
142        """Query the Attribute Authority specified in the request to retrieve
143        the attributes if any corresponding to the subject
144       
145        @type attributeResponse: PIPAttributeQuery
146        @param attributeResponse:
147        @rtype: PIPAttributeResponse
148        @return: response containing the attributes retrieved from the
149        Attribute Authority"""
150       
151        subject = attributeQuery[PIPAttributeQuery.SUBJECT_NS]
152        username = subject[Subject.USERID_NS]
153        sessionId = subject[Subject.SESSIONID_NS]
154        attributeAuthorityURI = attributeQuery[
155                                    PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS]
156       
157        sessionId = subject[Subject.SESSIONID_NS]
158       
159        log.debug("PIP: received attribute query: %r", attributeQuery)
160       
161        attributeCertificate = self._getAttributeCertificate(
162                    attributeAuthorityURI,
163                    username=username,
164                    sessionId=sessionId,
165                    sessionManagerURI=subject[Subject.SESSIONMANAGERURI_NS])
166
167        attributeResponse = PIPAttributeResponse()
168        attributeResponse[Subject.ROLES_NS] = attributeCertificate.roles
169       
170        log.debug("PIP.attributeQuery response: %r", attributeResponse)
171       
172        return attributeResponse
173   
174    def _getAttributeCertificate(self,
175                                 attributeAuthorityURI,
176                                 username=None,
177                                 sessionId=None,
178                                 sessionManagerURI=None):
179        '''Retrieve an Attribute Certificate
180
181        @type attributeAuthorityURI: basestring
182        @param attributeAuthorityURI: URI to Attribute Authority service
183        @type username: basestring
184        @param username: subject user identifier - could be an OpenID       
185        @type sessionId: basestring
186        @param sessionId: Session Manager session handle
187        @type sessionManagerURI: basestring
188        @param sessionManagerURI: URI to remote session manager service
189        @rtype: ndg.security.common.AttCert.AttCert
190        @return: Attribute Certificate containing user roles
191        '''
192
193        if sessionId and sessionManagerURI:
194            attrCert = self._getAttributeCertificateFromSessionManager(
195                                                     attributeAuthorityURI,
196                                                     sessionId,
197                                                     sessionManagerURI)
198        else:
199            attrCert = self._getAttributeCertificateFromAttributeAuthority(
200                                                     attributeAuthorityURI,
201                                                     username)
202       
203        try:
204            attrCert.certFilePathList = self.caCertFilePathList
205            attrCert.isValid(raiseExcep=True)
206       
207        except AttCertInvalidSignature, e:
208            log.exception(e)
209            raise AttributeCertificateInvalidSignature()
210       
211        except AttCertNotBeforeTimeError, e:   
212            log.exception(e)
213            raise AttributeCertificateNotBeforeTimeError()
214       
215        except AttCertExpired, e:   
216            log.exception(e)
217            raise AttributeCertificateExpired()
218
219        except AttCertError, e:
220            log.exception(e)
221            raise InvalidAttributeCertificate()
222       
223        return attrCert
224           
225    def _getAttributeCertificateFromSessionManager(self,
226                                                   attributeAuthorityURI,
227                                                   sessionId,
228                                                   sessionManagerURI):
229        '''Retrieve an Attribute Certificate using the subject's Session
230        Manager
231       
232        @type sessionId: basestring
233        @param sessionId: Session Manager session handle
234        @type sessionManagerURI: basestring
235        @param sessionManagerURI: URI to remote session manager service
236        @type attributeAuthorityURI: basestring
237        @param attributeAuthorityURI: URI to Attribute Authority service
238        @rtype: ndg.security.common.AttCert.AttCert
239        @return: Attribute Certificate containing user roles
240        '''
241       
242        log.debug("PIP._getAttributeCertificateFromSessionManager ...")
243       
244        try:
245            # Create Session Manager client - if a file path was set, setting
246            # are read from a separate config file section otherwise, from the
247            # PDP config object
248            smClnt = SessionManagerClient(
249                            uri=sessionManagerURI,
250                            sslCACertFilePathList=self.sslCACertFilePathList,
251                            cfg=self.wssecurityCfg)
252        except Exception, e:
253            log.error("Creating Session Manager client: %s" % e)
254            raise InitSessionCtxError()
255             
256        try:
257            # Make request for attribute certificate
258            return smClnt.getAttCert(
259                                attributeAuthorityURI=attributeAuthorityURI,
260                                sessID=sessionId)
261       
262        except AttributeRequestDenied, e:
263            log.error("Request for attribute certificate denied: %s" % e)
264            raise PDPUserAccessDenied()
265       
266        except SessionNotFound, e:
267            log.error("No session found: %s" % e)
268            raise SessionNotFoundMsg()
269
270        except SessionExpired, e:
271            log.error("Session expired: %s" % e)
272            raise SessionExpiredMsg()
273
274        except SessionCertTimeError, e:
275            log.error("Session cert. time error: %s" % e)
276            raise InvalidSessionMsg()
277           
278        except InvalidSession, e:
279            log.error("Invalid user session: %s" % e)
280            raise InvalidSessionMsg()
281
282        except Exception, e:
283            log.error("Request from Session Manager [%s] to Attribute "
284                      "Authority [%s] for attribute certificate: %s: %s" % 
285                      (sessionManagerURI,
286                       attributeAuthorityURI,
287                       e.__class__, e))
288            raise AttributeCertificateRequestError()
289           
290    def _getAttributeCertificateFromAttributeAuthority(self,
291                                                       attributeAuthorityURI,
292                                                       username):
293        '''Retrieve an Attribute Certificate direct from an Attribute
294        Authority.  This method is invoked if no session ID or Session
295        Manager endpoint where provided
296       
297        @type username: basestring
298        @param username: user identifier - may be an OpenID URI
299        @type attributeAuthorityURI: basestring
300        @param attributeAuthorityURI: URI to Attribute Authority service
301        @rtype: ndg.security.common.AttCert.AttCert
302        @return: Attribute Certificate containing user roles
303        '''
304       
305        log.debug("PIP._getAttributeCertificateFromAttributeAuthority ...")
306       
307        try:
308            # Create Attribute Authority client - if a file path was set,
309            # settingare read  from a separate config file section otherwise,
310            # from the PDP config object
311            aaClnt = AttributeAuthorityClient(
312                            uri=attributeAuthorityURI,
313                            sslCACertFilePathList=self.sslCACertFilePathList,
314                            cfg=self.wssecurityCfg)
315        except Exception:
316            log.error("Creating Attribute Authority client: %s",
317                      traceback.format_exc())
318            raise InitSessionCtxError()
319       
320         
321        try:
322            # Make request for attribute certificate
323            return aaClnt.getAttCert(userId=username)
324       
325       
326        except AA_AttributeRequestDenied:
327            log.error("Request for attribute certificate denied: %s",
328                      traceback.format_exc())
329            raise PDPUserAccessDenied()
330       
331        # TODO: handle other specific Exception types here for more fine
332        # grained response info
333
334        except Exception, e:
335            log.error("Request to Attribute Authority [%s] for attribute "
336                      "certificate: %s: %s", attributeAuthorityURI,
337                      e.__class__, traceback.format_exc())
338            raise AttributeCertificateRequestError()
339       
Note: See TracBrowser for help on using the repository browser.