From 248f297da74b6353b9589b2887c9ab5edad8dc22 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 19 Jul 2010 17:07:52 -0700 Subject: Raise 401, not exception if Authorization header not passed. Also minor fixes & Python exception-handling style tweak --- nova/objectstore/handler.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nova/objectstore/handler.py b/nova/objectstore/handler.py index b2ed3d482..e5c97c3bc 100644 --- a/nova/objectstore/handler.py +++ b/nova/objectstore/handler.py @@ -103,13 +103,16 @@ def get_argument(request, key, default_value): def get_context(request): try: # Authorization Header format: 'AWS :' - access, sep, secret = request.getHeader('Authorization').split(' ')[1].rpartition(':') + authorization_header = request.getHeader('Authorization') + if not authorization_header: + raise exception.NotAuthorized + access, sep, secret = authorization_header.split(' ')[1].rpartition(':') um = users.UserManager.instance() print 'um %s' % um (user, project) = um.authenticate(access, secret, {}, request.method, request.host, request.uri, False) # FIXME: check signature here! return api.APIRequestContext(None, user, project) - except exception.Error, ex: + except exception.Error as ex: logging.debug("Authentication Failure: %s" % ex) raise exception.NotAuthorized @@ -131,6 +134,7 @@ class S3(Resource): render_xml(request, {"ListAllMyBucketsResult": { "Buckets": {"Bucket": [b.metadata for b in buckets]}, }}) + request.finish() return server.NOT_DONE_YET class BucketResource(Resource): @@ -165,7 +169,7 @@ class BucketResource(Resource): logging.debug("Creating bucket %s" % (self.name)) try: print 'user is %s' % request.context - except Exception, e: + except Exception as e: logging.exception(e) logging.debug("calling bucket.Bucket.create(%r, %r)" % (self.name, request.context)) bucket.Bucket.create(self.name, request.context) @@ -239,7 +243,7 @@ class ImageResource(Resource): """ returns a json listing of all images that a user has permissions to see """ - images = [i for i in image.Image.all() if i.is_authorized(self.context)] + images = [i for i in image.Image.all() if i.is_authorized(request.context)] request.write(json.dumps([i.metadata for i in images])) return server.NOT_DONE_YET -- cgit From 8625275e14d40dd82d19d2273e14f82334c6b5ac Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 19 Jul 2010 18:26:19 -0700 Subject: I put the call to request.finish() in the wrong place. :-( --- nova/objectstore/handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/objectstore/handler.py b/nova/objectstore/handler.py index e5c97c3bc..c670ee02f 100644 --- a/nova/objectstore/handler.py +++ b/nova/objectstore/handler.py @@ -134,7 +134,6 @@ class S3(Resource): render_xml(request, {"ListAllMyBucketsResult": { "Buckets": {"Bucket": [b.metadata for b in buckets]}, }}) - request.finish() return server.NOT_DONE_YET class BucketResource(Resource): @@ -246,6 +245,7 @@ class ImageResource(Resource): images = [i for i in image.Image.all() if i.is_authorized(request.context)] request.write(json.dumps([i.metadata for i in images])) + request.finish() return server.NOT_DONE_YET def render_PUT(self, request): -- cgit From 8b0c70cce2dd914f1ab4caca8883d616c7c669d6 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 19 Jul 2010 21:39:33 -0700 Subject: Map exceptions to 404 / 403 codes, as was done before the move to twisted. However, I don't think this is the right way to do this in Twisted. For example, exceptions thrown after the render method returns will not be mapped --- nova/objectstore/handler.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/nova/objectstore/handler.py b/nova/objectstore/handler.py index c670ee02f..c3c4486bf 100644 --- a/nova/objectstore/handler.py +++ b/nova/objectstore/handler.py @@ -116,7 +116,21 @@ def get_context(request): logging.debug("Authentication Failure: %s" % ex) raise exception.NotAuthorized -class S3(Resource): +class ErrorHandlingResource(Resource): + """Maps exceptions to 404 / 401 codes. Won't work for exceptions thrown after NOT_DONE_YET is returned.""" + # TODO: This needs to be plugged in to the right place in twisted... + # This doesn't look like it's the right place (consider exceptions in getChild; or after NOT_DONE_YET is returned + def render(self, request): + try: + return Resource.render(self, request) + except exception.NotFound: + request.setResponseCode(404) + return '' + except exception.NotAuthorized: + request.setResponseCode(403) + return '' + +class S3(ErrorHandlingResource): """Implementation of an S3-like storage server based on local files.""" def getChild(self, name, request): request.context = get_context(request) @@ -136,7 +150,7 @@ class S3(Resource): }}) return server.NOT_DONE_YET -class BucketResource(Resource): +class BucketResource(ErrorHandlingResource): def __init__(self, name): Resource.__init__(self) self.name = name @@ -186,7 +200,7 @@ class BucketResource(Resource): return '' -class ObjectResource(Resource): +class ObjectResource(ErrorHandlingResource): def __init__(self, bucket, name): Resource.__init__(self) self.bucket = bucket @@ -227,7 +241,7 @@ class ObjectResource(Resource): request.setResponseCode(204) return '' -class ImageResource(Resource): +class ImageResource(ErrorHandlingResource): isLeaf = True def getChild(self, name, request): -- cgit