Remove deprecated `enforce_secure_rbac
` option
As per the revised SRBAC community goals, glance service is now switching to new defaults by default hence removing the deprecated ``enforce_secure_rbac`` option which is no longer needed. The ``enforce_secure_rbac`` option was introduced EXPERIMENTAL in Wallaby release for operators to opt into enforcing authorization based on common RBAC personas. Related blueprint secure-rbac Change-Id: I273527c85d30c1c09c086c73c892aaa6d127df6b
This commit is contained in:
parent
8c04d19e88
commit
b20cc91e6f
@ -25,7 +25,6 @@ from oslo_policy import policy
|
|||||||
|
|
||||||
from glance.common import exception
|
from glance.common import exception
|
||||||
from glance.domain import proxy
|
from glance.domain import proxy
|
||||||
from glance.i18n import _LW
|
|
||||||
from glance import policies
|
from glance import policies
|
||||||
|
|
||||||
|
|
||||||
@ -64,15 +63,6 @@ class Enforcer(policy.Enforcer):
|
|||||||
if suppress_deprecation_warnings:
|
if suppress_deprecation_warnings:
|
||||||
self.suppress_deprecation_warnings = True
|
self.suppress_deprecation_warnings = True
|
||||||
self.register_defaults(policies.list_rules())
|
self.register_defaults(policies.list_rules())
|
||||||
if CONF.enforce_secure_rbac and CONF.oslo_policy.enforce_new_defaults:
|
|
||||||
LOG.warning(_LW(
|
|
||||||
"Deploying glance with secure RBAC personas enabled via "
|
|
||||||
"`glance-api.conf [DEFAULT] enforce_secure_rbac=True` and "
|
|
||||||
"`glance-api.conf [oslo_policy] enforce_new_defaults=True` "
|
|
||||||
"is marked as EXPERIMENTAL in Wallaby. The status of this "
|
|
||||||
"feature will graduate to SUPPORTED as glance adopts more "
|
|
||||||
"personas, specifically for system-scope."
|
|
||||||
))
|
|
||||||
|
|
||||||
def add_rules(self, rules):
|
def add_rules(self, rules):
|
||||||
"""Add new rules to the Rules object"""
|
"""Add new rules to the Rules object"""
|
||||||
|
@ -82,7 +82,8 @@ class ImageMembersController(object):
|
|||||||
# NOTE(abhishekk): Ownership check only needs to performed while
|
# NOTE(abhishekk): Ownership check only needs to performed while
|
||||||
# adding new members to image
|
# adding new members to image
|
||||||
owner = image.owner
|
owner = image.owner
|
||||||
if not CONF.enforce_secure_rbac and not context.is_admin:
|
if not (CONF.oslo_policy.enforce_new_defaults or
|
||||||
|
CONF.oslo_policy.enforce_scope) and not context.is_admin:
|
||||||
if ownership_check == 'create':
|
if ownership_check == 'create':
|
||||||
if owner is None or owner != context.owner:
|
if owner is None or owner != context.owner:
|
||||||
message = _("You are not permitted to create image "
|
message = _("You are not permitted to create image "
|
||||||
|
@ -225,7 +225,8 @@ class ImageAPIPolicy(APIPolicyBase):
|
|||||||
self._enforce('delete_image_location')
|
self._enforce('delete_image_location')
|
||||||
# TODO(danms): Remove this legacy fallback when secure RBAC
|
# TODO(danms): Remove this legacy fallback when secure RBAC
|
||||||
# replaces the legacy policy.
|
# replaces the legacy policy.
|
||||||
if not CONF.enforce_secure_rbac:
|
if not (CONF.oslo_policy.enforce_new_defaults or
|
||||||
|
CONF.oslo_policy.enforce_scope):
|
||||||
check_is_image_mutable(self._context, self._image)
|
check_is_image_mutable(self._context, self._image)
|
||||||
|
|
||||||
def get_image_location(self):
|
def get_image_location(self):
|
||||||
@ -247,7 +248,8 @@ class ImageAPIPolicy(APIPolicyBase):
|
|||||||
raise
|
raise
|
||||||
if 'visibility' in self._target:
|
if 'visibility' in self._target:
|
||||||
self._enforce_visibility(self._target['visibility'])
|
self._enforce_visibility(self._target['visibility'])
|
||||||
if not CONF.enforce_secure_rbac:
|
if not (CONF.oslo_policy.enforce_new_defaults or
|
||||||
|
CONF.oslo_policy.enforce_scope):
|
||||||
check_admin_or_same_owner(self._context, self._target)
|
check_admin_or_same_owner(self._context, self._target)
|
||||||
|
|
||||||
def get_image(self):
|
def get_image(self):
|
||||||
@ -260,14 +262,16 @@ class ImageAPIPolicy(APIPolicyBase):
|
|||||||
self._enforce('delete_image')
|
self._enforce('delete_image')
|
||||||
# TODO(danms): Remove this legacy fallback when secure RBAC
|
# TODO(danms): Remove this legacy fallback when secure RBAC
|
||||||
# replaces the legacy policy.
|
# replaces the legacy policy.
|
||||||
if not CONF.enforce_secure_rbac:
|
if not (CONF.oslo_policy.enforce_new_defaults or
|
||||||
|
CONF.oslo_policy.enforce_scope):
|
||||||
check_is_image_mutable(self._context, self._image)
|
check_is_image_mutable(self._context, self._image)
|
||||||
|
|
||||||
def upload_image(self):
|
def upload_image(self):
|
||||||
self._enforce('upload_image')
|
self._enforce('upload_image')
|
||||||
# TODO(danms): Remove this legacy fallback when secure RBAC
|
# TODO(danms): Remove this legacy fallback when secure RBAC
|
||||||
# replaces the legacy policy.
|
# replaces the legacy policy.
|
||||||
if not CONF.enforce_secure_rbac:
|
if not (CONF.oslo_policy.enforce_new_defaults or
|
||||||
|
CONF.oslo_policy.enforce_scope):
|
||||||
check_is_image_mutable(self._context, self._image)
|
check_is_image_mutable(self._context, self._image)
|
||||||
|
|
||||||
def download_image(self):
|
def download_image(self):
|
||||||
@ -277,21 +281,24 @@ class ImageAPIPolicy(APIPolicyBase):
|
|||||||
self._enforce('modify_image')
|
self._enforce('modify_image')
|
||||||
# TODO(danms): Remove this legacy fallback when secure RBAC
|
# TODO(danms): Remove this legacy fallback when secure RBAC
|
||||||
# replaces the legacy policy.
|
# replaces the legacy policy.
|
||||||
if not CONF.enforce_secure_rbac:
|
if not (CONF.oslo_policy.enforce_new_defaults or
|
||||||
|
CONF.oslo_policy.enforce_scope):
|
||||||
check_is_image_mutable(self._context, self._image)
|
check_is_image_mutable(self._context, self._image)
|
||||||
|
|
||||||
def deactivate_image(self):
|
def deactivate_image(self):
|
||||||
self._enforce('deactivate')
|
self._enforce('deactivate')
|
||||||
# TODO(danms): Remove this legacy fallback when secure RBAC
|
# TODO(danms): Remove this legacy fallback when secure RBAC
|
||||||
# replaces the legacy policy.
|
# replaces the legacy policy.
|
||||||
if not CONF.enforce_secure_rbac:
|
if not (CONF.oslo_policy.enforce_new_defaults or
|
||||||
|
CONF.oslo_policy.enforce_scope):
|
||||||
check_is_image_mutable(self._context, self._image)
|
check_is_image_mutable(self._context, self._image)
|
||||||
|
|
||||||
def reactivate_image(self):
|
def reactivate_image(self):
|
||||||
self._enforce('reactivate')
|
self._enforce('reactivate')
|
||||||
# TODO(danms): Remove this legacy fallback when secure RBAC
|
# TODO(danms): Remove this legacy fallback when secure RBAC
|
||||||
# replaces the legacy policy.
|
# replaces the legacy policy.
|
||||||
if not CONF.enforce_secure_rbac:
|
if not (CONF.oslo_policy.enforce_new_defaults or
|
||||||
|
CONF.oslo_policy.enforce_scope):
|
||||||
check_is_image_mutable(self._context, self._image)
|
check_is_image_mutable(self._context, self._image)
|
||||||
|
|
||||||
def copy_image(self):
|
def copy_image(self):
|
||||||
|
@ -108,14 +108,6 @@ def main():
|
|||||||
host=CONF.bind_host
|
host=CONF.bind_host
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF.enforce_secure_rbac != CONF.oslo_policy.enforce_new_defaults:
|
|
||||||
fail_message = (
|
|
||||||
"[DEFAULT] enforce_secure_rbac does not match "
|
|
||||||
"[oslo_policy] enforce_new_defaults. Please set both to "
|
|
||||||
"True to enable secure RBAC personas. Otherwise, make sure "
|
|
||||||
"both are False.")
|
|
||||||
raise exception.ServerError(fail_message)
|
|
||||||
|
|
||||||
# NOTE(danms): Configure system-wide threading model to use eventlet
|
# NOTE(danms): Configure system-wide threading model to use eventlet
|
||||||
glance.async_.set_threadpool_model('eventlet')
|
glance.async_.set_threadpool_model('eventlet')
|
||||||
|
|
||||||
|
@ -593,30 +593,6 @@ Related options:
|
|||||||
|
|
||||||
Related options:
|
Related options:
|
||||||
* [DEFAULT]/node_staging_uri""")),
|
* [DEFAULT]/node_staging_uri""")),
|
||||||
cfg.BoolOpt('enforce_secure_rbac', default=True,
|
|
||||||
deprecated_for_removal=True,
|
|
||||||
deprecated_reason=_("""
|
|
||||||
This option has been introduced to require operators to opt into enforcing
|
|
||||||
authorization based on common RBAC personas, which is EXPERIMENTAL as of the
|
|
||||||
Wallaby release. This behavior will be the default and STABLE in a future
|
|
||||||
release, allowing this option to be removed.
|
|
||||||
"""),
|
|
||||||
deprecated_since='Wallaby',
|
|
||||||
help=_("""
|
|
||||||
Enforce API access based on common persona definitions used across OpenStack.
|
|
||||||
Enabling this option formalizes project-specific read/write operations, like
|
|
||||||
creating private images or updating the status of shared image, behind the
|
|
||||||
`member` role. It also formalizes a read-only variant useful for
|
|
||||||
project-specific API operations, like listing private images in a project,
|
|
||||||
behind the `reader` role.
|
|
||||||
|
|
||||||
Operators should take an opportunity to understand glance's new image policies,
|
|
||||||
audit assignments in their deployment, and update permissions using the default
|
|
||||||
roles in keystone (e.g., `admin`, `member`, and `reader`).
|
|
||||||
|
|
||||||
Related options:
|
|
||||||
* [oslo_policy]/enforce_new_defaults
|
|
||||||
""")),
|
|
||||||
cfg.StrOpt('worker_self_reference_url',
|
cfg.StrOpt('worker_self_reference_url',
|
||||||
default=None,
|
default=None,
|
||||||
help=_("""
|
help=_("""
|
||||||
|
@ -22,7 +22,6 @@ import osprofiler.initializer
|
|||||||
from glance.api import common
|
from glance.api import common
|
||||||
import glance.async_
|
import glance.async_
|
||||||
from glance.common import config
|
from glance.common import config
|
||||||
from glance.common import exception
|
|
||||||
from glance.common import store_utils
|
from glance.common import store_utils
|
||||||
from glance import housekeeping
|
from glance import housekeeping
|
||||||
from glance.i18n import _
|
from glance.i18n import _
|
||||||
@ -80,16 +79,6 @@ def _setup_os_profiler():
|
|||||||
host=CONF.bind_host)
|
host=CONF.bind_host)
|
||||||
|
|
||||||
|
|
||||||
def _validate_policy_enforcement_configuration():
|
|
||||||
if CONF.enforce_secure_rbac != CONF.oslo_policy.enforce_new_defaults:
|
|
||||||
fail_message = (
|
|
||||||
"[DEFAULT] enforce_secure_rbac does not match "
|
|
||||||
"[oslo_policy] enforce_new_defaults. Please set both to "
|
|
||||||
"True to enable secure RBAC personas. Otherwise, make sure "
|
|
||||||
"both are False.")
|
|
||||||
raise exception.ServerError(fail_message)
|
|
||||||
|
|
||||||
|
|
||||||
def drain_workers():
|
def drain_workers():
|
||||||
# NOTE(danms): If there are any other named pools that we need to
|
# NOTE(danms): If there are any other named pools that we need to
|
||||||
# drain before exit, they should be in this list.
|
# drain before exit, they should be in this list.
|
||||||
@ -155,5 +144,4 @@ def init_app():
|
|||||||
run_staging_cleanup()
|
run_staging_cleanup()
|
||||||
|
|
||||||
_setup_os_profiler()
|
_setup_os_profiler()
|
||||||
_validate_policy_enforcement_configuration()
|
|
||||||
return config.load_paste_app('glance-api')
|
return config.load_paste_app('glance-api')
|
||||||
|
@ -408,9 +408,7 @@ class ApiServer(Server):
|
|||||||
self.image_location_quota = 2
|
self.image_location_quota = 2
|
||||||
self.disable_path = None
|
self.disable_path = None
|
||||||
|
|
||||||
secure_rbac = bool(os.getenv('OS_GLANCE_TEST_RBAC_DEFAULTS'))
|
self.enforce_new_defaults = True
|
||||||
self.enforce_secure_rbac = secure_rbac
|
|
||||||
self.enforce_new_defaults = secure_rbac
|
|
||||||
|
|
||||||
self.needs_database = True
|
self.needs_database = True
|
||||||
default_sql_connection = SQLITE_CONN_TEMPLATE % self.test_dir
|
default_sql_connection = SQLITE_CONN_TEMPLATE % self.test_dir
|
||||||
@ -456,7 +454,6 @@ image_location_quota=%(image_location_quota)s
|
|||||||
location_strategy=%(location_strategy)s
|
location_strategy=%(location_strategy)s
|
||||||
allow_additional_image_properties = True
|
allow_additional_image_properties = True
|
||||||
node_staging_uri=%(node_staging_uri)s
|
node_staging_uri=%(node_staging_uri)s
|
||||||
enforce_secure_rbac=%(enforce_secure_rbac)s
|
|
||||||
[oslo_policy]
|
[oslo_policy]
|
||||||
policy_file = %(policy_file)s
|
policy_file = %(policy_file)s
|
||||||
policy_default_rule = %(policy_default_rule)s
|
policy_default_rule = %(policy_default_rule)s
|
||||||
@ -585,7 +582,6 @@ class ApiServerForMultipleBackend(Server):
|
|||||||
self.image_location_quota = 2
|
self.image_location_quota = 2
|
||||||
self.disable_path = None
|
self.disable_path = None
|
||||||
|
|
||||||
self.enforce_secure_rbac = True
|
|
||||||
self.enforce_new_defaults = True
|
self.enforce_new_defaults = True
|
||||||
|
|
||||||
self.needs_database = True
|
self.needs_database = True
|
||||||
@ -629,7 +625,6 @@ image_location_quota=%(image_location_quota)s
|
|||||||
location_strategy=%(location_strategy)s
|
location_strategy=%(location_strategy)s
|
||||||
allow_additional_image_properties = True
|
allow_additional_image_properties = True
|
||||||
enabled_backends=file1:file,file2:file,file3:file
|
enabled_backends=file1:file,file2:file,file3:file
|
||||||
enforce_secure_rbac=%(enforce_secure_rbac)s
|
|
||||||
[oslo_policy]
|
[oslo_policy]
|
||||||
policy_file = %(policy_file)s
|
policy_file = %(policy_file)s
|
||||||
policy_default_rule = %(policy_default_rule)s
|
policy_default_rule = %(policy_default_rule)s
|
||||||
@ -1620,9 +1615,9 @@ class SynchronousAPIBase(test_utils.BaseTestCase):
|
|||||||
|
|
||||||
self.api = config.load_paste_app(root_app,
|
self.api = config.load_paste_app(root_app,
|
||||||
conf_file=self.paste_config)
|
conf_file=self.paste_config)
|
||||||
secure_rbac = bool(os.getenv('OS_GLANCE_TEST_RBAC_DEFAULTS'))
|
self.config(enforce_new_defaults=True,
|
||||||
self.config(enforce_secure_rbac=secure_rbac)
|
group='oslo_policy')
|
||||||
self.config(enforce_new_defaults=secure_rbac,
|
self.config(enforce_scope=True,
|
||||||
group='oslo_policy')
|
group='oslo_policy')
|
||||||
|
|
||||||
def _headers(self, custom_headers=None):
|
def _headers(self, custom_headers=None):
|
||||||
|
@ -19,7 +19,6 @@ from unittest import mock
|
|||||||
from glance.api import common
|
from glance.api import common
|
||||||
from glance.api.v2 import cached_images
|
from glance.api.v2 import cached_images
|
||||||
import glance.async_
|
import glance.async_
|
||||||
from glance.common import exception
|
|
||||||
from glance.common import wsgi_app
|
from glance.common import wsgi_app
|
||||||
from glance.tests import utils as test_utils
|
from glance.tests import utils as test_utils
|
||||||
|
|
||||||
@ -91,40 +90,6 @@ class TestWsgiAppInit(test_utils.BaseTestCase):
|
|||||||
wsgi_app.drain_workers()
|
wsgi_app.drain_workers()
|
||||||
self.assertIsNone(cached_images.WORKER)
|
self.assertIsNone(cached_images.WORKER)
|
||||||
|
|
||||||
@mock.patch('glance.common.config.load_paste_app')
|
|
||||||
@mock.patch('glance.async_.set_threadpool_model')
|
|
||||||
@mock.patch('glance.common.wsgi_app._get_config_files')
|
|
||||||
def test_policy_enforcement_kills_service_if_misconfigured(
|
|
||||||
self, mock_load_app, mock_set, mock_config_files):
|
|
||||||
self.config(enforce_new_defaults=True, group='oslo_policy')
|
|
||||||
self.config(enforce_secure_rbac=False)
|
|
||||||
self.assertRaises(exception.ServerError, wsgi_app.init_app)
|
|
||||||
|
|
||||||
self.config(enforce_new_defaults=False, group='oslo_policy')
|
|
||||||
self.config(enforce_secure_rbac=True)
|
|
||||||
self.assertRaises(exception.ServerError, wsgi_app.init_app)
|
|
||||||
|
|
||||||
@mock.patch('glance.common.config.load_paste_app')
|
|
||||||
@mock.patch('glance.async_.set_threadpool_model')
|
|
||||||
@mock.patch('glance.common.wsgi_app._get_config_files')
|
|
||||||
def test_policy_enforcement_valid_truthy_configuration(
|
|
||||||
self, mock_load_app, mock_set, mock_config_files):
|
|
||||||
self.config(enforce_new_defaults=True, group='oslo_policy')
|
|
||||||
self.config(enforce_secure_rbac=True)
|
|
||||||
self.assertTrue(wsgi_app.init_app())
|
|
||||||
|
|
||||||
@mock.patch('glance.common.config.load_paste_app')
|
|
||||||
@mock.patch('glance.async_.set_threadpool_model')
|
|
||||||
@mock.patch('glance.common.wsgi_app._get_config_files')
|
|
||||||
def test_policy_enforcement_valid_falsy_configuration(
|
|
||||||
self, mock_load_app, mock_set, mock_config_files):
|
|
||||||
# This is effectively testing the default values, but we're doing that
|
|
||||||
# to make sure nothing bad happens at runtime in the default case when
|
|
||||||
# validating policy enforcement configuration.
|
|
||||||
self.config(enforce_new_defaults=False, group='oslo_policy')
|
|
||||||
self.config(enforce_secure_rbac=False)
|
|
||||||
self.assertTrue(wsgi_app.init_app())
|
|
||||||
|
|
||||||
@mock.patch('glance.async_._THREADPOOL_MODEL', new=None)
|
@mock.patch('glance.async_._THREADPOOL_MODEL', new=None)
|
||||||
@mock.patch('glance.common.config.load_paste_app')
|
@mock.patch('glance.common.config.load_paste_app')
|
||||||
@mock.patch('glance.common.wsgi_app._get_config_files')
|
@mock.patch('glance.common.wsgi_app._get_config_files')
|
||||||
|
@ -394,29 +394,6 @@ class TestPolicyEnforcer(base.IsolatedUnitTest):
|
|||||||
enforcer.check(context, 'foo', {})
|
enforcer.check(context, 'foo', {})
|
||||||
mock_enforcer.assert_called_once_with('foo', {}, context)
|
mock_enforcer.assert_called_once_with('foo', {}, context)
|
||||||
|
|
||||||
def test_ensure_experimental_warning_is_logged_for_secure_rbac(self):
|
|
||||||
self.config(enforce_new_defaults=True, group='oslo_policy')
|
|
||||||
self.config(enforce_secure_rbac=True)
|
|
||||||
expected_log_string = (
|
|
||||||
"Deploying glance with secure RBAC personas enabled via "
|
|
||||||
"`glance-api.conf [DEFAULT] enforce_secure_rbac=True` and "
|
|
||||||
"`glance-api.conf [oslo_policy] enforce_new_defaults=True` "
|
|
||||||
"is marked as EXPERIMENTAL in Wallaby. The status of this "
|
|
||||||
"feature will graduate to SUPPORTED as glance adopts more "
|
|
||||||
"personas, specifically for system-scope."
|
|
||||||
)
|
|
||||||
with mock.patch.object(glance.api.policy, 'LOG') as mock_log:
|
|
||||||
glance.api.policy.Enforcer(
|
|
||||||
suppress_deprecation_warnings=True)
|
|
||||||
mock_log.warning.assert_called_once_with(expected_log_string)
|
|
||||||
|
|
||||||
def test_ensure_experimental_warning_is_not_logged_for_legacy_rbac(self):
|
|
||||||
self.config(enforce_new_defaults=False, group='oslo_policy')
|
|
||||||
with mock.patch.object(glance.api.policy, 'LOG') as mock_log:
|
|
||||||
glance.api.policy.Enforcer(
|
|
||||||
suppress_deprecation_warnings=True)
|
|
||||||
mock_log.warning.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
class TestPolicyEnforcerNoFile(base.IsolatedUnitTest):
|
class TestPolicyEnforcerNoFile(base.IsolatedUnitTest):
|
||||||
|
|
||||||
|
@ -142,7 +142,8 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
mock.ANY)
|
mock.ANY)
|
||||||
|
|
||||||
def test_delete_locations_falls_back_to_legacy(self):
|
def test_delete_locations_falls_back_to_legacy(self):
|
||||||
self.config(enforce_secure_rbac=False)
|
self.config(enforce_new_defaults=False, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=False, group='oslo_policy')
|
||||||
|
|
||||||
# As admin, image is mutable even if owner does not match
|
# As admin, image is mutable even if owner does not match
|
||||||
self.context.is_admin = True
|
self.context.is_admin = True
|
||||||
@ -166,8 +167,10 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
self.policy.delete_locations()
|
self.policy.delete_locations()
|
||||||
m.assert_called_once_with(self.context, self.image)
|
m.assert_called_once_with(self.context, self.image)
|
||||||
|
|
||||||
# Make sure we are not checking it if enforce_secure_rbac=True
|
# Make sure we are not checking it if enforce_new_defaults=True and
|
||||||
self.config(enforce_secure_rbac=True)
|
# enforce_scope=True
|
||||||
|
self.config(enforce_new_defaults=True, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=True, group='oslo_policy')
|
||||||
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
||||||
self.policy.delete_locations()
|
self.policy.delete_locations()
|
||||||
self.assertFalse(m.called)
|
self.assertFalse(m.called)
|
||||||
@ -235,7 +238,8 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
generic_target)
|
generic_target)
|
||||||
|
|
||||||
def test_add_image_falls_back_to_legacy(self):
|
def test_add_image_falls_back_to_legacy(self):
|
||||||
self.config(enforce_secure_rbac=False)
|
self.config(enforce_new_defaults=False, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=False, group='oslo_policy')
|
||||||
|
|
||||||
self.context.is_admin = False
|
self.context.is_admin = False
|
||||||
self.policy = policy.ImageAPIPolicy(self.context, {'owner': 'else'},
|
self.policy = policy.ImageAPIPolicy(self.context, {'owner': 'else'},
|
||||||
@ -252,7 +256,8 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
# Make sure we are not calling the legacy handler if
|
# Make sure we are not calling the legacy handler if
|
||||||
# secure_rbac is being used. We won't fail the check because
|
# secure_rbac is being used. We won't fail the check because
|
||||||
# our enforcer is a mock, just make sure we don't call that handler.
|
# our enforcer is a mock, just make sure we don't call that handler.
|
||||||
self.config(enforce_secure_rbac=True)
|
self.config(enforce_new_defaults=True, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=True, group='oslo_policy')
|
||||||
with mock.patch('glance.api.v2.policy.check_admin_or_same_owner') as m:
|
with mock.patch('glance.api.v2.policy.check_admin_or_same_owner') as m:
|
||||||
self.policy.add_image()
|
self.policy.add_image()
|
||||||
m.assert_not_called()
|
m.assert_not_called()
|
||||||
@ -287,8 +292,8 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
mock.ANY)
|
mock.ANY)
|
||||||
|
|
||||||
def test_delete_image_falls_back_to_legacy(self):
|
def test_delete_image_falls_back_to_legacy(self):
|
||||||
self.config(enforce_secure_rbac=False)
|
self.config(enforce_new_defaults=False, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=False, group='oslo_policy')
|
||||||
# As admin, image is mutable even if owner does not match
|
# As admin, image is mutable even if owner does not match
|
||||||
self.context.is_admin = True
|
self.context.is_admin = True
|
||||||
self.context.owner = 'someuser'
|
self.context.owner = 'someuser'
|
||||||
@ -311,8 +316,10 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
self.policy.delete_image()
|
self.policy.delete_image()
|
||||||
m.assert_called_once_with(self.context, self.image)
|
m.assert_called_once_with(self.context, self.image)
|
||||||
|
|
||||||
# Make sure we are not checking it if enforce_secure_rbac=True
|
# Make sure we are not checking it if enforce_new_defaults=True and
|
||||||
self.config(enforce_secure_rbac=True)
|
# enforce_scope=True
|
||||||
|
self.config(enforce_new_defaults=True, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=True, group='oslo_policy')
|
||||||
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
||||||
self.policy.delete_image()
|
self.policy.delete_image()
|
||||||
self.assertFalse(m.called)
|
self.assertFalse(m.called)
|
||||||
@ -324,7 +331,8 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
mock.ANY)
|
mock.ANY)
|
||||||
|
|
||||||
def test_upload_image_falls_back_to_legacy(self):
|
def test_upload_image_falls_back_to_legacy(self):
|
||||||
self.config(enforce_secure_rbac=False)
|
self.config(enforce_new_defaults=False, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=False, group='oslo_policy')
|
||||||
|
|
||||||
# As admin, image is mutable even if owner does not match
|
# As admin, image is mutable even if owner does not match
|
||||||
self.context.is_admin = True
|
self.context.is_admin = True
|
||||||
@ -348,8 +356,10 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
self.policy.upload_image()
|
self.policy.upload_image()
|
||||||
m.assert_called_once_with(self.context, self.image)
|
m.assert_called_once_with(self.context, self.image)
|
||||||
|
|
||||||
# Make sure we are not checking it if enforce_secure_rbac=True
|
# Make sure we are not checking it if enforce_new_defaults=True and
|
||||||
self.config(enforce_secure_rbac=True)
|
# enforce_scope=True
|
||||||
|
self.config(enforce_new_defaults=True, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=True, group='oslo_policy')
|
||||||
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
||||||
self.policy.upload_image()
|
self.policy.upload_image()
|
||||||
self.assertFalse(m.called)
|
self.assertFalse(m.called)
|
||||||
@ -367,7 +377,8 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
mock.ANY)
|
mock.ANY)
|
||||||
|
|
||||||
def test_modify_image_falls_back_to_legacy(self):
|
def test_modify_image_falls_back_to_legacy(self):
|
||||||
self.config(enforce_secure_rbac=False)
|
self.config(enforce_new_defaults=False, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=False, group='oslo_policy')
|
||||||
|
|
||||||
# As admin, image is mutable even if owner does not match
|
# As admin, image is mutable even if owner does not match
|
||||||
self.context.is_admin = True
|
self.context.is_admin = True
|
||||||
@ -391,8 +402,10 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
self.policy.modify_image()
|
self.policy.modify_image()
|
||||||
m.assert_called_once_with(self.context, self.image)
|
m.assert_called_once_with(self.context, self.image)
|
||||||
|
|
||||||
# Make sure we are not checking it if enforce_secure_rbac=True
|
# Make sure we are not checking it if enforce_new_defaults=True and
|
||||||
self.config(enforce_secure_rbac=True)
|
# enforce_scope=True
|
||||||
|
self.config(enforce_new_defaults=True, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=True, group='oslo_policy')
|
||||||
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
||||||
self.policy.modify_image()
|
self.policy.modify_image()
|
||||||
self.assertFalse(m.called)
|
self.assertFalse(m.called)
|
||||||
@ -404,7 +417,8 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
mock.ANY)
|
mock.ANY)
|
||||||
|
|
||||||
def test_deactivate_image_falls_back_to_legacy(self):
|
def test_deactivate_image_falls_back_to_legacy(self):
|
||||||
self.config(enforce_secure_rbac=False)
|
self.config(enforce_new_defaults=False, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=False, group='oslo_policy')
|
||||||
|
|
||||||
# As admin, image is mutable even if owner does not match
|
# As admin, image is mutable even if owner does not match
|
||||||
self.context.is_admin = True
|
self.context.is_admin = True
|
||||||
@ -428,8 +442,10 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
self.policy.deactivate_image()
|
self.policy.deactivate_image()
|
||||||
m.assert_called_once_with(self.context, self.image)
|
m.assert_called_once_with(self.context, self.image)
|
||||||
|
|
||||||
# Make sure we are not checking it if enforce_secure_rbac=True
|
# Make sure we are not checking it if enforce_new_defaults=Truei and
|
||||||
self.config(enforce_secure_rbac=True)
|
# enforce_scope=True
|
||||||
|
self.config(enforce_new_defaults=True, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=True, group='oslo_policy')
|
||||||
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
||||||
self.policy.deactivate_image()
|
self.policy.deactivate_image()
|
||||||
self.assertFalse(m.called)
|
self.assertFalse(m.called)
|
||||||
@ -441,7 +457,8 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
mock.ANY)
|
mock.ANY)
|
||||||
|
|
||||||
def test_reactivate_image_falls_back_to_legacy(self):
|
def test_reactivate_image_falls_back_to_legacy(self):
|
||||||
self.config(enforce_secure_rbac=False)
|
self.config(enforce_new_defaults=False, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=False, group='oslo_policy')
|
||||||
|
|
||||||
# As admin, image is mutable even if owner does not match
|
# As admin, image is mutable even if owner does not match
|
||||||
self.context.is_admin = True
|
self.context.is_admin = True
|
||||||
@ -465,8 +482,10 @@ class APIImagePolicy(APIPolicyBase):
|
|||||||
self.policy.reactivate_image()
|
self.policy.reactivate_image()
|
||||||
m.assert_called_once_with(self.context, self.image)
|
m.assert_called_once_with(self.context, self.image)
|
||||||
|
|
||||||
# Make sure we are not checking it if enforce_secure_rbac=True
|
# Make sure we are not checking it if enforce_new_defaults=True and
|
||||||
self.config(enforce_secure_rbac=True)
|
# enforce_scope=True
|
||||||
|
self.config(enforce_new_defaults=True, group='oslo_policy')
|
||||||
|
self.config(enforce_scope=True, group='oslo_policy')
|
||||||
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
with mock.patch('glance.api.v2.policy.check_is_image_mutable') as m:
|
||||||
self.policy.reactivate_image()
|
self.policy.reactivate_image()
|
||||||
self.assertFalse(m.called)
|
self.assertFalse(m.called)
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
As per the revised SRBAC community goals, glance service is switching to
|
||||||
|
new defaults by default in Antelope cycle, hence removing the deprecated
|
||||||
|
``enforce_secure_rbac`` option which is no longer needed.
|
||||||
|
The ``enforce_secure_rbac`` option was introduced EXPERIMENTAL in Wallaby
|
||||||
|
release for operators to opt into enforcing authorization based on common
|
||||||
|
RBAC personas.
|
||||||
|
|
||||||
|
Now operator can control the scope and new defaults flag with the below
|
||||||
|
config options in
|
||||||
|
``glance-api.conf`` file::
|
||||||
|
|
||||||
|
[oslo_policy]
|
||||||
|
enforce_new_defaults=True
|
||||||
|
enforce_scope=True
|
Loading…
Reference in New Issue
Block a user