Changeset 7310
- Timestamp:
- 10/08/10 16:40:37 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/xacml/pip/saml_pip.py
r7298 r7310 18 18 from ndg.xacml.core.context.request import Request 19 19 20 from ndg.saml.saml2.core import AttributeQuery 20 from ndg.saml.saml2.core import (AttributeQuery as SamlAttributeQuery, 21 Attribute as SamlAttribute) 22 from ndg.saml.utils import TypedList as SamlTypedList 21 23 from ndg.saml.saml2.binding.soap.client.attributequery import \ 22 24 AttributeQuerySslSOAPBinding … … 33 35 DISALLOWED_ATTRIBUTE_QUERY_OPTNAMES = ( 34 36 AttributeQuerySslSOAPBinding.SUBJECT_ID_OPTNAME, 37 AttributeQuerySslSOAPBinding.QUERY_ATTRIBUTES_ATTRNAME 35 38 ) 36 39 ATTRIBUTE_QUERY_ATTRNAME = 'attributeQuery' 37 40 LEN_ATTRIBUTE_QUERY_ATTRNAME = len(ATTRIBUTE_QUERY_ATTRNAME) 38 41 39 __slots__ = ('__attributeQueryBinding') 42 # +1 allows for '.' or other separator e.g. 43 # pip.attributeQuery.issuerName 44 # ^ 45 ATTRIBUTE_QUERY_ATTRNAME_OFFSET = LEN_ATTRIBUTE_QUERY_ATTRNAME + 1 46 47 __slots__ = ('__mappingFilePath',) 40 48 41 49 def __init__(self): 42 50 '''Initialise settings for connection to an Attribute Authority''' 43 51 self.__attributeQueryBinding = AttributeQuerySslSOAPBinding() 52 self.__mappingFilePath = None 53 54 def _getMappingFilePath(self): 55 return self.__mappingFilePath 56 57 def _setMappingFilePath(self, value): 58 if not isinstance(value, basestring): 59 raise TypeError('Expecting string type for "mappingFilePath"; got ' 60 '%r' % type(value)) 61 self.__mappingFilePath = value 62 63 mappingFilePath = property(_getMappingFilePath, 64 _setMappingFilePath, 65 doc="Mapping File maps attribute IDs to the " 66 "Attribute Authorities from which they may " 67 "be queried for") 44 68 45 69 @classmethod … … 55 79 56 80 return obj 81 82 def __setAttr(self, optName, val): 83 """Helper method to differentiate attribute query binding option names 84 from other config options 85 86 @param optName: config file option name 87 @type optName: basestring 88 @param val: corresponding value 89 @type val: basestring 90 """ 91 if optName.startswith(self.__class__.ATTRIBUTE_QUERY_ATTRNAME): 92 setattr(self, 93 optName[self.__class__.ATTRIBUTE_QUERY_ATTRNAME_OFFSET:], 94 val) 95 else: 96 setattr(self, optName, val) 57 97 58 98 def parseConfig(self, cfg, prefix='', section='DEFAULT'): … … 84 124 85 125 prefixLen = len(prefix) 126 86 127 for optName, val in items: 87 128 if prefix: 88 129 # Filter attributes based on prefix 89 130 if optName.startswith(prefix): 90 se tattr(self,optName[prefixLen:], val)131 self.__setAttr(optName[prefixLen:], val) 91 132 else: 92 133 # 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 134 self.__setAttr(optName, val) 135 136 # def __setattr__(self, name, value): 137 # """Enable setting of AttributeQuerySslSOAPBinding attributes from 138 # names starting with attributeQuery.* / attributeQuery_*. Addition for 139 # setting these values from ini file 140 # """ 141 # 142 # # Coerce into setting AttributeQuerySslSOAPBinding attributes - 143 # # names must start with 'attributeQuery\W' e.g. 144 # # attributeQuery.clockSkew or attributeQuery_issuerDN 145 # if name.startswith(self.__class__.ATTRIBUTE_QUERY_ATTRNAME): 146 # queryAttrName = name[ 147 # self.__class__.ATTRIBUTE_QUERY_ATTRNAME_OFFSET:] 148 # 149 # # Skip subject and attribute Id related parameters to prevent 150 # # settings from static configuration. These are set from the 151 # # incoming XACML context 152 # if min([queryAttrName.startswith(i) for i in 153 # self.__class__.DISALLOWED_ATTRIBUTE_QUERY_OPTNAMES]): 154 # super(PIP, self).__setattr__(name, value) 155 # 156 # setattr(self.__attributeQueryBinding, queryAttrName, value) 157 # else: 158 # super(PIP, self).__setattr__(name, value) 159 126 160 127 161 def readMappingFile(self): 128 162 """Read the file which maps attribute names to Attribute Authorities 129 163 """ 164 mappingFile = open(self.mappingFilePath) 165 self.__attribute2AttributeAuthorityMap = dict() 166 for line in mappingFile.readline(): 167 if not line.startswith('#'): 168 attributeId, attributeAuthorityURI = line.split() 169 self.__attribute2AttributeAuthorityMap[attributeId 170 ] = attributeAuthorityURI 130 171 131 172 def attributeQuery(self, context, attributeDesignator): … … 141 182 (Request, type(context))) 142 183 143 # Check for cached attributes for this subject (i.e. user)184 # TODO: Check for cached attributes for this subject (i.e. user) 144 185 145 186 # If none found send a query to the attribute authority 146 187 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 188 # TODO: Look-up the attribute authority corresponding to the query 189 190 # attributeAuthorityURI = self.__attribute2AttributeAuthorityMap.get( 191 # attributeName) 192 attributeAuthorityURI = 'https://localhost:7443/AttributeAuthority' 193 194 # Get subject from the request context 195 # TODO: parameterise data type setting 196 subjectId = None 197 for subject in context.subjects: 198 for attribute in subject.attributes: 199 if attribute.dataType == 'urn:esg:openid': 200 if len(attribute.attributeValues) != 1: 201 raise Exception("Expecting a single attribute value " 202 "for query subject ID") 203 subjectId = attribute.attributeValues[0].value 204 break 205 206 if subjectId is None: 207 # TODO: parameterise data type setting 208 raise Exception('No subject found of type %r in request context' % 209 'urn:esg:openid') 210 else: 211 # Keep a reference to the matching Subject instance 212 _subject = subject 213 214 # Get the id of the attribute to be queried for and add it to the SAML 215 # query 216 attributeFormat = attributeDesignator.dataType 217 samlAttribute = SamlAttribute() 218 samlAttribute.name = attributeDesignator.attributeId 219 samlAttribute.nameFormat = attributeFormat 220 attributeQueryBinding.query.attributes.append(samlAttribute) 221 222 223 attributeQueryBinding.subjectID = subjectId 224 response = attributeQueryBinding.send(uri=attributeAuthorityURI) 225 226 # Unpack SAML assertion attribute values corresponding to the name 227 # format specified 228 attributeValues = [] 166 229 for assertion in response.assertions: 167 230 for statement in assertion.attributeStatements: 168 231 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 232 if attribute.nameFormat == attributeFormat: 233 attributeValues.append(attribute.attributeValues) 234 235 # Update the XACML request context subject with the new attributes 236 _subject.attributes.append(attributeValues) 237 238 # Return the attributes to the caller to comply with the interface 239 return attributeValues 179 240
Note: See TracChangeset
for help on using the changeset viewer.