Refactor gateway get_repo auth layer
This makes us able to optionally not get the authorization layer on top of the stack. The authorization layer makes everything on an Image read-only based on hard-coded checks for "owner or admin". If we are going to move to using policy to enforce modifications to images, we need to discard this layer. When the flag is True we also don't insert the policy layer in the middle of the stack. This patch cleans up the stacking to be a little more modular, and adds a flag to control whether or not we get the authorization layer on top or not. Partially-Implements: blueprint policy-refactor Change-Id: Ie8bea199175a0eb35428b1508af1c49111a87c37
This commit is contained in:
parent
429f16124b
commit
8767489f7b
@ -67,27 +67,42 @@ class Gateway(object):
|
||||
policy_member_factory, context)
|
||||
return authorized_image_factory
|
||||
|
||||
def get_repo(self, context):
|
||||
image_repo = glance.db.ImageRepo(context, self.db_api)
|
||||
store_image_repo = glance.location.ImageRepoProxy(
|
||||
image_repo, context, self.store_api, self.store_utils)
|
||||
quota_image_repo = glance.quota.ImageRepoProxy(
|
||||
store_image_repo, context, self.db_api, self.store_utils)
|
||||
policy_image_repo = policy.ImageRepoProxy(
|
||||
quota_image_repo, context, self.policy)
|
||||
notifier_image_repo = glance.notifier.ImageRepoProxy(
|
||||
policy_image_repo, context, self.notifier)
|
||||
def get_repo(self, context, authorization_layer=True):
|
||||
"""Get the layered ImageRepo model.
|
||||
|
||||
This is where we construct the "the onion" by layering
|
||||
ImageRepo models on top of each other, starting with the DB at
|
||||
the bottom.
|
||||
|
||||
NB: Code that has implemented policy checks fully above this
|
||||
layer should pass authorization_layer=False to ensure that no
|
||||
conflicts with old checks happen. Legacy code should continue
|
||||
passing True until legacy checks are no longer needed.
|
||||
|
||||
:param context: The RequestContext
|
||||
:param authorization_layer: Controls whether or not we add the legacy
|
||||
glance.authorization and glance.policy
|
||||
layers.
|
||||
:returns: An ImageRepo-like object
|
||||
|
||||
"""
|
||||
repo = glance.db.ImageRepo(context, self.db_api)
|
||||
repo = glance.location.ImageRepoProxy(
|
||||
repo, context, self.store_api, self.store_utils)
|
||||
repo = glance.quota.ImageRepoProxy(
|
||||
repo, context, self.db_api, self.store_utils)
|
||||
if authorization_layer:
|
||||
repo = policy.ImageRepoProxy(repo, context, self.policy)
|
||||
repo = glance.notifier.ImageRepoProxy(
|
||||
repo, context, self.notifier)
|
||||
if property_utils.is_property_protection_enabled():
|
||||
property_rules = property_utils.PropertyRules(self.policy)
|
||||
pir = property_protections.ProtectedImageRepoProxy(
|
||||
notifier_image_repo, context, property_rules)
|
||||
authorized_image_repo = authorization.ImageRepoProxy(
|
||||
pir, context)
|
||||
else:
|
||||
authorized_image_repo = authorization.ImageRepoProxy(
|
||||
notifier_image_repo, context)
|
||||
repo = property_protections.ProtectedImageRepoProxy(
|
||||
repo, context, property_rules)
|
||||
if authorization_layer:
|
||||
repo = authorization.ImageRepoProxy(repo, context)
|
||||
|
||||
return authorized_image_repo
|
||||
return repo
|
||||
|
||||
def get_member_repo(self, image, context):
|
||||
image_member_repo = glance.db.ImageMemberRepo(
|
||||
|
@ -15,7 +15,10 @@
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from glance.api import authorization
|
||||
from glance.api import property_protections
|
||||
from glance import gateway
|
||||
from glance import notifier
|
||||
import glance.tests.utils as test_utils
|
||||
|
||||
|
||||
@ -67,3 +70,23 @@ class TestGateway(test_utils.BaseTestCase):
|
||||
admin_repo=mock.sentinel.admin_repo)
|
||||
|
||||
_test()
|
||||
|
||||
@mock.patch('glance.api.policy.ImageRepoProxy')
|
||||
def test_get_repo(self, mock_proxy):
|
||||
repo = self.gateway.get_repo(self.context)
|
||||
self.assertIsInstance(repo, authorization.ImageRepoProxy)
|
||||
mock_proxy.assert_called_once_with(mock.ANY, mock.sentinel.context,
|
||||
mock.ANY)
|
||||
|
||||
@mock.patch('glance.api.policy.ImageRepoProxy')
|
||||
def test_get_repo_without_auth(self, mock_proxy):
|
||||
repo = self.gateway.get_repo(self.context, authorization_layer=False)
|
||||
self.assertIsInstance(repo, notifier.ImageRepoProxy)
|
||||
mock_proxy.assert_not_called()
|
||||
|
||||
@mock.patch('glance.common.property_utils.PropertyRules._load_rules')
|
||||
def test_get_repo_without_auth_with_pp(self, mock_load):
|
||||
self.config(property_protection_file='foo')
|
||||
repo = self.gateway.get_repo(self.context, authorization_layer=False)
|
||||
self.assertIsInstance(repo,
|
||||
property_protections.ProtectedImageRepoProxy)
|
||||
|
Loading…
Reference in New Issue
Block a user