Fixes 918535: time not properly parsed in auth_token middleware

- replaced get_datetime() with expanded _convert_datetime()
  function that uses datutil parser to handle any date
  string.
- added tests
- fixes bug 918535
- also addresses bug 911197

Change-Id: I7f4e3c01b1b7466fd5f30889c7b28deae9fc9367
This commit is contained in:
Ziad Sawalha 2012-01-19 11:19:13 -06:00
parent fd65f4c0b4
commit 8c98285ad0
1 changed files with 9 additions and 24 deletions

View File

@ -97,6 +97,7 @@ HTTP_X_ROLES
"""
from datetime import datetime
from dateutil import parser
import eventlet
from eventlet import wsgi
import json
@ -121,20 +122,6 @@ EXPIRE_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f"
MAX_CACHE_TIME = 86400
def get_datetime(time_string):
""" Gets datetime object with microsecond accuracy from input string.
Handle strings which don't include microseconds
:param: time_string: datetime in %Y-%m-%dT%H:%M:%S.%f format (.%f optional)
"""
result = time_string.split(".", 1)
datetime_string = result[0]
microseconds = result[1] if len(result) > 1 else "0"
d1 = datetime.strptime(datetime_string, "%Y-%m-%dT%H:%M:%S")
ms = int(microseconds.ljust(6, '0')[:6])
return d1.replace(microsecond=ms)
class ValidationFailed(Exception):
pass
@ -333,9 +320,7 @@ class AuthProtocol(object):
@staticmethod
def _convert_date(date):
""" Convert datetime to unix timestamp for caching """
return time.mktime(datetime.strptime(
date[:date.rfind(':')].replace('-', ''), "%Y%m%dT%H:%M",
).timetuple())
return time.mktime(parser.parse(date).utctimetuple())
@staticmethod
def _protect_claims(token, claims):
@ -360,8 +345,8 @@ class AuthProtocol(object):
timeout=expires - time.time())
else:
# normal memcache client
expires = get_datetime(claims['expires'])
delta = expires - datetime.now()
expires = self._convert_date(claims['expires'])
delta = expires - time.time()
timeout = delta.seconds
if timeout > MAX_CACHE_TIME or not valid:
# Limit cache to one day (and cache bad tokens for a day)
@ -383,7 +368,7 @@ class AuthProtocol(object):
if expires > time.time():
claims = self._unprotect_claims(token, claims)
else:
if expires > datetime.now():
if expires > time.time():
claims = self._unprotect_claims(token, claims)
return (claims, expires, valid)
return None
@ -426,7 +411,7 @@ class AuthProtocol(object):
if not valid:
logger.debug("Claims not valid (according to cache)")
raise ValidationFailed()
if expires <= datetime.now():
if expires <= time.time():
logger.debug("Claims (token) expired (according to cache)")
raise TokenExpired()
return claims
@ -467,7 +452,7 @@ class AuthProtocol(object):
logger.debug("Caching that results were invalid")
self._cache_put(env, claims,
claims={'expires':
datetime.strftime(datetime.now(),
datetime.strftime(time.time(),
EXPIRE_TIME_FORMAT)},
valid=False)
# Keystone rejected claim
@ -507,8 +492,8 @@ class AuthProtocol(object):
token_info['access']['user']['id'],
token_info['access']['user']['name']))
expires = get_datetime(verified_claims['expires'])
if expires <= datetime.now():
expires = self._convert_date(verified_claims['expires'])
if expires <= time.time():
logger.debug("Claims (token) expired: %s" % str(expires))
# Cache it if there is a cache available (we also cached bad
# claims)