Changeset 5182 for TI12-security
- Timestamp:
- 08/04/09 12:36:14 (12 years ago)
- Location:
- TI12-security/trunk/python
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/python/ndg.security.common/ndg/security/common/AttCert.py
r5181 r5182 39 39 """Exception handling for NDG Attribute Certificate class.""" 40 40 41 class AttCertInvalidSignature(AttCertError): 42 """Error with certificate signature""" 43 41 44 class AttCertNotBeforeTimeError(AttCertError): 42 45 """Current time is before the Attribute Certificate's not before time""" … … 1076 1079 if chkProvenance and not self.isValidProvenance(): 1077 1080 if raiseExcep: 1078 raise AttCertError( 1079 "Attribute Certificate Provenance must be set to \""1080 "\" or \"".join(AttCert.__validProvenanceSettings) + "\"")1081 raise AttCertError('Attribute Certificate Provenance must be ' 1082 'set to "%s"' % "\" or \"".join( 1083 AttCert.__validProvenanceSettings)) 1081 1084 return False 1082 1085 … … 1089 1092 except InvalidSignature, e: 1090 1093 if raiseExcep: 1091 raise AttCert Error(e)1094 raise AttCertInvalidSignature(e) 1092 1095 else: 1093 1096 return False -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/msi.py
r5181 r5182 17 17 # For parsing: ElementTree helpers 18 18 getNs = lambda elem: elem.tag.split('}')[0][1:] 19 getLocalName = lambda elem: elem.tag.rsplit('}', 1)[-1]19 getLocalName = lambda elem: elem.tag.rsplit('}', 1)[ - 1] 20 20 21 21 class PolicyParseError(Exception): … … 43 43 44 44 else: 45 raise PolicyParseError("Invalid policy attribute: %s" % 45 raise PolicyParseError("Invalid policy attribute: %s" % 46 46 localName) 47 47 … … 79 79 self.attributeAuthorityURI = elem[0].text.strip() 80 80 else: 81 raise ResourceParseError("Invalid resource attribute: %s" % 81 raise ResourceParseError("Invalid resource attribute: %s" % 82 82 localName) 83 83 … … 114 114 if key not in self.__class__.namespaces: 115 115 raise KeyError('Namespace "%s" not recognised. Valid ' 116 'namespaces are: %s' % 116 'namespaces are: %s' % 117 117 self.__class__.namespaces) 118 118 … … 177 177 SubjectRetrievalError.__init__(self, msg or 178 178 InvalidAttributeCertificate.__doc__) 179 179 180 class AttributeCertificateInvalidSignature(SubjectRetrievalError): 181 ("There is a problem with the signature of the certificate containing " 182 "authorisation roles") 183 def __init__(self, msg=None): 184 SubjectRetrievalError.__init__(self, msg or 185 AttributeCertificateInvalidSignature.__doc__) 186 180 187 class AttributeCertificateNotBeforeTimeError(SubjectRetrievalError): 181 188 ("There is a time issuing error with certificate containing authorisation " … … 217 224 'A problem occurred requesting a certificate containing authorisation roles' 218 225 def __init__(self, msg=None): 219 SubjectRetrievalError.__init__(self, msg or226 SubjectRetrievalError.__init__(self, msg or 220 227 AttributeCertificateRequestError.__doc__) 221 228 222 229 class PIPAttributeQuery(_AttrDict): 230 '''Policy Information Point Query class.''' 223 231 namespaces = ( 224 232 "urn:ndg:security:authz:1.0:attr:subject", … … 227 235 (SUBJECT_NS, ATTRIBUTEAUTHORITY_NS) = namespaces 228 236 229 class PIPAttributeResponse(_AttrDict): 237 class PIPAttributeResponse(dict): 238 '''Policy Information Point Response class.''' 230 239 namespaces = ( 231 "urn:ndg:security:authz:1.0:attr:attributeCertificate",240 Subject.ROLES_NS, 232 241 ) 233 (ATTRIBUTECERTIFICATE_NS,) = namespaces234 242 235 243 … … 251 259 ndg.security.common.wssecurity.WSSecurityConfig 252 260 ''' 253 self._subjectCache = {}254 255 261 self.wssecurityCfg = WSSecurityConfig() 256 262 wssePrefix = prefix + 'wssecurity' 257 263 self.wssecurityCfg.update(cfg, prefix=wssePrefix) 258 264 259 self.sslCACertFilePathList = cfg.get(prefix+'sslCACertFilePathList',[]) 265 # List of CA certificates used to verify peer certificate with SSL 266 # connections to Attribute Authority 267 self.sslCACertFilePathList = cfg.get(prefix + 'sslCACertFilePathList', []) 268 269 # List of CA certificates used to verify the signatures of 270 # Attribute Certificates retrieved 271 self.caCertFilePathList = cfg.get(prefix + 'caCertFilePathList', []) 260 272 261 273 def attributeQuery(self, attributeQuery): … … 274 286 PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS] 275 287 276 # Check this subject's cache for an Attribute Certificate previously 277 # retrieved. 278 attributeCertificate = None 279 if self._subjectCache.get(sessionId) is not None: 280 subjectCred = subjectCache.credentialByURI.get( 281 attributeAuthorityURI) 282 283 if subjectCred is not None: 284 if subjectCred['attCert'].isValid(): 285 attributeCertificate = subjectCred['attCert'] 286 287 # If no Attribute Certificate is available, retrieve from the relevant 288 # Attribute Authority 289 if attributeCertificate is None: 290 sessionId = subject[Subject.SESSIONID_NS] 291 attributeCertificate = self._getAttributeCertificate( 288 sessionId = subject[Subject.SESSIONID_NS] 289 attributeCertificate = self._getAttributeCertificate( 292 290 sessionId, 293 291 subject[Subject.SESSIONMANAGERURI_NS], 294 292 attributeAuthorityURI) 295 296 # Make a new wallet for this subject297 self._subjectCache[sessionId] = \298 CredentialWallet(userId=attributeCertificate.userId)299 300 self._subjectCache[sessionId].addCredential(301 attributeCertificate,302 attributeAuthorityURI=attributeAuthorityURI)303 293 304 294 attributeResponse = PIPAttributeResponse() 305 attributeResponse[PIPAttributeResponse.ATTRIBUTECERTIFICATE_NS] = \ 306 attributeCertificate 295 attributeResponse[Subject.ROLES_NS] = attributeCertificate.roles 307 296 308 297 return attributeResponse 309 298 310 299 311 def _getAttributeCertificate(self, 300 def _getAttributeCertificate(self, 312 301 sessionId, 313 302 sessionManagerURI, … … 372 361 373 362 try: 363 attCert.certFilePathList = self.caCertFilePathList 374 364 attCert.isValid(raiseExcep=True) 365 366 except AttCertInvalidSignature, e: 367 log.exception(e) 368 raise AttributeCertificateInvalidSignature() 375 369 376 370 except AttCertNotBeforeTimeError, e: … … 415 409 416 410 attributeQuery = PIPAttributeQuery() 417 attributeQuery[PIPAttributeQuery.SUBJECT_NS] =request.subject411 attributeQuery[PIPAttributeQuery.SUBJECT_NS] = request.subject 418 412 419 413 attributeQuery[PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS] = \ 420 414 matchingTarget.attributeAuthorityURI 421 415 422 attributeResponse = self.pip.attributeQuery(attributeQuery) 416 try: 417 attributeResponse = self.pip.attributeQuery(attributeQuery) 418 419 except SubjectRetrievalError, e: 420 log.exception(e) 421 return Response(Response.DECISION_INDETERMINATE, 422 message=str(e)) 423 424 except Exception, e: 425 log.exception(e) 426 return Response(Response.DECISION_INDETERMINATE, 427 message="An internal error occurred") 428 423 429 knownAttributeAuthorityURIs.append( 424 430 matchingTarget.attributeAuthorityURI) 425 431 426 attributeCertificate = attributeResponse[ 427 PIPAttributeResponse.ATTRIBUTECERTIFICATE_NS] 428 request.subject[Subject.ROLES_NS] = attributeCertificate.roles 432 request.subject[Subject.ROLES_NS] = attributeResponse[ 433 Subject.ROLES_NS] 429 434 430 435 # Match the subject's attributes against the target -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/credentialwallet.py
r5181 r5182 419 419 for attrName in CredentialWallet._protectedAttrs]) 420 420 421 def __setstate__(self ):421 def __setstate__(self, attrDict): 422 422 '''Enable pickling for use with beaker.session''' 423 pass 423 for attr, val in attrDict.items(): 424 setattr(self, attr, val) 424 425 425 426 def parseConfig(self, cfg, prefix='', section='DEFAULT'): -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/sessionmanager.py
r5063 r5182 108 108 excepMap = { 109 109 'SessionNotFound': SessionNotFound, 110 'UserSession X509CertNotBeforeTimeError': SessionCertTimeError,110 'UserSessionNotBeforeTimeError': SessionCertTimeError, 111 111 'UserSessionExpired': SessionExpired, 112 112 'InvalidUserSession': InvalidSession -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/__init__.py
r5181 r5182 17 17 from M2Crypto import X509, BIO, RSA 18 18 import base64 19 20 # Conditional import as this is required for the encryption21 # handler22 try:23 # For shared key encryption24 from Crypto.Cipher import AES, DES325 except:26 from warnings import warn27 warn('Crypto.Cipher not available: EncryptionHandler disabled!',28 RuntimeWarning)29 class AES:30 MODE_ECB = None31 MODE_CBC = None32 33 class DES3:34 MODE_CBC = None35 19 36 20 import os -
TI12-security/trunk/python/ndg.security.common/setup.py
r4840 r5182 27 27 'ZSI', 28 28 '4Suite-XML', 29 'pycrypto',30 29 'M2Crypto' 31 30 ] -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/sessionmanager.py
r4900 r5182 22 22 # Time module for use with cookie expiry 23 23 from time import strftime 24 from datetime import datetime 24 from datetime import datetime, timedelta 25 25 26 26 # For parsing of properties file … … 31 31 import cElementTree as ElementTree 32 32 33 # Session Manager URI in cookie34 from Crypto.Cipher import AES35 36 33 # Credential Wallet 37 34 from ndg.security.common.credentialwallet import CredentialWallet, \ … … 71 68 """Raise when session's X.509 cert. has expired""" 72 69 73 class UserSession X509CertNotBeforeTimeError(UserSessionError):70 class UserSessionNotBeforeTimeError(UserSessionError): 74 71 """Raise when session's X.509 cert. not before time is before the current 75 72 system time""" … … 82 79 sessIdLen = 32 83 80 84 def __init__(self, **credentialWalletKeys): 85 """Initialise UserSession with keywords to CredentialWallet""" 81 def __init__(self, lifetime=28800, **credentialWalletKeys): 82 """Initialise UserSession with keywords to CredentialWallet 83 84 @type lifetime: int / float 85 @param lifetime: lifetime of session in seconds before it is scheduled 86 to time out and becomes invalid - see isValid() 87 """ 86 88 87 89 log.debug("UserSession.__init__ ...") 90 91 # Set time stamp to enable auditing to remove stale sessions. The 92 # user's credential wallet may contain a user certificate which may 93 # also be checked for expiry using CredentialWallet.isValid() but there 94 # may be no user certificate set. This code is an extra provision to 95 # to allow for this 96 self.__dtCreationTime = datetime.utcnow() 97 self.lifetime = lifetime 88 98 89 99 # Each User Session has one or more browser sessions associated with … … 95 105 log.info("Created a session with ID = %s" % self.__sessIdList[-1]) 96 106 107 def __getDtCreationTime(self): 108 return self.__dtCreationTime 109 110 dtCreationTime = property(fget=__getDtCreationTime, 111 doc="time at which the session was created as a " 112 "datetime.datetime instance") 113 114 def __setLifetime(self, lifetime): 115 if not isinstance(lifetime, (int, float)): 116 raise TypeError("Expecting int or float type for session lifetime " 117 "attribute; got %s instead" % type(lifetime)) 118 self.__lifetime = lifetime 119 120 def __getLifetime(self): 121 return self.__lifetime 122 123 lifetime = property(fget=__getLifetime, 124 fset=__setLifetime, 125 doc="lifetime of session in seconds before it is " 126 "scheduled to time out and becomes invalid") 127 128 def isValidTime(self, raiseExcep=False): 129 """Return True if the session is within it's validity time 130 131 @type raiseExcep: bool 132 @param raiseExcep: set to True to raise an exception if the session 133 has an invalid time 134 135 @raise UserSessionNotBeforeTimeError: current time is BEFORE the 136 creation time for this session i/e/ something is seriously wrong 137 @raise UserSessionExpired: this session has expired 138 """ 139 dtNow = datetime.utcnow() 140 dtNotAfter = self.dtCreationTime + timedelta(seconds=self.lifetime) 141 142 if raiseExcep: 143 if dtNow < self.__dtCreationTime: 144 raise UserSessionNotBeforeTimeError("Current time %s is " 145 "before session's not before time of %s" % 146 (dtNow.strftime("%d/%m/%Y %H:%M:%S"), 147 self.__dtCreationTime.strftime("%d/%m/%Y %H:%M:%S"))) 148 149 if dtNow > dtNotAfter: 150 raise UserSessionExpired("Current time %s is after session's " 151 "expiry time of %s" % 152 (dtNow.strftime("%d/%m/%Y %H:%M:%S"), 153 self.__dtCreationTime.strftime("%d/%m/%Y %H:%M:%S"))) 154 else: 155 return dtNow > self.dtCreationTime and dtNow < dtNotAfter 156 157 def isValid(self, raiseExcep=False): 158 """Return True if this session is valid. This checks the 159 validity time calling isValidTime and the validity of the Credential 160 Wallet held 161 162 @type raiseExcep: bool 163 @param raiseExcep: set to True to raise an exception if the session 164 is invalid 165 @raise UserSessionNotBeforeTime: current time is before session 166 creation time 167 @raise UserSessionExpired: session has expired 168 @raise X509CertInvalidNotBeforeTime: X.509 certificate held by the 169 CredentialWallet is set after the current time 170 @raise X509CertExpired: X.509 certificate held by the 171 CredentialWallet has expired 172 """ 173 if not self.isValidTime(raiseExcep=raiseExcep): 174 return False 175 176 if not self.credentialWallet.isValid(raiseExcep=raiseExcep): 177 return False 178 179 return True 180 181 97 182 def __getCredentialWallet(self): 98 183 """Get Credential Wallet instance""" … … 128 213 sessID = base64.urlsafe_b64encode(os.urandom(UserSession.sessIdLen)) 129 214 self.__sessIdList.append(sessID) 130 131 @staticmethod132 def encodeTxt(txt, encrKey=None):133 """Encode Session Manager URI to allow inclusion in a web browser134 session cookie135 136 The address is optionally encrypted and then base 64 encoded use a137 URL safe encoding138 139 @type encrKey: string140 @param encrKey: 16 char encryption key used to encrypt the URI. If141 omitted or set None, the URI is not encrypted but merely base 64142 encoded"""143 144 if encrKey is not None:145 # Text length must be a multiple of 16 for AES encryption146 try:147 mod = len(txt) % 16148 nPad = mod and 16 - mod or 0149 150 # Add padding151 paddedURI = txt + ''.join(' '*nPad)152 except Exception, e:153 raise UserSessionError("Padding text for encryption: %s" % e)154 155 # Encrypt156 try:157 txt = AES.new(encrKey, AES.MODE_ECB).encrypt(paddedURI)158 159 except Exception, e:160 raise UserSessionError("Encrypting text: %s" % e)161 162 try:163 return base64.urlsafe_b64encode(txt)164 165 except Exception, e:166 raise UserSessionError("Encoding Session Manager URI: %s" % e)167 168 @staticmethod169 def decodeTxt(txt, encrKey=None):170 """Decode the URI from cookie set by another Session Manager. This171 is required when reading a session cookie to find out which172 Session Manager holds the client's session173 174 @type txt: string175 @param txt: base 64 encoded encrypted text176 177 @type encrKey: string178 @param encrKey: 16 char encryption key used to encrypt the URI. If179 omitted or set None, the URI is assumed to be unencrypted"""180 181 try:182 # Convert if unicode type - unicode causes TypeError with183 # base64.urlsafe_b64decode184 if isinstance(txt, unicode):185 txt = str(txt)186 187 # Decode from base 64188 b64DecodedEncrTxt = base64.urlsafe_b64decode(txt)189 190 except Exception, e:191 raise SessionManagerError("Decoding text: %s" % e)192 if encrKey is not None:193 try:194 aes = AES.new(encrKey, AES.MODE_ECB)195 196 # Decrypt and strip trailing spaces197 return aes.decrypt(b64DecodedEncrTxt).strip()198 199 except Exception, e:200 raise SessionManagerError("Decrypting Session Manager URI: %s" % e)201 else:202 return b64DecodedEncrTxt203 215 204 216 class SessionManagerError(_SessionException): … … 760 772 if createServerSess: 761 773 # Session Manager creates and manages user's session 762 userSess = self. _createUserSession(username,763 764 774 userSess = self.createUserSession(username, 775 passphrase, 776 userCreds) 765 777 sessID = userSess.latestSessID 766 778 else: … … 771 783 772 784 773 def _createUserSession(self, username, userPriKeyPwd=None, userCreds=None):785 def createUserSession(self, username, userPriKeyPwd=None, userCreds=None): 774 786 """Create a new user session from input user credentials 775 and return 787 and return it. This is an alternative to connect() useful in cases 788 where a session needs to be created for an existing authenticated user 776 789 777 790 @type username: basestring … … 789 802 790 803 @raise SessionManagerError: session ID added already exists in session 791 list""" 792 793 log.debug("Calling SessionManager._createUserSession ...") 804 list 805 @raise ndg.security.common.X509.X509CertError: from parsing X.509 cert 806 set in the userCreds keyword""" 807 808 log.debug("Calling SessionManager.createUserSession ...") 794 809 795 810 # Check for an existing session for the same user … … 841 856 userSess = UserSession(**credentialWalletProp) 842 857 except Exception, e: 843 log.error(" Error occurred whilst creating User Session: %s"%e)858 log.error("Creating User Session: %s" % e) 844 859 raise 845 860 … … 891 906 @raise UserSessionExpired: existing session has expired 892 907 @raise InvalidUserSession: user credential wallet is invalid 893 @raise UserSession X509CertNotBeforeTimeError: """908 @raise UserSessionNotBeforeTimeError: """ 894 909 895 910 log.debug("Calling SessionManager._connect2UserSession ...") … … 959 974 # Check that the Credentials held in the wallet are still valid 960 975 try: 961 userSess. credentialWallet.isValid(raiseExcep=True)976 userSess.isValid(raiseExcep=True) 962 977 return userSess 963 978 964 except X509CertInvalidNotBeforeTime, e:979 except (UserSessionNotBeforeTime, X509CertInvalidNotBeforeTime), e: 965 980 # ! Delete user session since it's user certificate is invalid 966 981 self.deleteUserSession(userSess=userSess) 967 raise UserSessionX509CertNotBeforeTimeError( 968 "User session is invalid: %s" % e) 969 970 except X509CertExpired, e: 982 raise 983 984 except (UserSessionExpired, X509CertExpired), e: 971 985 # ! Delete user session since it's user certificate is invalid 972 986 self.deleteUserSession(userSess=userSess) 973 raise UserSessionExpired("User session is invalid: %s" % e)987 raise 974 988 975 989 except Exception, e: … … 1054 1068 (userDN, userSess.sessIdList)) 1055 1069 1056 1070 def auditSessions(self): 1071 """Remove invalid sessions i.e. ones which have expired""" 1072 1073 log.debug("Auditing user sessions ...") 1074 for session in self.__sessDict.values(): 1075 if not session.isValid(): 1076 self.deleteUserSession(userSess=session) 1077 1057 1078 def getAttCert(self, 1058 1079 username=None, -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/utils/sessionmanagerclient.py
r5181 r5182 33 33 # Session Manager server side exceptions ... 34 34 from ndg.security.server.sessionmanager import SessionManagerError, \ 35 UserSessionExpired, UserSession X509CertNotBeforeTimeError, \35 UserSessionExpired, UserSessionNotBeforeTimeError, \ 36 36 InvalidUserSession, CredentialWalletAttributeRequestDenied 37 37 … … 60 60 # enable easier exception handling for a WSGISessionManagerClient caller. 61 61 # See SessionNotFound.__doc__ for more details of reasoning 62 SessionNotBeforeTimeError = (UserSession X509CertNotBeforeTimeError,62 SessionNotBeforeTimeError = (UserSessionNotBeforeTimeError, 63 63 SessionCertTimeError) 64 64 -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/config/attributeauthority/sitea/siteAMapConfig.xml
r4863 r5182 15 15 <loginServerDN>/O=SiteD/OU=D/CN=ndg.sitec.blah</loginServerDN> 16 16 <loginRequestServerDN>/O=SiteD/OU=D/CN=ndg.sitec.blah</loginRequestServerDN> 17 <role remote=" StaffMember" local="staff"/>17 <role remote="urn:SiteC:ndg:StaffMember" local="urn:siteA:security:authz:1.0:attr:staff"/> 18 18 </trusted> 19 19 <trusted name="Site D"> … … 24 24 <loginServerDN>/O=SiteD/OU=D/CN=ndg.sited.blah</loginServerDN> 25 25 <loginRequestServerDN>/O=SiteD/OU=D/CN=ndg.sited.blah</loginRequestServerDN> 26 <role remote=" academic" local="postgrad"/>27 <role remote=" student" local="SiteDStudent"/>28 <role remote=" eoGroup" local="atsr-archive"/>26 <role remote="urn:site-d:security:roles:academic" local="urn:siteA:security:authz:1.0:attr:postgrad"/> 27 <role remote="urn:site-d:security:roles:student" local="urn:siteA:security:authz:1.0:attr:SiteDStudent"/> 28 <role remote="urn:site-d:security:roles:eoGroup" local="urn:siteA:security:authz:1.0:attr:atsr-archive"/> 29 29 </trusted> 30 30 </AAmap> -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/config/attributeauthority/sitea/siteAUserRoles.py
r4840 r5182 27 27 28 28 def getRoles(self, userId): 29 return ['staff', 'postdoc', 'undergrad', 'coapec'] 29 return [ 30 'urn:siteA:security:authz:1.0:attr:postdoc', 31 'urn:siteA:security:authz:1.0:attr:staff', 32 'urn:siteA:security:authz:1.0:attr:undergrad', 33 'urn:siteA:security:authz:1.0:attr:coapec' 34 ] -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/config/attributeauthority/siteb/siteBMapConfig.xml
r4718 r5182 15 15 <loginServerDN>/C=UK/ST=Oxfordshire/O=STFC/OU=BADC/CN=localhost</loginServerDN> 16 16 <loginRequestServerDN>/C=UK/ST=Oxfordshire/O=STFC/OU=BADC/CN=localhost</loginRequestServerDN> 17 <role remote="postdoc" local="researcher"/>17 <role remote="urn:siteA:security:authz:1.0:attr:postdoc" local="urn:site-b:security:1.0:roles:researcher"/> 18 18 </trusted> 19 19 </AAmap> -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/policy.xml
r5168 r5182 6 6 <URIPattern>/test_securedURI</URIPattern> 7 7 <Attributes> 8 <Attribute> authz</Attribute>8 <Attribute>urn:siteA:security:authz:1.0:attr:staff</Attribute> 9 9 </Attributes> 10 10 <AttributeAuthority> -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/integration/authz/securedapp.ini
r5181 r5182 50 50 pip.sslCACertFilePathList= 51 51 52 # List of CA certificates used to verify the signatures of 53 # Attribute Certificates retrieved 54 pip.caCertFilePathList=%(testConfigDir)s/ca/ndg-test-ca.crt 55 52 56 # 53 57 # WS-Security Settings for call to Session Manager
Note: See TracChangeset
for help on using the changeset viewer.