From 3ead8ddf75dce56594d502513eb15b2a4b87587c Mon Sep 17 00:00:00 2001 From: Wim Van de Meerssche Date: Fri, 5 Aug 2016 16:30:24 +0200 Subject: [PATCH 1/5] added timezone to datetime.datetime.strptime result --- src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py b/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py index fafd42f..dfb6580 100644 --- a/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py +++ b/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py @@ -155,7 +155,7 @@ def create_slice(self, credentials, fields, options): fields['SLICE_EXPIRED'] = False if 'SLICE_EXPIRATION' in fields: - expDate = datetime.datetime.strptime(fields['SLICE_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ') + expDate = datetime.datetime.strptime(fields['SLICE_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.utc) if expDate > self.CRED_EXPIRY: fields['SLICE_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY.replace(tzinfo=pytz.utc)) else: From e2e823764a348f425d56ddb89ecd2fd48a722145 Mon Sep 17 00:00:00 2001 From: Wim Van de Meerssche Date: Fri, 5 Aug 2016 16:34:44 +0200 Subject: [PATCH 2/5] added timezone to additional datetime.datetime.strptime results --- .../osliceauthorityrm/osliceauthorityresourcemanager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py b/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py index dfb6580..a6c1ff9 100644 --- a/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py +++ b/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py @@ -269,7 +269,7 @@ def create_project(self, credentials, fields, options): self._validate_project_urn(p_urn) if 'PROJECT_EXPIRATION' in fields: - expDate = datetime.datetime.strptime(fields['PROJECT_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ') + expDate = datetime.datetime.strptime(fields['PROJECT_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.utc) if expDate > self.CRED_EXPIRY: fields['PROJECT_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY.replace(tzinfo=pytz.utc)) else: @@ -654,7 +654,7 @@ def _validate_slice_urn(self, slice_urn): if len(lookup_results) > 0: # Slice exists, Let's check if it has been expired - expDate = datetime.datetime.strptime(lookup_results[0]['SLICE_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ') + expDate = datetime.datetime.strptime(lookup_results[0]['SLICE_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.utc) now = datetime.datetime.utcnow() if now < expDate: raise self.gfed_ex.GFedv2DuplicateError("A slice with specified name already exists under the following URN:"+ str(slice_urn)) @@ -670,7 +670,7 @@ def _validate_project_urn(self, project_urn): if len(lookup_results) > 0: # Slice exists, Let's check if it has been expired - expDate = datetime.datetime.strptime(lookup_results[0]['PROJECT_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ') + expDate = datetime.datetime.strptime(lookup_results[0]['PROJECT_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.utc) now = datetime.datetime.utcnow() if now < expDate: raise self.gfed_ex.GFedv2DuplicateError("A project with specified name already exists under the following URN:"+ str(project_urn)) From 5db773071911f017ab8fa8bbab6832f4696e9217 Mon Sep 17 00:00:00 2001 From: Wim Van de Meerssche Date: Mon, 8 Aug 2016 13:32:42 +0200 Subject: [PATCH 3/5] various fixed related to timezones. C-BAS will now generate an exception rather than make timezone errors --- .../osliceauthorityresourcemanager.py | 20 ++++++--- .../geni_trust/ext/sfa/trust/credential.py | 42 +++++++++++++++---- src/vendor/geni_trust/ext/sfa/util/sfatime.py | 3 ++ .../geniv3rpc/ext/sfa/trust/credential.py | 40 +++++++++++++++--- src/vendor/geniv3rpc/ext/sfa/util/sfatime.py | 3 ++ 5 files changed, 90 insertions(+), 18 deletions(-) diff --git a/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py b/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py index a6c1ff9..3c88f39 100644 --- a/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py +++ b/src/plugins/osliceauthorityrm/osliceauthorityresourcemanager.py @@ -17,7 +17,7 @@ class OSliceAuthorityResourceManager(object): SA_CERT_FILE = 'sa-cert.pem' SA_KEY_FILE = 'sa-key.pem' - CRED_EXPIRY = datetime.datetime.utcnow() + datetime.timedelta(days=600) + CRED_EXPIRY = (datetime.datetime.utcnow() + datetime.timedelta(days=600)).replace(tzinfo=pytz.utc) AUTHORITY_NAME = 'sa' #: The short-name for this authority SUPPORTED_SERVICES = ['SLICE', 'SLICE_MEMBER', 'SLIVER_INFO', 'PROJECT', 'PROJECT_MEMBER'] #: The objects supported by this authority @@ -154,12 +154,14 @@ def create_slice(self, credentials, fields, options): fields['SLICE_CREATION'] = pyrfc3339.generate(datetime.datetime.utcnow().replace(tzinfo=pytz.utc)) fields['SLICE_EXPIRED'] = False + assert self.CRED_EXPIRY.tzinfo is not None + assert self.CRED_EXPIRY.utcoffset() is not None if 'SLICE_EXPIRATION' in fields: expDate = datetime.datetime.strptime(fields['SLICE_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.utc) if expDate > self.CRED_EXPIRY: - fields['SLICE_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY.replace(tzinfo=pytz.utc)) + fields['SLICE_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY) else: - fields['SLICE_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY.replace(tzinfo=pytz.utc)) + fields['SLICE_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY) # Generating Slice certificate s_cert, s_pu, s_pr = geniutil.create_certificate(slice_urn, self._sa_pr, self._sa_c, life_days=3650) @@ -268,12 +270,14 @@ def create_project(self, credentials, fields, options): # Verify the uniqueness of project name self._validate_project_urn(p_urn) + assert self.CRED_EXPIRY.tzinfo is not None + assert self.CRED_EXPIRY.utcoffset() is not None if 'PROJECT_EXPIRATION' in fields: expDate = datetime.datetime.strptime(fields['PROJECT_EXPIRATION'], '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=pytz.utc) if expDate > self.CRED_EXPIRY: - fields['PROJECT_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY.replace(tzinfo=pytz.utc)) + fields['PROJECT_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY) else: - fields['PROJECT_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY.replace(tzinfo=pytz.utc)) + fields['PROJECT_EXPIRATION'] = pyrfc3339.generate(self.CRED_EXPIRY) geniutil = pm.getService('geniutil') # Generating Project Certificate @@ -410,6 +414,8 @@ def modify_slice_membership(self, urn, credentials, options): if user_urn_from_cert != slice_lead and user_urn_from_cert != target_urn_from_cred: raise self.gfed_ex.GFedv2ArgumentError("Only slice LEAD or ROOT can modify lead membership "+ str(urn)) + assert self.CRED_EXPIRY.tzinfo is not None + assert self.CRED_EXPIRY.utcoffset() is not None # Create slice cred for new member if option_key == 'members_to_add': member_dict['SLICE_CREDENTIALS'] = geniutil.create_credential_ex(owner_cert=member_cert, target_cert=slice_cert, @@ -472,6 +478,8 @@ def _update_cred_expiry(self, cred, obj_cert, expiry): :param expiry: :return: """ + assert expiry.tzinfo is not None + assert expiry.utcoffset() is not None geniutil = pm.getService('geniutil') owner_cert = geniutil.extract_owner_certificate(cred) priv, _ = geniutil.get_privileges_and_target_urn(cred) @@ -575,6 +583,8 @@ def update_slice_credentials_for_member(self, member_urn, credentials, options): slice_creds_old = membership['SLICE_CREDENTIALS'] slice_prvlg, slice_urn = geniutil.get_privileges_and_target_urn(slice_creds_old) slice_exp = geniutil.get_expiration(slice_creds_old) + assert slice_exp.tzinfo is not None + assert slice_exp.utcoffset() is not None slice_creds_new = geniutil.create_credential_ex(owner_cert=member_cert, target_cert=slice_cert, issuer_key=self._sa_pr, issuer_cert=self._sa_c, privileges_list=slice_prvlg, expiration=slice_exp) diff --git a/src/vendor/geni_trust/ext/sfa/trust/credential.py b/src/vendor/geni_trust/ext/sfa/trust/credential.py index 2a22994..36a221f 100644 --- a/src/vendor/geni_trust/ext/sfa/trust/credential.py +++ b/src/vendor/geni_trust/ext/sfa/trust/credential.py @@ -32,6 +32,8 @@ from StringIO import StringIO from tempfile import mkstemp from xml.dom.minidom import Document, parseString +import pytz +import pyrfc3339 HAVELXML = False try: @@ -310,7 +312,7 @@ def translate_legacy(self, str): self.gidObject = legacy.get_gid_object() lifetime = legacy.get_lifetime() if not lifetime: - self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + self.set_expiration((datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)).replace(tzinfo=pytz.utc)) else: self.set_expiration(int(lifetime)) self.lifeTime = legacy.get_lifetime() @@ -372,13 +374,28 @@ def get_gid_object(self): # def set_expiration(self, expiration): if isinstance(expiration, (int, float)): - self.expiration = datetime.datetime.fromtimestamp(expiration) + self.expiration = datetime.datetime.utcfromtimestamp(expiration).replace(tzinfo=pytz.utc) elif isinstance (expiration, datetime.datetime): self.expiration = expiration + if self.expiration.tzinfo is None or self.expiration.tzinfo.utcoffset(self.expiration) is None: + raise ValueError('set_expiration called with expire time missing timezone info') elif isinstance (expiration, StringTypes): - self.expiration = utcparse (expiration) + self.expiration = dateutil.parser.parse(expiration) else: logger.error ("unexpected input type in Credential.set_expiration") + raise ValueError('unexpected input type in Credential.set_expiration', expiration) + + if not isinstance (self.expiration, datetime.datetime): + logger.error('credential.py bug: set_expiration finished with credential is not datetime. It is {0}'.format(self.expiration.__class__)) + raise RuntimeError('credential.py bug: set_expiration finished with credential that is not datetime') + + if self.expiration.tzinfo is None or self.expiration.tzinfo.utcoffset(self.expiration) is None: + logger.error('credential.py bug: set_expiration finished with credential that has expire time missing timezone info') + raise RuntimeError('credential.py bug: set_expiration finished with credential that has expire time missing timezone info') + + if t.utcoffset() is not None: + #force timezone to UTC without changing time + t = t.astimezone(pytz.utc) ## @@ -469,10 +486,21 @@ def encode(self): append_sub(doc, cred, "target_gid", self.gidObject.save_to_string()) append_sub(doc, cred, "target_urn", self.gidObject.get_urn()) append_sub(doc, cred, "uuid", "") + + #was: if not self.expiration: + #was: self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) if not self.expiration: - self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) - self.expiration = self.expiration.replace(microsecond=0) - append_sub(doc, cred, "expires", self.expiration.isoformat()) + logger.error('credential.py usage bug: credential was created without expire') + raise RuntimeError('credential.py usage bug: credential was created without expire') + if (not isinstance (self.expiration, datetime.datetime)) or self.expiration.tzinfo is None or self.expiration.tzinfo.utcoffset(self.expiration) is None: + #credential.py bug because set_expiration should have handled this + logger.error('credential.py bug: credential was has expire time missing timezone info') + raise RuntimeError('credential.py bug: credential was has expire time missing timezone info') + else: + self.expiration = self.expiration.replace(microsecond=0) + append_sub(doc, cred, "expires", pyrfc3339.generate(self.expiration)) + #was: append_sub(doc, cred, "expires", self.expiration.isoformat()) + privileges = doc.createElement("privileges") cred.appendChild(privileges) @@ -709,7 +737,7 @@ def decode(self): cred = creds[0] self.set_refid(cred.getAttribute("xml:id")) - self.set_expiration(utcparse(getTextNode(cred, "expires"))) + self.set_expiration(getTextNode(cred, "expires")) self.gidCaller = GID(string=getTextNode(cred, "owner_gid")) self.gidObject = GID(string=getTextNode(cred, "target_gid")) diff --git a/src/vendor/geni_trust/ext/sfa/util/sfatime.py b/src/vendor/geni_trust/ext/sfa/util/sfatime.py index 15de02f..29e6502 100644 --- a/src/vendor/geni_trust/ext/sfa/util/sfatime.py +++ b/src/vendor/geni_trust/ext/sfa/util/sfatime.py @@ -50,6 +50,9 @@ def utcparse(input): t = dateutil.parser.parse(input) if t.utcoffset() is not None: t = t.utcoffset() + t.replace(tzinfo=None) + # the above line is wrong: you need to substract the utcoffset, not add it! + # a better way is: t = t.astimezone(pytz.utc) #only works if not naive + raise RuntimeException('unfixed bug in code triggered') return t elif isinstance (input, (int,float,long)): return datetime.datetime.fromtimestamp(input) diff --git a/src/vendor/geniv3rpc/ext/sfa/trust/credential.py b/src/vendor/geniv3rpc/ext/sfa/trust/credential.py index 3b3cafc..756e9ef 100644 --- a/src/vendor/geniv3rpc/ext/sfa/trust/credential.py +++ b/src/vendor/geniv3rpc/ext/sfa/trust/credential.py @@ -32,6 +32,8 @@ from StringIO import StringIO from tempfile import mkstemp from xml.dom.minidom import Document, parseString +import pytz +import pyrfc3339 HAVELXML = False try: @@ -310,7 +312,7 @@ def translate_legacy(self, str): self.gidObject = legacy.get_gid_object() lifetime = legacy.get_lifetime() if not lifetime: - self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + self.set_expiration((datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)).replace(tzinfo=pytz.utc)) else: self.set_expiration(int(lifetime)) self.lifeTime = legacy.get_lifetime() @@ -372,13 +374,28 @@ def get_gid_object(self): # def set_expiration(self, expiration): if isinstance(expiration, (int, float)): - self.expiration = datetime.datetime.fromtimestamp(expiration) + self.expiration = datetime.datetime.utcfromtimestamp(expiration).replace(tzinfo=pytz.utc) elif isinstance (expiration, datetime.datetime): self.expiration = expiration + if self.expiration.tzinfo is None or self.expiration.tzinfo.utcoffset(self.expiration) is None: + raise ValueError('set_expiration called with expire time missing timezone info') elif isinstance (expiration, StringTypes): - self.expiration = utcparse (expiration) + self.expiration = dateutil.parser.parse(expiration) else: logger.error ("unexpected input type in Credential.set_expiration") + raise ValueError('unexpected input type in Credential.set_expiration', expiration) + + if not isinstance (self.expiration, datetime.datetime): + logger.error('credential.py bug: set_expiration finished with credential is not datetime. It is {0}'.format(self.expiration.__class__)) + raise RuntimeError('credential.py bug: set_expiration finished with credential that is not datetime') + + if self.expiration.tzinfo is None or self.expiration.tzinfo.utcoffset(self.expiration) is None: + logger.error('credential.py bug: set_expiration finished with credential that has expire time missing timezone info') + raise RuntimeError('credential.py bug: set_expiration finished with credential that has expire time missing timezone info') + + if t.utcoffset() is not None: + #force timezone to UTC without changing time + t = t.astimezone(pytz.utc) ## @@ -469,10 +486,21 @@ def encode(self): append_sub(doc, cred, "target_gid", self.gidObject.save_to_string()) append_sub(doc, cred, "target_urn", self.gidObject.get_urn()) append_sub(doc, cred, "uuid", "") + + #was: if not self.expiration: + #was: self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) if not self.expiration: - self.set_expiration(datetime.datetime.utcnow() + datetime.timedelta(seconds=DEFAULT_CREDENTIAL_LIFETIME)) + logger.error('credential.py usage bug: credential was created without expire') + raise RuntimeError('credential.py usage bug: credential was created without expire') + if (not isinstance (self.expiration, datetime.datetime)) or self.expiration.tzinfo is None or self.expiration.tzinfo.utcoffset(self.expiration) is None: + #credential.py bug because set_expiration should have handled this + logger.error('credential.py bug: credential was has expire time missing timezone info') + raise RuntimeError('credential.py bug: credential was has expire time missing timezone info') + else: self.expiration = self.expiration.replace(microsecond=0) - append_sub(doc, cred, "expires", self.expiration.isoformat()) + append_sub(doc, cred, "expires", pyrfc3339.generate(self.expiration)) + #was: append_sub(doc, cred, "expires", self.expiration.isoformat()) + privileges = doc.createElement("privileges") cred.appendChild(privileges) @@ -707,7 +735,7 @@ def decode(self): cred = creds[0] self.set_refid(cred.getAttribute("xml:id")) - self.set_expiration(utcparse(getTextNode(cred, "expires"))) + self.set_expiration(getTextNode(cred, "expires")) self.gidCaller = GID(string=getTextNode(cred, "owner_gid")) self.gidObject = GID(string=getTextNode(cred, "target_gid")) diff --git a/src/vendor/geniv3rpc/ext/sfa/util/sfatime.py b/src/vendor/geniv3rpc/ext/sfa/util/sfatime.py index 15de02f..29e6502 100644 --- a/src/vendor/geniv3rpc/ext/sfa/util/sfatime.py +++ b/src/vendor/geniv3rpc/ext/sfa/util/sfatime.py @@ -50,6 +50,9 @@ def utcparse(input): t = dateutil.parser.parse(input) if t.utcoffset() is not None: t = t.utcoffset() + t.replace(tzinfo=None) + # the above line is wrong: you need to substract the utcoffset, not add it! + # a better way is: t = t.astimezone(pytz.utc) #only works if not naive + raise RuntimeException('unfixed bug in code triggered') return t elif isinstance (input, (int,float,long)): return datetime.datetime.fromtimestamp(input) From f58b379f686fa02c4f959748bb38f3c66401c0d0 Mon Sep 17 00:00:00 2001 From: Arthur Garnier Date: Mon, 8 Aug 2016 16:11:56 +0200 Subject: [PATCH 4/5] fixes to credential expire fixes --- requirements.txt | 2 +- src/plugins/fedtools/delegatetools.py | 7 ++++++- src/vendor/geni_trust/ext/sfa/trust/credential.py | 15 ++++++++++++++- src/vendor/geniv3rpc/ext/sfa/trust/credential.py | 1 + 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 11d2c1b..8c7fbc6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ Werkzeug==0.9.4 argparse==1.2.1 blinker==1.3 cffi==0.8.1 -cryptography==0.2.2 +cryptography==0.6.1 flup==1.0.2 itsdangerous==0.23 jsonrpclib==0.1.3 diff --git a/src/plugins/fedtools/delegatetools.py b/src/plugins/fedtools/delegatetools.py index 84b5986..b262fa4 100644 --- a/src/plugins/fedtools/delegatetools.py +++ b/src/plugins/fedtools/delegatetools.py @@ -308,7 +308,12 @@ def check_if_authorized(self, credentials, owner_cert, method, type_, target_urn if not required_privileges or set(privileges+priv_from_cred).intersection(required_privileges): cred_accepted = True break +#This would be cleaner, but I don't know what the correct way to import this is +# except Credential.CredentialExpireTimezoneError as e: +# raise GFedv2AuthorizationError("Your credentials has an invalid expire date (missing timezone info)") except Exception as e: + if (e.args[0].startswith('Invalid expire value in credential, missing timezone info')): + raise GFedv2AuthorizationError("Your credentials has an invalid expire date (missing timezone info)") import traceback traceback.print_exc() #print e @@ -1034,4 +1039,4 @@ def check_list_of_dictionaries(value): raise Exception for dictionary in value: if not isinstance(dictionary, dict): - raise Exception \ No newline at end of file + raise Exception diff --git a/src/vendor/geni_trust/ext/sfa/trust/credential.py b/src/vendor/geni_trust/ext/sfa/trust/credential.py index 36a221f..c9bfe29 100644 --- a/src/vendor/geni_trust/ext/sfa/trust/credential.py +++ b/src/vendor/geni_trust/ext/sfa/trust/credential.py @@ -34,6 +34,7 @@ from xml.dom.minidom import Document, parseString import pytz import pyrfc3339 +import dateutil HAVELXML = False try: @@ -229,6 +230,11 @@ def filter_creds_by_caller(creds, caller_hrn_list): except: pass return caller_creds +class ExpireTimezoneError(ValueError): + pass +class CredentialExpireTimezoneError(ValueError): + pass + class Credential(object): ## @@ -369,6 +375,7 @@ def get_gid_object(self): self.decode() return self.gidObject + ## # Expiration: an absolute UTC time of expiration (as either an int or string or datetime) # @@ -381,6 +388,8 @@ def set_expiration(self, expiration): raise ValueError('set_expiration called with expire time missing timezone info') elif isinstance (expiration, StringTypes): self.expiration = dateutil.parser.parse(expiration) + if self.expiration.tzinfo is None or self.expiration.tzinfo.utcoffset(self.expiration) is None: + raise ExpireTimezoneError('set_expiration callled with String expire time missing timezone info: "{0}"'.format(expiration)) else: logger.error ("unexpected input type in Credential.set_expiration") raise ValueError('unexpected input type in Credential.set_expiration', expiration) @@ -708,6 +717,7 @@ def sign(self): self.decode() + ## # Retrieve the attributes of the credential from the XML. # This is automatically called by the various get_* methods of @@ -737,7 +747,10 @@ def decode(self): cred = creds[0] self.set_refid(cred.getAttribute("xml:id")) - self.set_expiration(getTextNode(cred, "expires")) + try: + self.set_expiration(getTextNode(cred, "expires")) + except ExpireTimezoneError as e: + raise CredentialExpireTimezoneError('Invalid expire value in credential, missing timezone info: "{0}"'.format(getTextNode(cred, "expires"))) self.gidCaller = GID(string=getTextNode(cred, "owner_gid")) self.gidObject = GID(string=getTextNode(cred, "target_gid")) diff --git a/src/vendor/geniv3rpc/ext/sfa/trust/credential.py b/src/vendor/geniv3rpc/ext/sfa/trust/credential.py index 756e9ef..8e2b350 100644 --- a/src/vendor/geniv3rpc/ext/sfa/trust/credential.py +++ b/src/vendor/geniv3rpc/ext/sfa/trust/credential.py @@ -34,6 +34,7 @@ from xml.dom.minidom import Document, parseString import pytz import pyrfc3339 +import dateutil HAVELXML = False try: From e37d5bcf473a54852bbd74dda50abd089583baf4 Mon Sep 17 00:00:00 2001 From: Wim Van de Meerssche Date: Mon, 8 Aug 2016 16:36:04 +0200 Subject: [PATCH 5/5] copied changes to other credential.py version --- src/vendor/geni_trust/ext/sfa/trust/credential.py | 2 -- src/vendor/geniv3rpc/ext/sfa/trust/credential.py | 10 ++++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vendor/geni_trust/ext/sfa/trust/credential.py b/src/vendor/geni_trust/ext/sfa/trust/credential.py index c9bfe29..9e20654 100644 --- a/src/vendor/geni_trust/ext/sfa/trust/credential.py +++ b/src/vendor/geni_trust/ext/sfa/trust/credential.py @@ -375,7 +375,6 @@ def get_gid_object(self): self.decode() return self.gidObject - ## # Expiration: an absolute UTC time of expiration (as either an int or string or datetime) # @@ -717,7 +716,6 @@ def sign(self): self.decode() - ## # Retrieve the attributes of the credential from the XML. # This is automatically called by the various get_* methods of diff --git a/src/vendor/geniv3rpc/ext/sfa/trust/credential.py b/src/vendor/geniv3rpc/ext/sfa/trust/credential.py index 8e2b350..a2d8e4a 100644 --- a/src/vendor/geniv3rpc/ext/sfa/trust/credential.py +++ b/src/vendor/geniv3rpc/ext/sfa/trust/credential.py @@ -230,6 +230,11 @@ def filter_creds_by_caller(creds, caller_hrn_list): except: pass return caller_creds +class ExpireTimezoneError(ValueError): + pass +class CredentialExpireTimezoneError(ValueError): + pass + class Credential(object): ## @@ -382,6 +387,8 @@ def set_expiration(self, expiration): raise ValueError('set_expiration called with expire time missing timezone info') elif isinstance (expiration, StringTypes): self.expiration = dateutil.parser.parse(expiration) + if self.expiration.tzinfo is None or self.expiration.tzinfo.utcoffset(self.expiration) is None: + raise ExpireTimezoneError('set_expiration callled with String expire time missing timezone info: "{0}"'.format(expiration)) else: logger.error ("unexpected input type in Credential.set_expiration") raise ValueError('unexpected input type in Credential.set_expiration', expiration) @@ -736,7 +743,10 @@ def decode(self): cred = creds[0] self.set_refid(cred.getAttribute("xml:id")) + try: self.set_expiration(getTextNode(cred, "expires")) + except ExpireTimezoneError as e: + raise CredentialExpireTimezoneError('Invalid expire value in credential, missing timezone info: "{0}"'.format(getTextNode(cred, "expires"))) self.gidCaller = GID(string=getTextNode(cred, "owner_gid")) self.gidObject = GID(string=getTextNode(cred, "target_gid"))