Changeset 7327
- Timestamp:
- 16/08/10 13:54:09 (9 years ago)
- Location:
- TI12-security/trunk/NDGSecurity/python
- Files:
-
- 2 added
- 1 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/X509.py
r7155 r7327 698 698 'userid': 'UID' 699 699 } 700 PARSER_RE_STR = '/(%s)=' % '|'.join(__shortNameLUT.keys() + 701 __shortNameLUT.values()) 702 703 PARSER_RE = re.compile(PARSER_RE_STR) 700 SLASH_PARSER_RE_STR = '/(%s)=' % '|'.join(__shortNameLUT.keys() + 701 __shortNameLUT.values()) 702 SLASH_PARSER_RE = re.compile(SLASH_PARSER_RE_STR) 703 704 COMMA_PARSER_RE_STR = '[,]?\s*(%s)=' % '|'.join(__shortNameLUT.keys() + 705 __shortNameLUT.values()) 706 COMMA_PARSER_RE = re.compile(COMMA_PARSER_RE_STR) 704 707 705 708 def __init__(self, dn=None, m2CryptoX509Name=None, separator=None): … … 894 897 self.__separator = separator 895 898 896 897 899 # If no separator has been set, parse if from the DN string 898 900 if self.__separator is None: 899 901 self.__separator = self.parseSeparator(dn) 900 902 903 if self.__separator == '/': 904 parserRe = self.__class__.SLASH_PARSER_RE 905 906 elif self.__separator == ',': 907 parserRe = self.__class__.COMMA_PARSER_RE 908 else: 909 raise X500DNError("DN field separator %r not recognised" % 910 self.__separator) 911 901 912 try: 902 dnFields = X500DN.PARSER_RE.split(dn)913 dnFields = parserRe.split(dn) 903 914 if len(dnFields) < 2: 904 915 raise X500DNError("Error parsing DN string: \"%s\"" % dn) -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authz/service.py
r7257 r7327 49 49 50 50 POLICY_FILEPATH_OPTNAME = 'policyFilePath' 51 PIP_CFG_PREFIX = 'pip.'52 51 53 52 __slots__ = ( … … 98 97 99 98 # Initialise the XACML Context handler 100 ctxHandlerPrefix = prefix + \101 self.__class__.XACML_CTX_HANDLER_PARAM_PREFIX102 lenCtxHandlerPrefix = len(ctxHandlerPrefix)103 104 for optName, value in app_conf.items():105 if optName.startswith(ctxHandlerPrefix):106 attrName = optName[lenCtxHandlerPrefix:]107 setattr(self.__xacmlCtxHandler, attrName, value)108 109 # Read XACML policy into PDP110 self.__xacmlCtxHandler.pdp = PDP.fromPolicySource(policyFilePath,111 XacmlEtreePolicyReaderFactory)112 99 113 100 @classmethod -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/xacml/ctx_handler/saml_ctx_handler.py
r7298 r7327 12 12 log = logging.getLogger(__name__) 13 13 14 from os import path 15 from ConfigParser import SafeConfigParser, ConfigParser 14 16 from datetime import datetime, timedelta 15 17 from uuid import uuid4 … … 18 20 from ndg.saml.common import SAMLVersion 19 21 22 from ndg.xacml.core.context.pdp import PDP 20 23 from ndg.xacml.core import context as _xacmlContext 21 24 from ndg.xacml.core.attribute import Attribute as XacmlAttribute 22 25 from ndg.xacml.core.attributevalue import AttributeValueClassFactory as \ 23 26 XacmlAttributeValueClassFactory 24 from ndg.xacml.parsers.etree.factory import ReaderFactory 27 from ndg.xacml.parsers.etree.factory import ReaderFactory as \ 28 XacmlPolicyReaderFactory 25 29 26 30 from ndg.security.server.xacml.pip.saml_pip import PIP … … 65 69 Interface 66 70 """ 71 DEFAULT_OPT_PREFIX = 'saml_ctx_handler.' 72 PIP_OPT_PREFIX = 'pip.' 73 67 74 __slots__ = ( 68 75 '__policyFilePath', … … 74 81 super(SamlCtxHandler, self).__init__() 75 82 76 # Proxy object for SAML Response Issuer attributes. By generating a77 # proxy the Response objects inherent attribute validation can be78 # applied to Issuer related config parameters before they're assigned to79 # the response issuer object generated in the authorisation decision80 # query response83 # Proxy object for SAML AuthzDecisionQueryResponse Issuer attributes. 84 # By generating a proxy the Response objects inherent attribute 85 # validation can be applied to Issuer related config parameters before 86 # they're assigned to the response issuer object generated in the 87 # authorisation decision query response 81 88 self.__issuerProxy = _saml.Issuer() 82 89 self.__assertionLifetime = 0. 90 self.__policyFilePath = None 83 91 84 92 # Policy Information Point 85 93 self.pip = PIP() 86 94 95 @classmethod 96 def fromConfig(cls, cfg, **kw): 97 '''Alternative constructor makes object from config file settings 98 @type cfg: basestring /ConfigParser derived type 99 @param cfg: configuration file path or ConfigParser type object 100 @rtype: ndg.security.server.xacml.ctx_handler.saml_ctx_handler 101 @return: new instance of this class 102 ''' 103 obj = cls() 104 obj.parseConfig(cfg, **kw) 105 106 if obj.policyFilePath: 107 obj.pdp = PDP.fromPolicySource(obj.policyFilePath, 108 XacmlPolicyReaderFactory) 109 110 return obj 111 112 def parseConfig(self, cfg, prefix=DEFAULT_OPT_PREFIX, section='DEFAULT'): 113 '''Read config settings from a file, config parser object or dict 114 115 @type cfg: basestring / ConfigParser derived type / dict 116 @param cfg: configuration file path or ConfigParser type object 117 @type prefix: basestring 118 @param prefix: prefix for option names e.g. "attributeQuery." 119 @type section: basetring 120 @param section: configuration file section from which to extract 121 parameters. 122 ''' 123 if isinstance(cfg, basestring): 124 cfgFilePath = path.expandvars(cfg) 125 126 # Add a 'here' helper option for setting dir paths in the config 127 # file 128 hereDir = path.abspath(path.dirname(cfgFilePath)) 129 _cfg = SafeConfigParser(defaults={'here': hereDir}) 130 131 # Make option name reading case sensitive 132 _cfg.optionxform = str 133 _cfg.read(cfgFilePath) 134 items = _cfg.items(section) 135 136 elif isinstance(cfg, ConfigParser): 137 items = cfg.items(section) 138 139 elif isinstance(cfg, dict): 140 items = cfg.items() 141 else: 142 raise AttributeError('Expecting basestring, ConfigParser or dict ' 143 'type for "cfg" attribute; got %r type' % 144 type(cfg)) 145 146 self.__parseFromItems(items, prefix=prefix) 147 148 def __parseFromItems(self, items, prefix=DEFAULT_OPT_PREFIX): 149 """Update from list of tuple name, value pairs - for internal use 150 by parseKeywords and parseConfig 151 """ 152 prefixLen = len(prefix) 153 pipPrefix = self.__class__.PIP_OPT_PREFIX 154 pipPrefixLen = len(pipPrefix) 155 156 def _setAttr(__optName): 157 # Check for PIP attribute related items 158 if __optName.startswith(pipPrefix): 159 setattr(self.pip, __optName[pipPrefixLen:], val) 160 else: 161 setattr(self, __optName, val) 162 163 for optName, val in items: 164 if prefix: 165 # Filter attributes based on prefix 166 if optName.startswith(prefix): 167 _optName = optName[prefixLen:] 168 _setAttr(_optName) 169 else: 170 # No prefix set - attempt to set all attributes 171 _setAttr(optName) 172 173 def parseKeywords(self, prefix=DEFAULT_OPT_PREFIX, **kw): 174 """Update object from input keywords 175 176 @type prefix: basestring 177 @param prefix: if a prefix is given, only update self from kw items 178 where keyword starts with this prefix 179 @type kw: dict 180 @param kw: items corresponding to class instance variables to 181 update. Keyword names must match their equivalent class instance 182 variable names. However, they may prefixed with <prefix> 183 """ 184 self.__parseFromItems(kw.items(), prefix=prefix) 185 186 @classmethod 187 def fromKeywords(cls, prefix=DEFAULT_OPT_PREFIX, **kw): 188 """Create a new instance initialising instance variables from the 189 keyword inputs 190 @type prefix: basestring 191 @param prefix: if a prefix is given, only update self from kw items 192 where keyword starts with this prefix 193 @type kw: dict 194 @param kw: items corresponding to class instance variables to 195 update. Keyword names must match their equivalent class instance 196 variable names. However, they may prefixed with <prefix> 197 @return: new instance of this class 198 @rtype: ndg.saml.saml2.binding.soap.client.SOAPBinding or derived type 199 """ 200 obj = cls() 201 obj.parseKeywords(prefix=prefix, **kw) 202 203 if obj.policyFilePath: 204 obj.pdp = PDP.fromPolicySource(obj.policyFilePath, 205 XacmlPolicyReaderFactory) 206 207 return obj 208 209 def _getPolicyFilePath(self): 210 return self.__policyFilePath 211 212 def _setPolicyFilePath(self, value): 213 if not isinstance(value, basestring): 214 raise TypeError('Expecting string type for "policyFilePath"; got ' 215 '%r' % type(value)) 216 self.__policyFilePath = path.expandvars(value) 217 218 policyFilePath = property(_getPolicyFilePath, 219 _setPolicyFilePath, 220 doc="Policy file path for policy used by the PDP") 221 87 222 def _getIssuerFormat(self): 88 223 if self.__issuerProxy is None: … … 131 266 "set assertion conditions notOnOrAfter " 132 267 "time") 133 268 134 269 def handlePEPRequest(self, pepRequest): 135 270 """Handle request from Policy Enforcement Point … … 181 316 182 317 def pipQuery(self, request, designator): 183 """Query a Policy Information Point to retrieve the attribute values 318 """Implements interface method: 319 320 Query a Policy Information Point to retrieve the attribute values 184 321 corresponding to the specified input designator. Optionally, update the 185 322 request context. This could be a subject, environment or resource. 186 323 Matching attributes values are returned 187 """ 188 return self.pip.query(request, designator) 324 325 @param request: request context 326 @type request: ndg.xacml.core.context.request.Request 327 @param designator: designator requiring additional subject attribute 328 information 329 @type designator: ndg.xacml.core.expression.Expression derived type 330 @return: list of attribute values for subject corresponding to given 331 policy designator. Return None if none can be found 332 @rtype: ndg.xacml.utils.TypedList(<designator attribute type>) / None 333 """ 334 return self.pip.attributeQuery(request, designator) 189 335 190 336 def _createXacmlRequestCtx(self, samlAuthzDecisionQuery): -
TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/xacml/pip/saml_pip.py
r7314 r7327 15 15 from ConfigParser import SafeConfigParser, ConfigParser 16 16 17 from ndg.xacml.core.attributedesignator import SubjectAttributeDesignator 18 from ndg.xacml.core.attribute import Attribute as XacmlAttribute 19 from ndg.xacml.core.attributevalue import AttributeValueClassFactory as \ 20 XacmlAttributeValueClassFactory 17 21 from ndg.xacml.core.context.pipinterface import PIPInterface 18 from ndg.xacml.core.context.request import Request 22 from ndg.xacml.core.context.request import Request as XacmlRequestCtx 19 23 20 24 from ndg.saml.saml2.core import (AttributeQuery as SamlAttributeQuery, 21 25 Attribute as SamlAttribute) 22 from ndg.saml.utils import TypedList 26 from ndg.saml.utils import TypedList as SamlTypedList 23 27 from ndg.saml.saml2.binding.soap.client.attributequery import \ 24 28 AttributeQuerySslSOAPBinding … … 47 51 DEFAULT_OPT_PREFIX = 'saml_pip.' 48 52 53 XACML_ATTR_VAL_CLASS_FACTORY = XacmlAttributeValueClassFactory() 54 49 55 __slots__ = ( 50 56 '__subjectAttributeId', … … 113 119 @type cfg: basestring /ConfigParser derived type 114 120 @param cfg: configuration file path or ConfigParser type object 115 @rtype: ndg.s aml.saml2.binding.soap.client.SOAPBinding121 @rtype: ndg.security.server.xacml.pip.saml_pip.PIP 116 122 @return: new instance of this class 117 123 ''' … … 120 126 121 127 return obj 122 123 def __setAttr(self, optName, val):124 """Helper method to differentiate attribute query binding option names125 from other config options126 127 @param optName: config file option name128 @type optName: basestring129 @param val: corresponding value130 @type val: basestring131 """132 if optName.startswith(self.__class__.ATTRIBUTE_QUERY_ATTRNAME):133 setattr(self,134 optName[self.__class__.ATTRIBUTE_QUERY_ATTRNAME_OFFSET:],135 val)136 else:137 setattr(self, optName, val)138 128 139 129 def parseConfig(self, cfg, prefix=DEFAULT_OPT_PREFIX, section='DEFAULT'): … … 204 194 setattr(self.__attributeQueryBinding, queryAttrName, value) 205 195 else: 206 super(PIP, self).__setattr__(name, value) 196 super(PIP, self).__setattr__(name, value) 207 197 208 198 def readMappingFile(self): … … 218 208 219 209 def attributeQuery(self, context, attributeDesignator): 220 """Query this PIP for attributes. 210 """Query this PIP for the given request context attribute specified by 211 the attribute designator. Nb. this implementation is only intended to 212 accept queries for a given *subject* in the request 221 213 222 214 @param context: the request context 223 215 @type context: ndg.xacml.core.context.request.Request 224 @rtype: 225 @return: attribute values found for query subject 216 @param designator: 217 @type designator: ndg.xacml.core.attributedesignator.SubjectAttributeDesignator 218 @rtype: ndg.xacml.utils.TypedList(<attributeDesignator.dataType>) / None 219 @return: attribute values found for query subject or None if none 220 could be found 226 221 """ 227 if not isinstance(context, Request): 222 223 # Check the attribute designator type - this implementation takes 224 # queries for request context subjects only 225 if not isinstance(attributeDesignator, SubjectAttributeDesignator): 226 log.debug('This PIP query interface can only accept subject ' 227 'attribute designator related queries') 228 return None 229 230 if not isinstance(context, XacmlRequestCtx): 228 231 raise TypeError('Expecting %r type for context input; got %r' % 229 ( Request, type(context)))232 (XacmlRequestCtx, type(context))) 230 233 231 234 # TODO: Check for cached attributes for this subject (i.e. user) … … 243 246 attributeDesignator.attributeId) 244 247 245 return []248 return None 246 249 247 250 # Get subject from the request context … … 283 286 self.attributeQueryBinding.subjectID = '' 284 287 self.attributeQueryBinding.subjectIdFormat = '' 285 self.attributeQueryBinding.query.attributes = TypedList(288 self.attributeQueryBinding.query.attributes = SamlTypedList( 286 289 SamlAttribute) 287 290 288 # Unpack SAML assertion attribute values corresponding to the name 289 # format specified 290 attributeValues = [] 291 # Unpack SAML assertion attribute corresponding to the name 292 # format specified and copy into XACML attributes 293 xacmlAttribute = XacmlAttribute() 294 xacmlAttribute.attributeId = attributeDesignator.attributeId 295 xacmlAttribute.dataType = attributeFormat 296 297 # Create XACML class from SAML type identifier 298 factory = self.__class__.XACML_ATTR_VAL_CLASS_FACTORY 299 xacmlAttrValClass = factory(attributeFormat) 300 291 301 for assertion in response.assertions: 292 302 for statement in assertion.attributeStatements: 293 303 for attribute in statement.attributes: 294 304 if attribute.nameFormat == attributeFormat: 295 attributeValues.append(attribute.attributeValues) 305 # Convert SAML Attribute values to XACML equivalent 306 # types 307 for samlAttrVal in attribute.attributeValues: 308 # Instantiate and initial new XACML value 309 xacmlAttrVal = xacmlAttrValClass( 310 value=samlAttrVal.value) 311 312 xacmlAttribute.attributeValues.append(xacmlAttrVal) 296 313 297 314 # Update the XACML request context subject with the new attributes 298 xacmlCtxSubject.attributes.append( attributeValues)315 xacmlCtxSubject.attributes.append(xacmlAttribute) 299 316 300 317 # Return the attributes to the caller to comply with the interface 301 return attributeValues318 return xacmlAttribute.attributeValues 302 319 -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/__init__.py
r7168 r7327 131 131 X500DN.fromString("/O=Site A/CN=Authorisation Service"), 132 132 X500DN.fromString("/O=Site B/CN=Authorisation Service"), 133 X500DN.fromString('/CN=test/O=NDG/OU=BADC') 133 X500DN.fromString('/CN=test/O=NDG/OU=BADC'), 134 X500DN.fromString('/O=NDG/OU=Security/CN=localhost') 134 135 ) 135 136 -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/x509/test_x509.py
r6861 r7327 25 25 26 26 from ConfigParser import SafeConfigParser 27 27 28 from ndg.security.test.unit import BaseTestCase 28 29 import warnings 30 _warningMsg = None 31 _origWarn = warnings.warn 32 def _warnWrapper(*arg, **kw): 33 global _warningMsg 34 _warningMsg = arg[0] 35 _origWarn(*arg, **kw) 36 37 warnings.warn = _warnWrapper 38 39 from ndg.security.common.X509 import X509CertRead, X509CertParse, X500DN, \ 40 X509Stack, X509StackEmptyError, SelfSignedCert, X509CertIssuerNotFound 29 from ndg.security.common.X509 import (X509CertRead, X509CertParse, X500DN, 30 X509Stack, X509StackEmptyError, SelfSignedCert, X509CertIssuerNotFound) 31 41 32 42 33 class X509TestCase(BaseTestCase): 43 34 """Unit test X509 module""" 44 35 CA_DIR = os.path.join(BaseTestCase.NDGSEC_TEST_CONFIG_DIR, 'ca') 45 46 def __del__(self):47 warnings.warn = _origWarn48 if getattr(super(X509TestCase, self), "__del__", None):49 super(X509TestCase, self).__del__()50 36 51 37 def setUp(self): … … 189 175 self.test01X509CertRead() 190 176 191 # Set ridiculous bounds for expiry warning to ensure a warning message 192 # is output 193 self.assert_(self.x509Cert.isValidTime(nDaysBeforeExpiryLimit=36500), 194 "Certificate has expired") 195 if not _warningMsg: 196 self.fail("No warning message was set") 197 else: 198 print("PASSED - Got warning message from X509Cert." 199 "isValidTime: %s" % _warningMsg) 200 201 def test10ReadStackFromCADir(self): 202 203 stack = X509Stack.fromCADir(X509TestCase.CA_DIR) 204 self.assert_(stack) 205 self.assert_(len(stack) > 0) 177 warningMsg = None 178 179 # Capture stderr 180 try: 181 warningOutput = StringIO() 182 _stderr = sys.stderr 183 sys.stderr = warningOutput 184 185 # Set ridiculous bounds for expiry warning to ensure a warning 186 # message is output 187 validStatus = self.x509Cert.isValidTime( 188 nDaysBeforeExpiryLimit=36500) 189 self.assert_(validStatus, "Certificate has expired") 190 finally: 191 sys.stderr = _stderr 192 warningMsg = warningOutput.getvalue() 193 194 self.assert_("UserWarning" in str(warningMsg), 195 "No warning message was set") 196 197 print("PASSED - Got warning message from X509Cert.isValidTime: %s" % 198 warningMsg) 199 206 200 207 201 class X500DNTestCase(BaseTestCase): … … 215 209 self.assert_(str(dn)) 216 210 print(dn) 211 212 def test02VerifyCommaSeparatedDnParsing(self): 213 # Test parsing for ',' delimited fields 214 dnStr = 'O=NDG, OU=Security, CN=localhost' 215 dn = X500DN.fromString(dnStr) 216 self.assert_(str(dn)) 217 print(dn) 218 217 219 218 220 if __name__ == "__main__": -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/xacml/pip-mapping.txt
r7314 r7327 19 19 20 20 # Entries are whitespace delimited <attribute id> <attribute authority> 21 urn: ndg:security:attributeshttps://localhost:5443/AttributeAuthority21 urn:siteA:security:authz:1.0:attr https://localhost:5443/AttributeAuthority 22 22 myattributeid https://myattributeauthority.ac.uk/ 23 23 http://someotherattributeid.schema https://another.ac.uk/attributeservice/ -
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/xacml/test_saml_pip.py
r7314 r7327 38 38 CONFIG_FILEPATH = path.join(THIS_DIR, CONFIG_FILENAME) 39 39 40 NDGS_ATTR_ID = 'urn:ndg:security:attributes'40 NDGS_ATTR_ID = BaseTestCase.ATTRIBUTE_NAMES[0] 41 41 OPENID_ATTR_ID = 'urn:esg:openid' 42 OPENID = 'https://localhost:7443/pjkershaw'43 42 44 43 CLNT_CERT_FILEPATH = path.join(BaseTestCase.PKI_DIR, 'localhost.crt') … … 83 82 openidAttr.dataType) 84 83 85 openidAttrVal = anyUriAttrValue(self.__class__.OPENID )84 openidAttrVal = anyUriAttrValue(self.__class__.OPENID_URI) 86 85 openidAttr.attributeValues.append(openidAttrVal) 87 86 … … 115 114 ctx = self._createXacmlRequestCtx() 116 115 117 attributes = pip.attributeQuery(ctx, designator) 118 self.assert_(len(attributes) > 0) 116 attributeValues = pip.attributeQuery(ctx, designator) 117 self.assert_(len(attributeValues) > 0) 118 print("PIP retrieved attribute values %r" % attributeValues) 119 119 120 120 def test04InitFromConfigFile(self): … … 122 122 pip = PIP.fromConfig(self.__class__.CONFIG_FILEPATH) 123 123 self.assert_(pip.mappingFilePath) 124 125 for i in dir(PIP): 126 print("%s = %r" % (i, getattr(pip, i))) 124 127 125 128 126 if __name__ == "__main__":
Note: See TracChangeset
for help on using the changeset viewer.