source: TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/xacml/pip/saml_pip.py @ 7298

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/xacml/pip/saml_pip.py@7298
Revision 7298, 7.2 KB checked in by pjkersha, 10 years ago (diff)

Incomplete - task 2: XACML-Security Integration

  • Working on PIP to make Attribute Service query
Line 
1"""Module for XACML Policy Information Point with SAML interface to
2Attribute Authority
3
4"""
5__author__ = "P J Kershaw"
6__date__ = "06/08/10"
7__copyright__ = "(C) 2010 Science and Technology Facilities Council"
8__license__ = "BSD - see LICENSE file in top-level directory"
9__contact__ = "Philip.Kershaw@stfc.ac.uk"
10__revision__ = '$Id:$'
11import logging
12log = logging.getLogger(__name__)
13
14from os import path
15from ConfigParser import SafeConfigParser
16
17from ndg.xacml.core.context.pipinterface import PIPInterface
18from ndg.xacml.core.context.request import Request
19
20from ndg.saml.saml2.core import AttributeQuery
21from ndg.saml.saml2.binding.soap.client.attributequery import \
22                                            AttributeQuerySslSOAPBinding
23                                           
24from ndg.security.common.X509 import X509Cert
25
26
27class PIP(PIPInterface):
28    '''Policy Information Point enables XACML PDP to query for additional user
29    attrbiutes.  The PDP does this indirectly via the Context Handler
30    '''
31    # Subject attributes makes no sense for external configuration - these
32    # are set at run time based on the given subject identity
33    DISALLOWED_ATTRIBUTE_QUERY_OPTNAMES = (
34        AttributeQuerySslSOAPBinding.SUBJECT_ID_OPTNAME,
35    )
36    ATTRIBUTE_QUERY_ATTRNAME = 'attributeQuery'
37    LEN_ATTRIBUTE_QUERY_ATTRNAME = len(ATTRIBUTE_QUERY_ATTRNAME)
38   
39    __slots__ = ('__attributeQueryBinding')
40   
41    def __init__(self):
42        '''Initialise settings for connection to an Attribute Authority'''
43        self.__attributeQueryBinding = AttributeQuerySslSOAPBinding()   
44
45    @classmethod
46    def fromConfig(cls, cfg, **kw):
47        '''Alternative constructor makes object from config file settings
48        @type cfg: basestring /ConfigParser derived type
49        @param cfg: configuration file path or ConfigParser type object
50        @rtype: ndg.saml.saml2.binding.soap.client.SOAPBinding
51        @return: new instance of this class
52        '''
53        obj = cls()
54        obj.parseConfig(cfg, **kw)
55       
56        return obj
57
58    def parseConfig(self, cfg, prefix='', section='DEFAULT'):
59        '''Read config settings from a file, config parser object or dict
60       
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 = SafeConfigParser()
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 and 
96            self.attributeQueryBinding.sslCtxProxy.sslCertFilePath is not None):
97            issuerX509Cert = X509Cert.Read(
98                        self.attributeQueryBinding.sslCtxProxy.sslCertFilePath)
99            self.attributeQueryBinding.issuerName = str(issuerX509Cert.dn)
100           
101    def __setattr__(self, name, value):
102        """Enable setting of AttributeQuerySslSOAPBinding attributes from
103        names starting with attributeQuery.* / attributeQuery_*.  Addition for
104        setting these values from ini file
105        """
106
107        # Coerce into setting AttributeQuerySslSOAPBinding attributes -
108        # names must start with 'attributeQuery\W' e.g.
109        # attributeQuery.clockSkew or attributeQuery_issuerDN
110        if name.startswith(self.__class__.ATTRIBUTE_QUERY_ATTRNAME):
111            queryAttrName = name[self.__class__.LEN_ATTRIBUTE_QUERY_ATTRNAME+1:]
112           
113            # Skip subject related parameters to prevent settings from static
114            # configuration.  These are set at runtime
115            if queryAttrName in self.__class__.DISALLOWED_ATTRIBUTE_QUERY_OPTNAMES:
116                super(PIP, self).__setattr__(name, value)
117               
118            setattr(self.__attributeQueryBinding, queryAttrName, value)
119        else:
120            super(PIP, self).__setattr__(name, value)   
121
122    @property
123    def attributeQueryBinding(self):
124        """SAML SOAP Attribute Query client binding object"""
125        return self.__attributeQueryBinding
126   
127    def readMappingFile(self):
128        """Read the file which maps attribute names to Attribute Authorities
129        """
130       
131    def attributeQuery(self, context, attributeDesignator):
132        """Query this PIP for attributes.   
133       
134        @param context: the request context
135        @type context: ndg.xacml.core.context.request.Request
136        @rtype:
137        @return: attribute values found for query subject
138        """
139        if not isinstance(context, Request):
140            raise TypeError('Expecting %r type for context input; got %r' %
141                            (Request, type(context)))
142       
143        # Check for cached attributes for this subject (i.e. user)
144       
145        # If none found send a query to the attribute authority
146       
147        # Find out the attribute authority corresponding to the query
148        attributeName = attributes[0]
149        attributeAuthorityURI = self.__attribute2AttributeAuthorityMap.get(attributeName)
150       
151               
152        log.debug("PIP: received attribute query: %r", attributeQuery)
153         
154        try:
155            self.attributeQueryBinding.subjectID = None
156            response = self.attributeQueryBinding.send(
157                                                    uri=attributeAuthorityURI)
158        finally:
159            # Ensure subject ID is reset ready for any subsequent query
160            self.attributeQueryBinding.subjectID = ''
161       
162        attributeResponse = PIPAttributeResponse()
163        attributeResponse[Subject.ROLES_NS] = []
164       
165        # Unpack assertion attribute values and add to the response object
166        for assertion in response.assertions:
167            for statement in assertion.attributeStatements:
168                for attribute in statement.attributes:
169                    attributeResponse[Subject.ROLES_NS] += [
170                        attributeValue.value
171                        for attributeValue in attribute.attributeValues
172                        if attributeValue.value not in attributeResponse[
173                                                            Subject.ROLES_NS]
174                    ]
175       
176        log.debug("PIP.attributeQuery response: %r", attributeResponse)
177       
178        return attributeResponse
179       
Note: See TracBrowser for help on using the repository browser.