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

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

Renamed PIP modules to avoid ndg name clash.

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