diff options
Diffstat (limited to 'keystone/api/_shared/EC2_S3_Resource.py')
-rw-r--r-- | keystone/api/_shared/EC2_S3_Resource.py | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/keystone/api/_shared/EC2_S3_Resource.py b/keystone/api/_shared/EC2_S3_Resource.py index 021cf4ad5..803254816 100644 --- a/keystone/api/_shared/EC2_S3_Resource.py +++ b/keystone/api/_shared/EC2_S3_Resource.py @@ -12,15 +12,20 @@ # Common base resource for EC2 and S3 Authentication +import datetime + from oslo_serialization import jsonutils +from oslo_utils import timeutils from werkzeug import exceptions from keystone.common import provider_api from keystone.common import utils +import keystone.conf from keystone import exception as ks_exceptions from keystone.i18n import _ from keystone.server import flask as ks_flask +CONF = keystone.conf.CONF PROVIDERS = provider_api.ProviderAPIs CRED_TYPE_EC2 = 'ec2' @@ -36,6 +41,31 @@ class ResourceBase(ks_flask.ResourceBase): # the ABC module. raise NotImplementedError() + @staticmethod + def _check_timestamp(credentials): + timestamp = ( + # AWS Signature v1/v2 + credentials.get('params', {}).get('Timestamp') or + # AWS Signature v4 + credentials.get('headers', {}).get('X-Amz-Date') or + credentials.get('params', {}).get('X-Amz-Date') + ) + if not timestamp: + # If the signed payload doesn't include a timestamp then the signer + # must have intentionally left it off + return + try: + timestamp = timeutils.parse_isotime(timestamp) + timestamp = timeutils.normalize_time(timestamp) + except Exception as e: + raise ks_exceptions.Unauthorized( + _('Credential timestamp is invalid: %s') % e) + auth_ttl = datetime.timedelta(minutes=CONF.credential.auth_ttl) + current_time = timeutils.normalize_time(timeutils.utcnow()) + if current_time > timestamp + auth_ttl: + raise ks_exceptions.Unauthorized( + _('Credential is expired')) + def handle_authenticate(self): # TODO(morgan): convert this dirty check to JSON Schema validation # this mirrors the previous behavior of the webob system where an @@ -101,6 +131,7 @@ class ResourceBase(ks_flask.ResourceBase): except AssertionError as e: raise ks_exceptions.Unauthorized from e + self._check_timestamp(credentials) roles = PROVIDERS.assignment_api.get_roles_for_user_and_project( user_ref['id'], project_ref['id']) |