source: TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/pip/esg.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/esg.py@6597
Revision 6597, 6.3 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 SAML 2.0 Attribute Authority as used with ESG
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "19/02/10"
7__copyright__ = "(C) 2010 Science and Technology Facilities Council"
8__contact__ = "Philip.Kershaw@stfc.ac.uk"
9__license__ = "BSD - see LICENSE file in top-level directory"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = "$Id: $"
12import traceback
13import logging
14log = logging.getLogger(__name__)
15
16from ndg.security.common.saml_utils.attributeQuery import \
17                                            AttributeQuerySslSOAPBinding
18from ndg.security.common.X509 import X509Cert
19from ndg.security.common.authz import SubjectBase
20from ndg.security.common.authz.pip import (PIPBase, PIPAttributeQuery, 
21                                           PIPAttributeResponse)
22
23
24class Subject(SubjectBase):
25    """Container for information about the subject of the query"""
26   
27
28class PIP(PIPBase):
29    """Policy Information Point to query ESG Attribute Authority for user
30    attributes
31    """
32         
33    ATTRIBUTE_QUERY_ATTRNAME = 'attributeQuery'
34    LEN_ATTRIBUTE_QUERY_ATTRNAME = len(ATTRIBUTE_QUERY_ATTRNAME)
35   
36    __slots__ = ('__attributeQueryBinding')
37   
38    def __init__(self):
39        '''Initialise settings for connection to an Attribute Authority'''
40        self.__attributeQueryBinding = None
41   
42    def parse(self, prefix='', **cfg):
43        self.__attributeQueryBinding = AttributeQuerySslSOAPBinding()
44       
45
46    @classmethod
47    def fromConfig(cls, cfg, **kw):
48        '''Alternative constructor makes object from config file settings
49        @type cfg: basestring /ConfigParser derived type
50        @param cfg: configuration file path or ConfigParser type object
51        @rtype: ndg.security.common.saml_utils.binding.soap.SOAPBinding
52        @return: new instance of this class
53        '''
54        obj = cls()
55        obj.parseConfig(cfg, **kw)
56       
57        return obj
58
59    def parseConfig(self, cfg, prefix='', section='DEFAULT'):
60        '''Read config settings from a file, config parser object or dict
61        @type cfg: basestring / ConfigParser derived type / dict
62        @param cfg: configuration file path or ConfigParser type object
63        @type prefix: basestring
64        @param prefix: prefix for option names e.g. "attributeQuery."
65        @type section: baestring
66        @param section: configuration file section from which to extract
67        parameters.
68        ''' 
69        if isinstance(cfg, basestring):
70            cfgFilePath = path.expandvars(cfg)
71            _cfg = CaseSensitiveConfigParser()
72            _cfg.read(cfgFilePath)
73            items = _cfg.items(section)
74           
75        elif isinstance(cfg, ConfigParser):
76            items = cfg.items(section)
77         
78        elif isinstance(cfg, dict):
79            items = cfg.items()     
80        else:
81            raise AttributeError('Expecting basestring, ConfigParser or dict '
82                                 'type for "cfg" attribute; got %r type' % 
83                                 type(cfg))
84       
85        prefixLen = len(prefix)
86        for optName, val in items:
87            if prefix:
88                # Filter attributes based on prefix
89                if optName.startswith(prefix):
90                    setattr(self, optName[prefixLen:], val)
91            else:
92                # No prefix set - attempt to set all attributes   
93                setattr(self, optName, val)
94               
95        if not self.__attributeQueryBinding.issuerName:
96            issuerX509Cert = X509Cert.Read(
97                    self.__attributeQueryBinding.sslCtxProxy.sslCertFilePath)
98            self.__attributeQueryBinding.issuerName = str(issuerX509Cert.dn)
99           
100    def __setattr__(self, name, value):
101        """Enable setting of AttributeQuerySslSOAPBinding attributes from
102        names starting with attributeQuery.* / attributeQuery_*.  Addition for
103        setting these values from ini file
104        """
105
106        # Coerce into setting AttributeQuerySslSOAPBinding attributes -
107        # names must start with 'attributeQuery\W' e.g.
108        # attributeQuery.clockSkew or attributeQuery_issuerDN
109        if name.startswith(PIP.ATTRIBUTE_QUERY_ATTRNAME):
110            setattr(self.__attributeQueryBinding, 
111                    name[PIP.LEN_ATTRIBUTE_QUERY_ATTRNAME+1:], 
112                    value)
113        else:
114            super(PIP, self).__setattr__(name, value)   
115
116    @property
117    def attributeQueryBinding(self):
118        """SAML SOAP Attribute Query client binding object"""
119        return self.__attributeQueryBinding
120   
121    def attributeQuery(self, attributeQuery):
122        """Query the Attribute Authority specified in the request to retrieve
123        the attributes if any corresponding to the subject
124       
125        @type attributeResponse: PIPAttributeQuery
126        @param attributeResponse:
127        @rtype: PIPAttributeResponse
128        @return: response containing the attributes retrieved from the
129        Attribute Authority"""
130        if not isinstance(attributeQuery, PIPAttributeQuery):
131            raise TypeError('Expecting %r type for input "attributeQuery"; '
132                            'got %r' % (PIPAttributeQuery, 
133                                        type(attributeQuery)))
134                           
135        attributeAuthorityURI = attributeQuery[
136                                        PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS]
137       
138        log.debug("PIP: received attribute query: %r", attributeQuery)
139         
140        response = self.attributeQueryBinding.send(uri=attributeAuthorityURI)
141       
142        attributeResponse = PIPAttributeResponse()
143        attributeResponse[Subject.ROLES_NS] = []
144       
145        # Unpack assertion attribute values and add to the response object
146        for assertion in response.assertions:
147            for statement in assertion.attributeStatements:
148                for attribute in statement.attributes:
149                    attributeResponse[Subject.ROLES_NS] += [
150                        attributeValue.value
151                        for attributeValue in attribute.attributeValues
152                        if attributeValue.value not in attributeResponse[
153                                                            Subject.ROLES_NS]
154                    ]
155       
156        log.debug("PIP.attributeQuery response: %r", attributeResponse)
157       
158        return attributeResponse
Note: See TracBrowser for help on using the repository browser.