Add check_is_image_mutable() legacy helper

This adds a method to let API code replicate the legacy admin-or-owner
behavior where needed. Since the authorization layer does this in
some places (which is being removed) and the DB does it in others,
we need a way to replicate that check when secure_rbac is not in use
for certain code paths (like image delete) which need it.

Change-Id: I89785ae04e7f66651a1b9673f7e5513c2eac10fc
Partially-implements: blueprint policy-refactor
This commit is contained in:
Dan Smith 2021-08-06 09:49:47 -07:00
parent 2841892229
commit 39198f93f8
2 changed files with 65 additions and 0 deletions

View File

@ -13,13 +13,44 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from oslo_log import log as logging
import webob.exc
from glance.api import policy
from glance.common import exception
from glance.i18n import _
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
# TODO(danms): Remove this once secure RBAC is fully implemented and
# used instead of legacy policy checks.
def check_is_image_mutable(context, image):
"""Replicate the DB-layer admin-or-owner check for the API.
Much of the API code depends on hard-coded admin-or-owner
enforcement in the DB or authorization layer, as the policy layer
is largely a no-op by default. During blueprint policy-refactor,
we are trying to remove as much of that as possible, but in
certain places we need to do that (if secure_rbac is not
enabled). This transitional helper provides a way to do that
enforcement where necessary.
:param context: A RequestContext
:param image: An ImageProxy
:raises: exception.Forbidden if the context is not the owner or an admin
"""
# Is admin == image mutable
if context.is_admin:
return
# No owner == image not mutable
# Image only mutable by its owner
if (image.owner is None or context.owner is None or
image.owner != context.owner):
raise exception.Forbidden(_('You do not own this image'))
class APIPolicyBase(object):

View File

@ -55,6 +55,40 @@ class APIPolicyBase(utils.BaseTestCase):
self.enforcer.enforce.side_effect = exception.Forbidden
self.assertFalse(self.policy.check('_enforce', 'fake_rule'))
def test_check_is_image_mutable(self):
context = mock.MagicMock()
image = mock.MagicMock()
# Admin always wins
context.is_admin = True
context.owner = 'someuser'
self.assertIsNone(policy.check_is_image_mutable(context, image))
# Image has no owner is never mutable by non-admins
context.is_admin = False
image.owner = None
self.assertRaises(exception.Forbidden,
policy.check_is_image_mutable,
context, image)
# Not owner is not mutable
image.owner = 'someoneelse'
self.assertRaises(exception.Forbidden,
policy.check_is_image_mutable,
context, image)
# No project in context means not mutable
image.owner = 'someoneelse'
context.owner = None
self.assertRaises(exception.Forbidden,
policy.check_is_image_mutable,
context, image)
# Context matches image owner is mutable
image.owner = 'someuser'
context.owner = 'someuser'
self.assertIsNone(policy.check_is_image_mutable(context, image))
class APIImagePolicy(APIPolicyBase):
def setUp(self):