Add TokenNotFound exception

* raise TokenNotFound from token backends on get/delete when token doesn't exist

Change-Id: Ic9aba7911088c30c20fe62501a05d75232f2d8b9
This commit is contained in:
Brian Waldon 2012-02-09 09:53:03 -08:00
parent 1951c87de3
commit 2c18314e7c
11 changed files with 74 additions and 43 deletions

View File

@ -202,8 +202,11 @@ class Application(BaseApplication):
def assert_admin(self, context): def assert_admin(self, context):
if not context['is_admin']: if not context['is_admin']:
user_token_ref = self.token_api.get_token( try:
context=context, token_id=context['token_id']) user_token_ref = self.token_api.get_token(
context=context, token_id=context['token_id'])
except exception.TokenNotFound:
raise exception.Unauthorized()
creds = user_token_ref['metadata'].copy() creds = user_token_ref['metadata'].copy()
creds['user_id'] = user_token_ref['user'].get('id') creds['user_id'] = user_token_ref['user'].get('id')
creds['tenant_id'] = user_token_ref['tenant'].get('id') creds['tenant_id'] = user_token_ref['tenant'].get('id')

View File

@ -26,6 +26,7 @@ import webob.exc
from keystone import catalog from keystone import catalog
from keystone import config from keystone import config
from keystone import exception
from keystone import identity from keystone import identity
from keystone import policy from keystone import policy
from keystone import service from keystone import service
@ -252,8 +253,11 @@ class Ec2Controller(wsgi.Application):
:raises webob.exc.HTTPForbidden: when token is invalid :raises webob.exc.HTTPForbidden: when token is invalid
""" """
token_ref = self.token_api.get_token(context=context, try:
token_id=context['token_id']) token_ref = self.token_api.get_token(context=context,
token_id=context['token_id'])
except exception.TokenNotFound:
raise exception.Unauthorized()
token_user_id = token_ref['user'].get('id') token_user_id = token_ref['user'].get('id')
if not token_user_id == user_id: if not token_user_id == user_id:
raise webob.exc.HTTPForbidden() raise webob.exc.HTTPForbidden()

View File

@ -52,3 +52,7 @@ class NotFound(Error):
"""Could not find: %(target)s""" """Could not find: %(target)s"""
code = 404 code = 404
title = 'Not Found' title = 'Not Found'
class TokenNotFound(NotFound):
"""Could not find token: %(token_id)s"""

View File

@ -232,10 +232,10 @@ class TenantController(wsgi.Application):
Doesn't care about token scopedness. Doesn't care about token scopedness.
""" """
token_ref = self.token_api.get_token(context=context, try:
token_id=context['token_id']) token_ref = self.token_api.get_token(context=context,
token_id=context['token_id'])
if token_ref is None: except exception.NotFound:
raise exception.Unauthorized() raise exception.Unauthorized()
user_ref = token_ref['user'] user_ref = token_ref['user']
@ -250,17 +250,7 @@ class TenantController(wsgi.Application):
def get_tenant(self, context, tenant_id): def get_tenant(self, context, tenant_id):
# TODO(termie): this stuff should probably be moved to middleware # TODO(termie): this stuff should probably be moved to middleware
if not context['is_admin']: self.assert_admin(context)
user_token_ref = self.token_api.get_token(
context=context, token_id=context['token_id'])
creds = user_token_ref['metadata'].copy()
creds['user_id'] = user_token_ref['user'].get('id')
creds['tenant_id'] = user_token_ref['tenant'].get('id')
# Accept either is_admin or the admin role
assert self.policy_api.can_haz(context,
('is_admin:1', 'roles:admin'),
creds)
tenant = self.identity_api.get_tenant(context, tenant_id) tenant = self.identity_api.get_tenant(context, tenant_id)
if not tenant: if not tenant:
return webob.exc.HTTPNotFound() return webob.exc.HTTPNotFound()

View File

@ -1,8 +1,5 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
import json
import urllib
import urlparse
import uuid import uuid
import routes import routes
@ -15,7 +12,6 @@ from keystone import identity
from keystone import policy from keystone import policy
from keystone import token from keystone import token
from keystone.common import logging from keystone.common import logging
from keystone.common import utils
from keystone.common import wsgi from keystone.common import wsgi
@ -195,10 +191,10 @@ class TokenController(wsgi.Application):
else: else:
tenant_id = auth.get('tenantId', None) tenant_id = auth.get('tenantId', None)
old_token_ref = self.token_api.get_token(context=context, try:
token_id=token) old_token_ref = self.token_api.get_token(context=context,
token_id=token)
if old_token_ref is None: except exception.NotFound:
raise exception.Unauthorized() raise exception.Unauthorized()
user_ref = old_token_ref['user'] user_ref = old_token_ref['user']
@ -253,9 +249,6 @@ class TokenController(wsgi.Application):
token_ref = self.token_api.get_token(context=context, token_ref = self.token_api.get_token(context=context,
token_id=token_id) token_id=token_id)
if token_ref is None:
raise exception.NotFound(target='token')
if belongs_to: if belongs_to:
assert token_ref['tenant']['id'] == belongs_to assert token_ref['tenant']['id'] == belongs_to
@ -277,8 +270,12 @@ class TokenController(wsgi.Application):
def endpoints(self, context, token_id): def endpoints(self, context, token_id):
"""Return service catalog endpoints.""" """Return service catalog endpoints."""
token_ref = self.token_api.get_token(context=context, try:
token_id=token_id) token_ref = self.token_api.get_token(context=context,
token_id=token_id)
except exception.NotFound:
raise exception.Unauthorized()
catalog_ref = self.catalog_api.get_catalog(context, catalog_ref = self.catalog_api.get_catalog(context,
token_ref['user']['id'], token_ref['user']['id'],
token_ref['tenant']['id']) token_ref['tenant']['id'])

View File

@ -1,17 +1,24 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
from keystone import token
from keystone.common import kvs from keystone.common import kvs
from keystone import exception
from keystone import token
class Token(kvs.Base, token.Driver): class Token(kvs.Base, token.Driver):
# Public interface # Public interface
def get_token(self, token_id): def get_token(self, token_id):
return self.db.get('token-%s' % token_id) try:
return self.db['token-%s' % token_id]
except KeyError:
raise exception.TokenNotFound(token_id=token_id)
def create_token(self, token_id, data): def create_token(self, token_id, data):
self.db.set('token-%s' % token_id, data) self.db.set('token-%s' % token_id, data)
return data return data
def delete_token(self, token_id): def delete_token(self, token_id):
return self.db.delete('token-%s' % token_id) try:
return self.db.delete('token-%s' % token_id)
except KeyError:
raise exception.TokenNotFound(token_id=token_id)

View File

@ -5,6 +5,7 @@ from __future__ import absolute_import
import memcache import memcache
from keystone import config from keystone import config
from keystone import exception
from keystone import token from keystone import token
@ -30,7 +31,11 @@ class Token(token.Driver):
def get_token(self, token_id): def get_token(self, token_id):
ptk = self._prefix_token_id(token_id) ptk = self._prefix_token_id(token_id)
return self.client.get(ptk) token = self.client.get(ptk)
if token is None:
raise exception.TokenNotFound(token_id=token_id)
return token
def create_token(self, token_id, data): def create_token(self, token_id, data):
ptk = self._prefix_token_id(token_id) ptk = self._prefix_token_id(token_id)
@ -38,5 +43,7 @@ class Token(token.Driver):
return data return data
def delete_token(self, token_id): def delete_token(self, token_id):
# Test for existence
self.get_token(token_id)
ptk = self._prefix_token_id(token_id) ptk = self._prefix_token_id(token_id)
return self.client.delete(ptk) return self.client.delete(ptk)

View File

@ -1,7 +1,8 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4 # vim: tabstop=4 shiftwidth=4 softtabstop=4
from keystone import token
from keystone.common import sql from keystone.common import sql
from keystone import exception
from keystone import token
class TokenModel(sql.ModelBase, sql.DictBase): class TokenModel(sql.ModelBase, sql.DictBase):
@ -30,7 +31,7 @@ class Token(sql.Base, token.Driver):
session = self.get_session() session = self.get_session()
token_ref = session.query(TokenModel).filter_by(id=token_id).first() token_ref = session.query(TokenModel).filter_by(id=token_id).first()
if not token_ref: if not token_ref:
return raise exception.TokenNotFound(token_id=token_id)
return token_ref.to_dict() return token_ref.to_dict()
def create_token(self, token_id, data): def create_token(self, token_id, data):
@ -47,6 +48,9 @@ class Token(sql.Base, token.Driver):
token_ref = session.query(TokenModel)\ token_ref = session.query(TokenModel)\
.filter_by(id=token_id)\ .filter_by(id=token_id)\
.first() .first()
if not token_ref:
raise exception.TokenNotFound(token_id=token_id)
with session.begin(): with session.begin():
session.delete(token_ref) session.delete(token_ref)
session.flush() session.flush()

View File

@ -29,7 +29,8 @@ class Driver(object):
:param token_id: identity of the token :param token_id: identity of the token
:type token_id: string :type token_id: string
:returns: token_ref or None. :returns: token_ref
:raises: keystone.exception.TokenNotFound
""" """
raise NotImplementedError() raise NotImplementedError()
@ -63,6 +64,7 @@ class Driver(object):
:param token_id: identity of the token :param token_id: identity of the token
:type token_id: string :type token_id: string
:returns: None. :returns: None.
:raises: keystone.exception.TokenNotFound
""" """
raise NotImplementedError() raise NotImplementedError()

View File

@ -2,6 +2,9 @@
import uuid import uuid
from keystone import exception
class IdentityTests(object): class IdentityTests(object):
def test_authenticate_bad_user(self): def test_authenticate_bad_user(self):
self.assertRaises(AssertionError, self.assertRaises(AssertionError,
@ -214,5 +217,7 @@ class TokenTests(object):
self.assertEquals(new_data_ref, data) self.assertEquals(new_data_ref, data)
self.token_api.delete_token(token_id) self.token_api.delete_token(token_id)
deleted_data_ref = self.token_api.get_token(token_id) self.assertRaises(exception.TokenNotFound,
self.assertTrue(deleted_data_ref is None) self.token_api.delete_token, token_id)
self.assertRaises(exception.TokenNotFound,
self.token_api.get_token, token_id)

View File

@ -1,6 +1,11 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
from keystone import exception
from keystone import test from keystone import test
from keystone.token.backends import memcache as token_memcache from keystone.token.backends import memcache as token_memcache
import test_backend
class MemcacheClient(object): class MemcacheClient(object):
"""Replicates a tiny subset of memcached client interface.""" """Replicates a tiny subset of memcached client interface."""
@ -11,7 +16,10 @@ class MemcacheClient(object):
def get(self, key): def get(self, key):
"""Retrieves the value for a key or None.""" """Retrieves the value for a key or None."""
return self.cache.get(key) try:
return self.cache[key]
except KeyError:
raise exception.TokenNotFound(token_id=key)
def set(self, key, value): def set(self, key, value):
"""Sets the value for a key.""" """Sets the value for a key."""
@ -26,7 +34,7 @@ class MemcacheClient(object):
pass pass
class MemcacheToken(test.TestCase): class MemcacheToken(test.TestCase, test_backend.TokenTests):
def setUp(self): def setUp(self):
super(MemcacheToken, self).setUp() super(MemcacheToken, self).setUp()
fake_client = MemcacheClient() fake_client = MemcacheClient()