From c4fb755b169895f9ffab6ab4d18f5227688b7ae4 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Wed, 22 Dec 2010 13:18:26 -0600 Subject: Abstracted auth and ratelimiting more --- nova/api/openstack/__init__.py | 56 ++++------------------------- nova/api/openstack/auth.py | 22 +++++++++--- nova/api/openstack/ratelimiting/__init__.py | 22 ++++++++++-- 3 files changed, 43 insertions(+), 57 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index cdc25e2b7..b18edc8e7 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -45,12 +45,12 @@ from nova.auth import manager FLAGS = flags.FLAGS -flags.DEFINE_string('nova_api_auth', - 'nova.api.openstack.auth.BasicApiAuthManager', +flags.DEFINE_string('os_api_auth', + 'nova.api.openstack.auth.AuthMiddleware', 'The auth mechanism to use for the OpenStack API implemenation') flags.DEFINE_string('os_api_ratelimiting', - 'nova.api.openstack.ratelimiting.BasicRateLimiting', + 'nova.api.openstack.ratelimiting.RateLimitingMiddleware', 'Default ratelimiting implementation for the Openstack API') flags.DEFINE_bool('allow_admin_api', @@ -62,7 +62,10 @@ class API(wsgi.Middleware): """WSGI entry point for all OpenStack API requests.""" def __init__(self): - app = AuthMiddleware(RateLimitingMiddleware(APIRouter())) + auth_middleware = utils.import_class(FLAGS.os_api_auth) + ratelimiting_middleware = \ + utils.import_class(FLAGS.os_api_ratelimiting) + app = auth_middleware(ratelimiting_middleware(APIRouter())) super(API, self).__init__(app) @webob.dec.wsgify @@ -76,51 +79,6 @@ class API(wsgi.Middleware): return faults.Fault(exc) -class AuthMiddleware(wsgi.Middleware): - """Authorize the openstack API request or return an HTTP Forbidden.""" - - def __init__(self, application): - self.auth_driver = utils.import_class(FLAGS.nova_api_auth)() - super(AuthMiddleware, self).__init__(application) - - @webob.dec.wsgify - def __call__(self, req): - if not self.auth_driver.has_authentication(req): - return self.auth_driver.authenticate(req) - - user = self.auth_driver.get_user_by_authentication(req) - - if not user: - return faults.Fault(webob.exc.HTTPUnauthorized()) - - req.environ['nova.context'] = context.RequestContext(user, user) - return self.application - - -class RateLimitingMiddleware(wsgi.Middleware): - """Rate limit incoming requests according to the OpenStack rate limits.""" - - def __init__(self, application, service_host=None): - """Create a rate limiting middleware that wraps the given application. - - By default, rate counters are stored in memory. If service_host is - specified, the middleware instead relies on the ratelimiting.WSGIApp - at the given host+port to keep rate counters. - """ - super(RateLimitingMiddleware, self).__init__(application) - self._limiting_driver = \ - utils.import_class(FLAGS.os_api_ratelimiting)(service_host) - - @webob.dec.wsgify - def __call__(self, req): - """Rate limit the request. - - If the request should be rate limited, return a 413 status with a - Retry-After header giving the time when the request would succeed. - """ - return self._limiting_driver.limited_request(req, self.application) - - class APIRouter(wsgi.Router): """ Routes requests on the OpenStack API to the appropriate controller diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index 26cb50dca..3850dd1f0 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -16,16 +16,28 @@ from nova.api.openstack import faults FLAGS = flags.FLAGS +class AuthMiddleware(wsgi.Middleware): + """Authorize the openstack API request or return an HTTP Forbidden.""" -class BasicApiAuthManager(object): - """ Implements a somewhat rudimentary version of OpenStack Auth""" - - def __init__(self, db_driver=None): + def __init__(self, application): if not db_driver: db_driver = FLAGS.db_driver self.db = utils.import_object(db_driver) self.auth = auth.manager.AuthManager() - super(BasicApiAuthManager, self).__init__() + super(AuthMiddleware, self).__init__(application) + + @webob.dec.wsgify + def __call__(self, req): + if not self.has_authentication(req): + return self.authenticate(req) + + user = self.get_user_by_authentication(req) + + if not user: + return faults.Fault(webob.exc.HTTPUnauthorized()) + + req.environ['nova.context'] = context.RequestContext(user, user) + return self.application def has_authentication(self, req): return 'X-Auth-Token' in req.headers diff --git a/nova/api/openstack/ratelimiting/__init__.py b/nova/api/openstack/ratelimiting/__init__.py index 1bf44bc7b..9892e792e 100644 --- a/nova/api/openstack/ratelimiting/__init__.py +++ b/nova/api/openstack/ratelimiting/__init__.py @@ -14,11 +14,16 @@ PER_MINUTE = 60 PER_HOUR = 60 * 60 PER_DAY = 60 * 60 * 24 +class RateLimitingMiddleware(wsgi.Middleware): + """Rate limit incoming requests according to the OpenStack rate limits.""" -class BasicRateLimiting(object): - """ Implements Rate limits as per the Rackspace CloudServers API spec. """ + def __init__(self, application, service_host=None): + """Create a rate limiting middleware that wraps the given application. - def __init__(self, service_host): + By default, rate counters are stored in memory. If service_host is + specified, the middleware instead relies on the ratelimiting.WSGIApp + at the given host+port to keep rate counters. + """ if not service_host: #TODO(gundlach): These limits were based on limitations of Cloud #Servers. We should revisit them in Nova. @@ -31,6 +36,16 @@ class BasicRateLimiting(object): }) else: self.limiter = WSGIAppProxy(service_host) + super(RateLimitingMiddleware, self).__init__(application) + + @webob.dec.wsgify + def __call__(self, req): + """Rate limit the request. + + If the request should be rate limited, return a 413 status with a + Retry-After header giving the time when the request would succeed. + """ + return self.limited_request(req, self.application) def limited_request(self, req, application): """Rate limit the request. @@ -75,6 +90,7 @@ class BasicRateLimiting(object): return req.method return None + class Limiter(object): """Class providing rate limiting of arbitrary actions.""" -- cgit