diff --git a/bin/glance b/bin/glance index 3dffd64678..bfef25e10a 100755 --- a/bin/glance +++ b/bin/glance @@ -62,7 +62,7 @@ def catch_error(action): try: ret = func(*args, **kwargs) return SUCCESS if ret is None else ret - except (exception.NotAuthorized, exception.Forbidden): + except exception.Forbidden: print "Not authorized to make this request. Check "\ "your credentials (OS_AUTH_USER, OS_AUTH_KEY, ...)." return FAILURE @@ -392,7 +392,7 @@ to spell field names correctly.""" except exception.NotFound: print "No image with ID %s was found" % image_id return FAILURE - except (exception.NotAuthorized, exception.Forbidden): + except exception.Forbidden: print "You do not have permission to update image %s" % image_id return FAILURE except Exception, e: @@ -443,7 +443,7 @@ Deletes an image from Glance""" except exception.NotFound: print "No image with ID %s was found" % image_id return FAILURE - except (exception.NotAuthorized, exception.Forbidden): + except exception.Forbidden: print "You do not have permission to delete image %s" % image_id return FAILURE diff --git a/bin/glance-cache-manage b/bin/glance-cache-manage index f8cccdee6b..9286ad0ff3 100755 --- a/bin/glance-cache-manage +++ b/bin/glance-cache-manage @@ -60,7 +60,7 @@ def catch_error(action): print ("Cache management middleware not enabled on host %s" % options.host) return FAILURE - except exception.NotAuthorized: + except exception.Forbidden: print "Not authorized to make this request. Check "\ "your credentials (OS_AUTH_USER, OS_AUTH_KEY, ...)." return FAILURE diff --git a/glance/api/cached_images.py b/glance/api/cached_images.py index f132683e9e..efbfd0bd9d 100644 --- a/glance/api/cached_images.py +++ b/glance/api/cached_images.py @@ -46,7 +46,7 @@ def _enforce(self, req): """Authorize request against 'manage_image_cache' policy""" try: self.policy.enforce(req.context, 'manage_image_cache', {}) - except exception.NotAuthorized: + except exception.Forbidden: raise webob.exc.HTTPForbidden() def get_cached_images(self, req): diff --git a/glance/api/policy.py b/glance/api/policy.py index 0bd24e085f..8a6ff0151c 100644 --- a/glance/api/policy.py +++ b/glance/api/policy.py @@ -84,7 +84,7 @@ def enforce(self, context, action, target): :param context: Glance request context :param action: String representing the action to be checked :param object: Dictionary representing the object of the action. - :raises: `glance.common.exception.NotAuthorized` + :raises: `glance.common.exception.Forbidden` :returns: None """ self.load_rules() @@ -99,4 +99,4 @@ def enforce(self, context, action, target): try: policy.enforce(match_list, target, credentials) except policy.NotAuthorized: - raise exception.NotAuthorized(action=action) + raise exception.Forbidden(action=action) diff --git a/glance/api/v1/controller.py b/glance/api/v1/controller.py index 2f4b55ecde..d4417801a1 100644 --- a/glance/api/v1/controller.py +++ b/glance/api/v1/controller.py @@ -44,11 +44,6 @@ def get_image_meta_or_404(self, request, image_id): logger.debug(msg) raise webob.exc.HTTPNotFound( msg, request=request, content_type='text/plain') - except exception.NotAuthorized: - msg = _("Unauthorized image access") - logger.debug(msg) - raise webob.exc.HTTPUnauthorized(msg, request=request, - content_type='text/plain') except exception.Forbidden: msg = _("Forbidden image access") logger.debug(msg) diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py index 5a3d78bfa8..9839d2e2bf 100644 --- a/glance/api/v1/images.py +++ b/glance/api/v1/images.py @@ -29,7 +29,6 @@ HTTPConflict, HTTPBadRequest, HTTPForbidden, - HTTPUnauthorized, HTTPRequestEntityTooLarge, HTTPServiceUnavailable, ) @@ -103,8 +102,8 @@ def _enforce(self, req, action): """Authorize an action against our policies""" try: self.policy.enforce(req.context, action, {}) - except exception.NotAuthorized: - raise HTTPUnauthorized() + except exception.Forbidden: + raise HTTPForbidden() def index(self, req): """ @@ -325,10 +324,6 @@ def _reserve(self, req, image_meta): for line in msg.split('\n'): logger.error(line) raise HTTPBadRequest(msg, request=req, content_type="text/plain") - except exception.NotAuthorized: - msg = _("Not authorized to reserve image.") - logger.error(msg) - raise HTTPUnauthorized(msg, request=req, content_type="text/plain") except exception.Forbidden: msg = _("Forbidden to reserve image.") logger.error(msg) @@ -429,14 +424,6 @@ def _upload(self, req, image_meta): self.notifier.error('image.upload', msg) raise HTTPConflict(msg, request=req) - except exception.NotAuthorized, e: - msg = _("Unauthorized upload attempt: %s") % e - logger.error(msg) - self._safe_kill(req, image_id) - self.notifier.error('image.upload', msg) - raise HTTPUnauthorized(msg, request=req, - content_type='text/plain') - except exception.Forbidden, e: msg = _("Forbidden upload attempt: %s") % e logger.error(msg) @@ -698,12 +685,6 @@ def update(self, req, id, image_meta, image_data): logger.info(line) self.notifier.info('image.update', msg) raise HTTPNotFound(msg, request=req, content_type="text/plain") - except exception.NotAuthorized, e: - msg = ("Unable to update image: %(e)s" % locals()) - for line in msg.split('\n'): - logger.info(line) - self.notifier.info('image.update', msg) - raise HTTPUnauthorized(msg, request=req, content_type="text/plain") except exception.Forbidden, e: msg = ("Forbidden to update image: %(e)s" % locals()) for line in msg.split('\n'): @@ -760,12 +741,6 @@ def delete(self, req, id): logger.info(line) self.notifier.info('image.delete', msg) raise HTTPNotFound(msg, request=req, content_type="text/plain") - except exception.NotAuthorized, e: - msg = ("Unable to delete image: %(e)s" % locals()) - for line in msg.split('\n'): - logger.info(line) - self.notifier.info('image.delete', msg) - raise HTTPUnauthorized(msg, request=req, content_type="text/plain") except exception.Forbidden, e: msg = ("Forbidden to delete image: %(e)s" % locals()) for line in msg.split('\n'): diff --git a/glance/api/v1/members.py b/glance/api/v1/members.py index d4e0afb380..4c1dc0127f 100644 --- a/glance/api/v1/members.py +++ b/glance/api/v1/members.py @@ -52,10 +52,6 @@ def index(self, req, image_id): msg = _("Image with identifier %s not found") % image_id logger.debug(msg) raise webob.exc.HTTPNotFound(msg) - except exception.NotAuthorized: - msg = _("Unauthorized image access") - logger.debug(msg) - raise webob.exc.HTTPUnauthorized(msg) except exception.Forbidden: msg = _("Unauthorized image access") logger.debug(msg) @@ -77,7 +73,7 @@ def delete(self, req, image_id, id): msg = "%s" % e logger.debug(msg) raise webob.exc.HTTPNotFound(msg) - except (exception.NotAuthorized, exception.Forbidden), e: + except exception.Forbidden, e: msg = "%s" % e logger.debug(msg) raise webob.exc.HTTPNotFound(msg) @@ -120,7 +116,7 @@ def update(self, req, image_id, id, body=None): msg = "%s" % e logger.debug(msg) raise webob.exc.HTTPNotFound(msg) - except (exception.NotAuthorized, exception.Forbidden), e: + except exception.Forbidden, e: msg = "%s" % e logger.debug(msg) raise webob.exc.HTTPNotFound(msg) @@ -152,7 +148,7 @@ def update_all(self, req, image_id, body): msg = "%s" % e logger.debug(msg) raise webob.exc.HTTPNotFound(msg) - except (exception.NotAuthorized, exception.Forbidden), e: + except exception.Forbidden, e: msg = "%s" % e logger.debug(msg) raise webob.exc.HTTPNotFound(msg) @@ -178,7 +174,7 @@ def index_shared_images(self, req, id): msg = "%s" % e logger.debug(msg) raise webob.exc.HTTPNotFound(msg) - except (exception.NotAuthorized, exception.Forbidden), e: + except exception.Forbidden, e: msg = "%s" % e logger.debug(msg) raise webob.exc.HTTPForbidden(msg) diff --git a/glance/common/auth.py b/glance/common/auth.py index 59cbc959e4..7c38426b76 100644 --- a/glance/common/auth.py +++ b/glance/common/auth.py @@ -178,7 +178,7 @@ def _management_url(self, resp): elif resp.status == 400: raise exception.AuthBadRequest(url=token_url) elif resp.status == 401: - raise exception.NotAuthorized() + raise exception.NotAuthenticated() elif resp.status == 404: raise exception.AuthUrlNotFound(url=token_url) else: @@ -246,7 +246,7 @@ def get_endpoint(service_catalog): elif resp.status == 400: raise exception.AuthBadRequest(url=token_url) elif resp.status == 401: - raise exception.NotAuthorized() + raise exception.NotAuthenticated() elif resp.status == 404: raise exception.AuthUrlNotFound(url=token_url) else: diff --git a/glance/common/client.py b/glance/common/client.py index 5649b8aeba..7c6ae555c0 100644 --- a/glance/common/client.py +++ b/glance/common/client.py @@ -48,7 +48,7 @@ CHUNKSIZE = 65536 -def handle_unauthorized(func): +def handle_unauthenticated(func): """ Wrap a function to re-authenticate and retry. """ @@ -56,7 +56,7 @@ def handle_unauthorized(func): def wrapped(self, *args, **kwargs): try: return func(self, *args, **kwargs) - except (exception.NotAuthorized, exception.Forbidden): + except exception.NotAuthenticated: self._authenticate(force_reauth=True) return func(self, *args, **kwargs) return wrapped @@ -399,7 +399,7 @@ def _authenticate(self, force_reauth=False): if management_url and self.configure_via_auth: self.configure_from_url(management_url) - @handle_unauthorized + @handle_unauthenticated def do_request(self, method, action, body=None, headers=None, params=None): """ @@ -531,7 +531,7 @@ def _retry(res): elif status_code in self.REDIRECT_RESPONSE_CODES: raise exception.RedirectException(res.getheader('Location')) elif status_code == httplib.UNAUTHORIZED: - raise exception.NotAuthorized(res.read()) + raise exception.NotAuthenticated(res.read()) elif status_code == httplib.FORBIDDEN: raise exception.Forbidden(res.read()) elif status_code == httplib.NOT_FOUND: diff --git a/glance/common/context.py b/glance/common/context.py index a0d2cf80cd..41bd205224 100644 --- a/glance/common/context.py +++ b/glance/common/context.py @@ -89,7 +89,7 @@ def process_request(self, req): to determine permissions. 2. An X-Auth-Token was passed in, but the Identity-Status is not - confirmed. For now, just raising a NotAuthorized exception. + confirmed. For now, just raising a NotAuthenticated exception. 3. X-Auth-Token is omitted. If we were using Keystone, then the tokenauth middleware would have rejected the request, so we must be @@ -108,8 +108,8 @@ def process_request(self, req): else: # 2. Indentity-Status not confirmed # FIXME(sirp): not sure what the correct behavior in this case - # is; just raising NotAuthorized for now - raise exception.NotAuthorized() + # is; just raising NotAuthenticated for now + raise exception.NotAuthenticated() else: # 3. Auth-token is ommited, assume NoAuth user = None diff --git a/glance/common/exception.py b/glance/common/exception.py index 9efc901bc7..980158f32e 100644 --- a/glance/common/exception.py +++ b/glance/common/exception.py @@ -109,15 +109,20 @@ class AuthorizationFailure(GlanceException): message = _("Authorization failed.") -class NotAuthorized(GlanceException): - message = _("You are not authorized to complete this action.") +class NotAuthenticated(GlanceException): + message = _("You are not authenticated.") class Forbidden(GlanceException): - message = _("That action is forbidden.") + message = _("You are not authorized to complete this action.") + + +class ForbiddenPublicImage(Forbidden): + message = _("You are not authorized to complete this action.") -class NotAuthorizedPublicImage(NotAuthorized): +#NOTE(bcwaldon): here for backwards-compatability, need to deprecate. +class NotAuthorized(Forbidden): message = _("You are not authorized to complete this action.") diff --git a/glance/registry/api/v1/images.py b/glance/registry/api/v1/images.py index 1c172da2b4..8ccb9461b8 100644 --- a/glance/registry/api/v1/images.py +++ b/glance/registry/api/v1/images.py @@ -274,7 +274,7 @@ def show(self, req, id): image = db_api.image_get(req.context, id) except exception.NotFound: raise exc.HTTPNotFound() - except exception.NotAuthorized: + except exception.Forbidden: # If it's private and doesn't belong to them, don't let on # that it exists msg = _("Access by %(user)s to image %(id)s " @@ -300,7 +300,7 @@ def delete(self, req, id): try: db_api.image_destroy(req.context, id) - except exception.NotAuthorizedPublicImage: + except exception.ForbiddenPublicImage: # If it's private and doesn't belong to them, don't let on # that it exists msg = _("Access by %(user)s to delete public image %(id)s denied") @@ -308,7 +308,7 @@ def delete(self, req, id): logger.info(msg % args) raise exc.HTTPForbidden() - except exception.NotAuthorized: + except exception.Forbidden: msg = _("Access by %(user)s to delete private image %(id)s denied") args = {'user': req.context.user, 'id': id} logger.info(msg % args) @@ -397,12 +397,12 @@ def update(self, req, id, body): raise exc.HTTPNotFound(body='Image not found', request=req, content_type='text/plain') - except exception.NotAuthorizedPublicImage: + except exception.ForbiddenPublicImage: msg = _("Access by %(user)s to update public image %(id)s denied") logger.info(msg % {'user': req.context.user, 'id': id}) raise exc.HTTPForbidden() - except exception.NotAuthorized: + except exception.Forbidden: # If it's private and doesn't belong to them, don't let on # that it exists msg = _("Access by %(user)s to update private image %(id)s denied") diff --git a/glance/registry/api/v1/members.py b/glance/registry/api/v1/members.py index d518a375f1..c1a726614e 100644 --- a/glance/registry/api/v1/members.py +++ b/glance/registry/api/v1/members.py @@ -41,7 +41,7 @@ def index(self, req, image_id): image = db_api.image_get(req.context, image_id) except exception.NotFound: raise webob.exc.HTTPNotFound() - except exception.NotAuthorized: + except exception.Forbidden: # If it's private and doesn't belong to them, don't let on # that it exists msg = _("Access by %(user)s to image %(id)s " @@ -75,7 +75,7 @@ def update_all(self, req, image_id, body): image = db_api.image_get(req.context, image_id, session=session) except exception.NotFound: raise webob.exc.HTTPNotFound() - except exception.NotAuthorized: + except exception.Forbidden: # If it's private and doesn't belong to them, don't let on # that it exists msg = _("Access by %(user)s to image %(id)s " @@ -177,7 +177,7 @@ def update(self, req, image_id, id, body=None): image = db_api.image_get(req.context, image_id) except exception.NotFound: raise webob.exc.HTTPNotFound() - except exception.NotAuthorized: + except exception.Forbidden: # If it's private and doesn't belong to them, don't let on # that it exists msg = _("Access by %(user)s to image %(id)s " @@ -232,7 +232,7 @@ def delete(self, req, image_id, id): image = db_api.image_get(req.context, image_id) except exception.NotFound: raise webob.exc.HTTPNotFound() - except exception.NotAuthorized: + except exception.Forbidden: # If it's private and doesn't belong to them, don't let on # that it exists msg = _("Access by %(user)s to image %(id)s " diff --git a/glance/registry/db/api.py b/glance/registry/db/api.py index d373fe30e6..18094310cc 100644 --- a/glance/registry/db/api.py +++ b/glance/registry/db/api.py @@ -136,9 +136,9 @@ def check_mutate_authorization(context, image_ref): logger.info(_("Attempted to modify image user did not own.")) msg = _("You do not own this image") if image_ref.is_public: - exc_class = exception.NotAuthorizedPublicImage + exc_class = exception.ForbiddenPublicImage else: - exc_class = exception.NotAuthorized + exc_class = exception.Forbidden raise exc_class(msg) @@ -207,7 +207,7 @@ def image_get(context, image_id, session=None, force_show_deleted=False): # Make sure they can look at it if not context.is_image_visible(image): - raise exception.NotAuthorized("Image not visible to you") + raise exception.Forbidden("Image not visible to you") return image @@ -618,7 +618,7 @@ def image_member_get(context, member_id, session=None): # Make sure they can look at it if not context.is_image_visible(member.image): - raise exception.NotAuthorized("Image not visible to you") + raise exception.Forbidden("Image not visible to you") return member diff --git a/glance/store/filesystem.py b/glance/store/filesystem.py index ecbd2041c6..9e9324febf 100644 --- a/glance/store/filesystem.py +++ b/glance/store/filesystem.py @@ -155,7 +155,7 @@ def delete(self, location): from glance.store.location.get_location_from_uri() :raises NotFound if image does not exist - :raises NotAuthorized if cannot delete because of permissions + :raises Forbidden if cannot delete because of permissions """ loc = location.store_location fn = loc.path @@ -164,8 +164,7 @@ def delete(self, location): logger.debug(_("Deleting image at %(fn)s") % locals()) os.unlink(fn) except OSError: - raise exception.NotAuthorized(_("You cannot delete file %s") - % fn) + raise exception.Forbidden(_("You cannot delete file %s") % fn) else: raise exception.NotFound(_("Image file %s does not exist") % fn) diff --git a/glance/tests/functional/test_bin_glance.py b/glance/tests/functional/test_bin_glance.py index 11b9e52b66..0e370e367c 100644 --- a/glance/tests/functional/test_bin_glance.py +++ b/glance/tests/functional/test_bin_glance.py @@ -54,12 +54,11 @@ def test_index_with_https_auth(self): #NOTE(markwash): we should expect the command to fail because the # testing glance api server is not configured to authenticate, and the # token we provide is invalid. However, it should fail due to - # NotAuthorized, rather than because of an SSL error. + # NotAuthenticated, rather than because of an SSL error. self.assertNotEqual(0, exitcode) self.assertNotIn('SSL23_GET_SERVER_HELLO', out) - self.assertIn('NotAuthorized: You are not authorized to complete ' - 'this action.', out) + self.assertIn('NotAuthenticated: You are not authenticated.', out) class TestBinGlance(functional.FunctionalTest): diff --git a/glance/tests/unit/test_api.py b/glance/tests/unit/test_api.py index 7834b5593d..8cfdaf8395 100644 --- a/glance/tests/unit/test_api.py +++ b/glance/tests/unit/test_api.py @@ -2194,7 +2194,7 @@ def test_add_image_unauthorized(self): req.headers['Content-Type'] = 'application/octet-stream' req.body = "chunk00000remainder" res = req.get_response(self.api) - self.assertEquals(res.status_int, 401) + self.assertEquals(res.status_int, 403) def test_add_public_image_unauthorized(self): rules = {"add_image": [], "publicize_image": [["false:false"]]} @@ -2213,7 +2213,7 @@ def test_add_public_image_unauthorized(self): req.headers['Content-Type'] = 'application/octet-stream' req.body = "chunk00000remainder" res = req.get_response(self.api) - self.assertEquals(res.status_int, 401) + self.assertEquals(res.status_int, 403) def _do_test_post_image_content_missing_format(self, missing): """Tests creation of an image with missing format""" @@ -2447,7 +2447,7 @@ def test_publicize_image_unauthorized(self): req.method = 'PUT' req.headers['x-image-meta-is-public'] = 'true' res = req.get_response(self.api) - self.assertEquals(res.status_int, 401) + self.assertEquals(res.status_int, 403) def test_get_index_sort_name_asc(self): """ @@ -2607,14 +2607,14 @@ def test_get_images_detailed_unauthorized(self): self.set_policy_rules(rules) req = webob.Request.blank('/images/detail') res = req.get_response(self.api) - self.assertEquals(res.status_int, 401) + self.assertEquals(res.status_int, 403) def test_get_images_unauthorized(self): rules = {"get_images": [["false:false"]]} self.set_policy_rules(rules) req = webob.Request.blank('/images/detail') res = req.get_response(self.api) - self.assertEquals(res.status_int, 401) + self.assertEquals(res.status_int, 403) def test_store_location_not_revealed(self): """ @@ -2776,7 +2776,7 @@ def test_image_meta_unauthorized(self): req = webob.Request.blank("/images/%s" % UUID2) req.method = 'HEAD' res = req.get_response(self.api) - self.assertEquals(res.status_int, 401) + self.assertEquals(res.status_int, 403) def test_show_image_basic(self): req = webob.Request.blank("/images/%s" % UUID2) @@ -2795,7 +2795,7 @@ def test_show_image_unauthorized(self): self.set_policy_rules(rules) req = webob.Request.blank("/images/%s" % UUID2) res = req.get_response(self.api) - self.assertEqual(res.status_int, 401) + self.assertEqual(res.status_int, 403) def test_delete_image(self): req = webob.Request.blank("/images/%s" % UUID2) @@ -2877,7 +2877,7 @@ def test_delete_image_unauthorized(self): req = webob.Request.blank("/images/%s" % UUID2) req.method = 'DELETE' res = req.get_response(self.api) - self.assertEquals(res.status_int, 401) + self.assertEquals(res.status_int, 403) def test_get_details_invalid_marker(self): """ diff --git a/glance/tests/unit/test_auth.py b/glance/tests/unit/test_auth.py index e5436278bb..24193fc729 100644 --- a/glance/tests/unit/test_auth.py +++ b/glance/tests/unit/test_auth.py @@ -223,9 +223,9 @@ def fake_do_request(cls, url, method, headers=None, body=None): try: plugin = auth.KeystoneStrategy(creds) plugin.authenticate() - self.fail("Failed to raise NotAuthorized when supplying bad " - "credentials: %r" % creds) - except exception.NotAuthorized: + self.fail("Failed to raise NotAuthenticated when supplying " + "bad credentials: %r" % creds) + except exception.NotAuthenticated: continue # Expected no_strategy_creds = { @@ -316,9 +316,9 @@ def fake_do_request(cls, url, method, headers=None, body=None): try: plugin = auth.KeystoneStrategy(creds) plugin.authenticate() - self.fail("Failed to raise NotAuthorized when supplying bad " - "credentials: %r" % creds) - except exception.NotAuthorized: + self.fail("Failed to raise NotAuthenticated when supplying " + "bad credentials: %r" % creds) + except exception.NotAuthenticated: continue # Expected no_region_creds = { diff --git a/glance/tests/unit/test_clients.py b/glance/tests/unit/test_clients.py index 0b832c2092..12b8384ef5 100644 --- a/glance/tests/unit/test_clients.py +++ b/glance/tests/unit/test_clients.py @@ -1127,18 +1127,18 @@ def test_get_member_images(self): def test_replace_members(self): """Tests replacing image members""" - self.assertRaises(exception.NotAuthorized, + self.assertRaises(exception.NotAuthenticated, self.client.replace_members, UUID2, dict(member_id='pattieblack')) def test_add_member(self): """Tests adding image members""" - self.assertRaises(exception.NotAuthorized, + self.assertRaises(exception.NotAuthenticated, self.client.add_member, UUID2, 'pattieblack') def test_delete_member(self): """Tests deleting image members""" - self.assertRaises(exception.NotAuthorized, + self.assertRaises(exception.NotAuthenticated, self.client.delete_member, UUID2, 'pattieblack') @@ -1991,18 +1991,18 @@ def test_get_member_images(self): def test_replace_members(self): """Tests replacing image members""" - self.assertRaises(exception.NotAuthorized, + self.assertRaises(exception.NotAuthenticated, self.client.replace_members, UUID2, dict(member_id='pattieblack')) def test_add_member(self): """Tests adding image members""" - self.assertRaises(exception.NotAuthorized, + self.assertRaises(exception.NotAuthenticated, self.client.add_member, UUID2, 'pattieblack') def test_delete_member(self): """Tests deleting image members""" - self.assertRaises(exception.NotAuthorized, + self.assertRaises(exception.NotAuthenticated, self.client.delete_member, UUID2, 'pattieblack')