summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPranali Deore <pdeore@redhat.com>2023-02-02 10:24:00 +0000
committerPranali Deore <pdeore@redhat.com>2023-02-16 11:11:31 +0000
commit8c04d19e8858594fe687f555c9be99ce6b16dc16 (patch)
tree49cbcfcac21d83a053e180d6334d0202261caad8
parent81da9ccbdee88e77f06e42c4f121b68cf2c1389e (diff)
downloadglance-8c04d19e8858594fe687f555c9be99ce6b16dc16.tar.gz
Enabled new defaults and scope checks by default
Enabling the enforce scope and new defaults by default in glance Related blueprint secure-rbac Change-Id: I0808dc0b1b34b527e38aa137c1dd25e1fc06409f
-rw-r--r--.zuul.yaml18
-rw-r--r--glance/api/policy.py12
-rw-r--r--glance/common/config.py2
-rw-r--r--glance/tests/functional/__init__.py5
-rw-r--r--glance/tests/unit/test_cache_middleware.py3
-rw-r--r--glance/tests/unit/test_policy.py3
-rw-r--r--glance/tests/unit/utils.py9
-rw-r--r--glance/tests/unit/v2/test_image_data_resource.py70
-rw-r--r--glance/tests/unit/v2/test_image_members_resource.py22
-rw-r--r--glance/tests/unit/v2/test_images_resource.py61
-rw-r--r--releasenotes/notes/enable-enforce-scope-and-new-defaults-ef543183e6c2eabb.yaml14
-rw-r--r--requirements.txt2
12 files changed, 177 insertions, 44 deletions
diff --git a/.zuul.yaml b/.zuul.yaml
index 04836e2fe..f04d00b38 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -289,6 +289,20 @@
glance_store:
rbd_thin_provisioning: True
+# TODO(pdeore): Remove this jobs once all the glance jobs will be tested
+# with new RBAC in integrated way and we do not need this separate job.
+- job:
+ name: tempest-integrated-storage-enforce-scope-new-defaults
+ parent: tempest-integrated-storage
+ description: |
+ This job runs the Tempest tests with scope and new defaults enabled
+ Glance services.
+ vars:
+ devstack_localrc:
+ NOVA_ENFORCE_SCOPE: true
+ CINDER_ENFORCE_SCOPE: true
+ GLANCE_ENFORCE_SCOPE: true
+
- project:
templates:
- check-requirements
@@ -319,6 +333,8 @@
- ^\.zuul\.yaml$
- tempest-integrated-storage:
irrelevant-files: *tempest-irrelevant-files
+ - tempest-integrated-storage-enforce-scope-new-defaults:
+ irrelevant-files: *tempest-irrelevant-files
- tempest-integrated-storage-import:
irrelevant-files: *tempest-irrelevant-files
- tempest-integrated-storage-import-standalone:
@@ -339,6 +355,8 @@
- openstack-tox-functional-py39
- tempest-integrated-storage:
irrelevant-files: *tempest-irrelevant-files
+ - tempest-integrated-storage-enforce-scope-new-defaults:
+ irrelevant-files: *tempest-irrelevant-files
- tempest-integrated-storage-import:
irrelevant-files: *tempest-irrelevant-files
- tempest-integrated-storage-import-standalone:
diff --git a/glance/api/policy.py b/glance/api/policy.py
index 605b8118c..d92d4df6d 100644
--- a/glance/api/policy.py
+++ b/glance/api/policy.py
@@ -34,11 +34,15 @@ CONF = cfg.CONF
_ENFORCER = None
-# TODO(gmann): Remove setting the default value of config policy_file
-# once oslo_policy change the default value to 'policy.yaml'.
-# https://github.com/openstack/oslo.policy/blob/a626ad12fe5a3abd49d70e3e5b95589d279ab578/oslo_policy/opts.py#L49
+# TODO(gmann): Remove overriding the default value of config options
+# 'policy_file', 'enforce_scope', and 'enforce_new_defaults' once
+# oslo_policy change their default value to what is overridden here.
DEFAULT_POLICY_FILE = 'policy.yaml'
-opts.set_defaults(cfg.CONF, DEFAULT_POLICY_FILE)
+opts.set_defaults(
+ cfg.CONF,
+ DEFAULT_POLICY_FILE,
+ enforce_scope=True,
+ enforce_new_defaults=True)
class Enforcer(policy.Enforcer):
diff --git a/glance/common/config.py b/glance/common/config.py
index 7891daccf..cff15ab1d 100644
--- a/glance/common/config.py
+++ b/glance/common/config.py
@@ -593,7 +593,7 @@ Related options:
Related options:
* [DEFAULT]/node_staging_uri""")),
- cfg.BoolOpt('enforce_secure_rbac', default=False,
+ 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
diff --git a/glance/tests/functional/__init__.py b/glance/tests/functional/__init__.py
index cbdcfe4bb..a17c67c39 100644
--- a/glance/tests/functional/__init__.py
+++ b/glance/tests/functional/__init__.py
@@ -585,6 +585,9 @@ class ApiServerForMultipleBackend(Server):
self.image_location_quota = 2
self.disable_path = None
+ self.enforce_secure_rbac = True
+ self.enforce_new_defaults = True
+
self.needs_database = True
default_sql_connection = SQLITE_CONN_TEMPLATE % self.test_dir
self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION',
@@ -626,9 +629,11 @@ image_location_quota=%(image_location_quota)s
location_strategy=%(location_strategy)s
allow_additional_image_properties = True
enabled_backends=file1:file,file2:file,file3:file
+enforce_secure_rbac=%(enforce_secure_rbac)s
[oslo_policy]
policy_file = %(policy_file)s
policy_default_rule = %(policy_default_rule)s
+enforce_new_defaults=%(enforce_new_defaults)s
[paste_deploy]
flavor = %(deployment_flavor)s
[store_type_location_strategy]
diff --git a/glance/tests/unit/test_cache_middleware.py b/glance/tests/unit/test_cache_middleware.py
index 034edc4b1..39288b821 100644
--- a/glance/tests/unit/test_cache_middleware.py
+++ b/glance/tests/unit/test_cache_middleware.py
@@ -409,7 +409,8 @@ class TestCacheMiddlewareProcessResponse(base.IsolatedUnitTest):
rules = {
"restricted":
"not ('test_1234':%(x_test_key)s and role:_member_)",
- "download_image": "role:admin or rule:restricted"
+ "download_image": "role:admin or rule:restricted",
+ "get_image": ""
}
self.set_policy_rules(rules)
cache_filter.policy = glance.api.policy.Enforcer(
diff --git a/glance/tests/unit/test_policy.py b/glance/tests/unit/test_policy.py
index 70ad783e7..9f26d0e29 100644
--- a/glance/tests/unit/test_policy.py
+++ b/glance/tests/unit/test_policy.py
@@ -320,7 +320,8 @@ class TestPolicyEnforcer(base.IsolatedUnitTest):
self.assertEqual(False, enforcer.check(context, 'get_image', {}))
def test_policy_file_get_image_default_everybody(self):
- rules = {"default": ''}
+ rules = {"default": '',
+ "get_image": ''}
self.set_policy_rules(rules)
enforcer = glance.api.policy.Enforcer(
diff --git a/glance/tests/unit/utils.py b/glance/tests/unit/utils.py
index 3cbb51dbc..16640a9c1 100644
--- a/glance/tests/unit/utils.py
+++ b/glance/tests/unit/utils.py
@@ -20,6 +20,7 @@ from unittest import mock
import urllib
from oslo_config import cfg
+from oslo_policy import policy
from glance.async_.flows._internal_plugins import base_download
from glance.common import exception
@@ -87,6 +88,14 @@ def get_fake_request(path='', method='POST', is_admin=False, user=USER1,
return req
+def enforcer_from_rules(unparsed_rules):
+ rules = policy.Rules.from_dict(unparsed_rules)
+ enforcer = glance.api.policy.Enforcer(
+ suppress_deprecation_warnings=True)
+ enforcer.set_rules(rules, overwrite=True)
+ return enforcer
+
+
def fake_get_size_from_backend(uri, context=None):
return 1
diff --git a/glance/tests/unit/v2/test_image_data_resource.py b/glance/tests/unit/v2/test_image_data_resource.py
index 3889c2f63..4ed96a1c3 100644
--- a/glance/tests/unit/v2/test_image_data_resource.py
+++ b/glance/tests/unit/v2/test_image_data_resource.py
@@ -135,7 +135,7 @@ class TestImagesController(base.StoreClearingUnitTest):
self.addCleanup(patcher.stop)
def test_download(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd',
locations=[{'url': 'http://example.com/image',
'metadata': {}, 'status': 'active'}])
@@ -156,7 +156,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def test_download_no_location(self):
# NOTE(mclaren): NoContent will be raised by the ResponseSerializer
# That's tested below.
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
self.image_repo.result = FakeImage('abcd')
image = self.controller.download(request, unit_test_utils.UUID2)
self.assertEqual('abcd', image.image_id)
@@ -179,7 +179,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def __len__(self):
raise exception.Forbidden()
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd')
self.image_repo.result = image
image.locations = ImageLocations()
@@ -187,7 +187,7 @@ class TestImagesController(base.StoreClearingUnitTest):
self.assertEqual('abcd', image.image_id)
def test_upload(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd', owner='tenant1')
self.image_repo.result = image
self.controller.upload(request, unit_test_utils.UUID2, 'YYYY', 4)
@@ -217,7 +217,7 @@ class TestImagesController(base.StoreClearingUnitTest):
self.assertTrue(mock_enf.called)
def test_upload_status(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd')
self.image_repo.result = image
insurance = {'called': False}
@@ -234,7 +234,7 @@ class TestImagesController(base.StoreClearingUnitTest):
self.image_repo.saved_image.status)
def test_upload_no_size(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd')
self.image_repo.result = image
self.controller.upload(request, unit_test_utils.UUID2, 'YYYY', None)
@@ -256,7 +256,7 @@ class TestImagesController(base.StoreClearingUnitTest):
mock_enforce.assert_has_calls(expected_call)
def test_upload_invalid(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd')
image.status = ValueError()
self.image_repo.result = image
@@ -270,7 +270,7 @@ class TestImagesController(base.StoreClearingUnitTest):
mocked_save = mock.Mock(side_effect=side_effect)
mocked_delete = mock.Mock()
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd')
image.delete = mocked_delete
self.image_repo.result = image
@@ -287,7 +287,7 @@ class TestImagesController(base.StoreClearingUnitTest):
mocked_save.side_effect = [lambda *a: None,
exception.NotAuthenticated(),
lambda *a: None]
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
request.environ['keystone.token_info'] = {
'token': {
'roles': [{'name': 'member'}]
@@ -309,7 +309,8 @@ class TestImagesController(base.StoreClearingUnitTest):
raise exception.Conflict()
for fun in [fake_save_not_found, fake_save_conflict]:
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(
+ roles=['admin', 'member'])
image = FakeImage('abcd', locations=['http://example.com/image'])
self.image_repo.result = image
self.image_repo.save = fun
@@ -325,7 +326,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def fake_delete():
raise exception.ImageNotFound()
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd', locations=['http://example.com/image'])
self.image_repo.result = image
self.image_repo.save = fake_save
@@ -340,7 +341,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def fake_delete():
raise exception.ImageNotFound()
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd', locations=['http://example.com/image'])
self.image_repo.result = image
self.image_repo.save = fake_save
@@ -355,7 +356,7 @@ class TestImagesController(base.StoreClearingUnitTest):
request, str(uuid.uuid4()), 'ABC', 3)
def test_upload_data_exists(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage()
exc = exception.InvalidImageStatusTransition(cur_status='active',
new_status='queued')
@@ -365,7 +366,7 @@ class TestImagesController(base.StoreClearingUnitTest):
request, unit_test_utils.UUID1, 'YYYY', 4)
def test_upload_storage_full(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage()
image.set_data = Raise(glance_store.StorageFull)
self.image_repo.result = image
@@ -374,7 +375,7 @@ class TestImagesController(base.StoreClearingUnitTest):
request, unit_test_utils.UUID2, 'YYYYYYY', 7)
def test_upload_signature_verification_fails(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage()
image.set_data = Raise(cursive_exception.SignatureVerificationError)
self.image_repo.result = image
@@ -383,7 +384,7 @@ class TestImagesController(base.StoreClearingUnitTest):
self.assertEqual('queued', self.image_repo.saved_image.status)
def test_image_size_limit_exceeded(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage()
image.set_data = Raise(exception.ImageSizeLimitExceeded)
self.image_repo.result = image
@@ -399,7 +400,8 @@ class TestImagesController(base.StoreClearingUnitTest):
request, unit_test_utils.UUID1, 'YYYYYYY', 7)
def test_upload_storage_forbidden(self):
- request = unit_test_utils.get_fake_request(user=unit_test_utils.USER2)
+ request = unit_test_utils.get_fake_request(
+ user=unit_test_utils.USER2, roles=['admin', 'member'])
image = FakeImage()
image.set_data = Raise(exception.Forbidden)
self.image_repo.result = image
@@ -414,7 +416,8 @@ class TestImagesController(base.StoreClearingUnitTest):
request, unit_test_utils.UUID1, 'ABC', 3)
def test_upload_storage_write_denied(self):
- request = unit_test_utils.get_fake_request(user=unit_test_utils.USER3)
+ request = unit_test_utils.get_fake_request(
+ user=unit_test_utils.USER3, roles=['admin', 'member'])
image = FakeImage()
image.set_data = Raise(glance_store.StorageWriteDenied)
self.image_repo.result = image
@@ -424,7 +427,8 @@ class TestImagesController(base.StoreClearingUnitTest):
def test_upload_storage_store_disabled(self):
"""Test that uploading an image file raises StoreDisabled exception"""
- request = unit_test_utils.get_fake_request(user=unit_test_utils.USER3)
+ request = unit_test_utils.get_fake_request(
+ user=unit_test_utils.USER3, roles=['admin', 'member'])
image = FakeImage()
image.set_data = Raise(glance_store.StoreAddDisabled)
self.image_repo.result = image
@@ -484,7 +488,7 @@ class TestImagesController(base.StoreClearingUnitTest):
self.assertEqual(activate_log, output_log[2])
def test_restore_image_when_upload_failed(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('fake')
image.set_data = Raise(glance_store.StorageWriteDenied)
self.image_repo.result = image
@@ -496,7 +500,7 @@ class TestImagesController(base.StoreClearingUnitTest):
@mock.patch.object(filesystem.Store, 'add')
def test_restore_image_when_staging_failed(self, mock_store_add):
mock_store_add.side_effect = glance_store.StorageWriteDenied()
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image_id = str(uuid.uuid4())
image = FakeImage('fake')
self.image_repo.result = image
@@ -507,7 +511,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def test_stage(self):
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage(image_id=image_id)
self.image_repo.result = image
with mock.patch.object(filesystem.Store, 'add') as mock_add:
@@ -518,7 +522,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def test_image_already_on_staging(self):
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage(image_id=image_id)
self.image_repo.result = image
with mock.patch.object(filesystem.Store, 'add') as mock_store_add:
@@ -534,7 +538,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def test_image_stage_raises_bad_store_uri(self, mock_store_configure):
mock_store_configure.side_effect = AttributeError()
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
self.assertRaises(exception.BadStoreUri, self.controller.stage,
request, image_id, 'YYYY', 4)
@@ -542,7 +546,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def test_image_stage_raises_storage_full(self, mock_store_add):
mock_store_add.side_effect = glance_store.StorageFull()
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage(image_id=image_id)
self.image_repo.result = image
with mock.patch.object(self.controller, "_unstage"):
@@ -554,7 +558,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def test_image_stage_raises_storage_quota_full(self, mock_store_add):
mock_store_add.side_effect = exception.StorageQuotaFull("message")
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage(image_id=image_id)
self.image_repo.result = image
with mock.patch.object(self.controller, "_unstage"):
@@ -566,7 +570,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def test_image_stage_raises_storage_write_denied(self, mock_store_add):
mock_store_add.side_effect = glance_store.StorageWriteDenied()
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage(image_id=image_id)
self.image_repo.result = image
with mock.patch.object(self.controller, "_unstage"):
@@ -592,7 +596,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def test_image_stage_raises_image_size_exceeded(self, mock_store_add):
mock_store_add.side_effect = exception.ImageSizeLimitExceeded()
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage(image_id=image_id)
self.image_repo.result = image
with mock.patch.object(self.controller, "_unstage"):
@@ -603,7 +607,7 @@ class TestImagesController(base.StoreClearingUnitTest):
@mock.patch.object(filesystem.Store, 'add')
def test_image_stage_invalid_image_transition(self, mock_store_add):
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage(image_id=image_id)
self.image_repo.result = image
with mock.patch.object(filesystem.Store, 'add') as mock_add:
@@ -619,7 +623,7 @@ class TestImagesController(base.StoreClearingUnitTest):
def _test_image_stage_records_host(self, expected_url):
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage(image_id=image_id)
self.image_repo.result = image
with mock.patch.object(filesystem.Store, 'add') as mock_add:
@@ -651,7 +655,7 @@ class TestImagesController(base.StoreClearingUnitTest):
# image staged.
self.config(public_endpoint='http://worker1.example.com')
image_id = str(uuid.uuid4())
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage(image_id=image_id)
self.image_repo.result = image
exc_cls = glance_store.exceptions.StorageFull
@@ -732,7 +736,7 @@ class TestImageDataDeserializer(test_utils.BaseTestCase):
self.deserializer.upload, request)
def test_stage(self):
- req = unit_test_utils.get_fake_request()
+ req = unit_test_utils.get_fake_request(roles=['admin', 'member'])
req.headers['Content-Type'] = 'application/octet-stream'
req.headers['Content-Length'] = 4
req.body_file = io.BytesIO(b'YYYY')
@@ -1078,7 +1082,7 @@ class TestMultiBackendImagesController(base.MultiStoreClearingUnitTest):
self.addCleanup(patcher.stop)
def test_upload(self):
- request = unit_test_utils.get_fake_request()
+ request = unit_test_utils.get_fake_request(roles=['admin', 'member'])
image = FakeImage('abcd')
self.image_repo.result = image
self.controller.upload(request, unit_test_utils.UUID2, 'YYYY', 4)
diff --git a/glance/tests/unit/v2/test_image_members_resource.py b/glance/tests/unit/v2/test_image_members_resource.py
index 457b8505d..7287a3b5d 100644
--- a/glance/tests/unit/v2/test_image_members_resource.py
+++ b/glance/tests/unit/v2/test_image_members_resource.py
@@ -316,6 +316,11 @@ class TestImageMembersController(test_utils.BaseTestCase):
self.assertEqual('accepted', output.status)
def test_update_done_by_owner(self):
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "modify_image": "'{0}':%(owner)s".format(TENANT1)
+ })
+ self.controller.policy = enforcer
request = unit_test_utils.get_fake_request(tenant=TENANT1)
self.assertRaises(webob.exc.HTTPForbidden, self.controller.update,
request, UUID2, TENANT4, status='accepted')
@@ -331,6 +336,10 @@ class TestImageMembersController(test_utils.BaseTestCase):
request, UUID2, TENANT4, status='accept')
def test_create_private_image(self):
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ })
+ self.controller.policy = enforcer
request = unit_test_utils.get_fake_request()
self.assertRaises(webob.exc.HTTPForbidden, self.controller.create,
request, UUID4, TENANT2)
@@ -359,7 +368,14 @@ class TestImageMembersController(test_utils.BaseTestCase):
self.assertEqual([], found_member)
def test_delete_by_member(self):
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "delete_member": "'{0}':%(owner)s".format(TENANT4),
+ "get_members": "",
+ "get_member": ""
+ })
request = unit_test_utils.get_fake_request(tenant=TENANT4)
+ self.controller.policy = enforcer
self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete,
request, UUID2, TENANT4)
request = unit_test_utils.get_fake_request()
@@ -395,6 +411,12 @@ class TestImageMembersController(test_utils.BaseTestCase):
request, UUID2, TENANT4)
def test_delete_private_image(self):
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "delete_member": "'{0}':%(owner)s".format(TENANT1),
+ "get_member": ""
+ })
+ self.controller.policy = enforcer
request = unit_test_utils.get_fake_request()
self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete,
request, UUID4, TENANT1)
diff --git a/glance/tests/unit/v2/test_images_resource.py b/glance/tests/unit/v2/test_images_resource.py
index 203092554..733e644e8 100644
--- a/glance/tests/unit/v2/test_images_resource.py
+++ b/glance/tests/unit/v2/test_images_resource.py
@@ -1253,17 +1253,25 @@ class TestImagesController(base.IsolatedUnitTest):
tags=tags)
def test_create_with_owner_non_admin(self):
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "add_image": "role:member,reader",
+ })
request = unit_test_utils.get_fake_request()
request.context.is_admin = False
image = {'owner': '12345'}
+ self.controller.policy = enforcer
self.assertRaises(webob.exc.HTTPForbidden,
self.controller.create,
request, image=image, extra_properties={},
tags=[])
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "add_image": "'{0}':%(owner)s".format(TENANT1),
+ })
request = unit_test_utils.get_fake_request()
request.context.is_admin = False
image = {'owner': TENANT1}
+ self.controller.policy = enforcer
output = self.controller.create(request, image=image,
extra_properties={}, tags=[])
self.assertEqual(TENANT1, output.owner)
@@ -1616,7 +1624,7 @@ class TestImagesController(base.IsolatedUnitTest):
enforcer,
self.notifier,
self.store)
- request = unit_test_utils.get_fake_request(roles=['spl_role'])
+ request = unit_test_utils.get_fake_request(roles=['spl_role', 'admin'])
image = {'name': 'image-1'}
extra_props = {'spl_creator_policy': 'bar'}
created_image = self.controller.create(request, image=image,
@@ -1629,8 +1637,19 @@ class TestImagesController(base.IsolatedUnitTest):
changes = [
{'op': 'replace', 'path': ['spl_creator_policy'], 'value': 'par'},
]
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "modify_image": "role:spl_role"
+ })
+
+ self.controller.policy = enforcer
self.assertRaises(webob.exc.HTTPForbidden, self.controller.update,
another_request, created_image.image_id, changes)
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "modify_image": "role:admin"
+ })
+ self.controller.policy = enforcer
another_request = unit_test_utils.get_fake_request(roles=['admin'])
output = self.controller.update(another_request,
created_image.image_id, changes)
@@ -1655,9 +1674,19 @@ class TestImagesController(base.IsolatedUnitTest):
changes = [
{'op': 'add', 'path': ['spl_creator_policy'], 'value': 'bar'},
]
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "modify_image": "role:fake_role"
+ })
+
+ self.controller.policy = enforcer
self.assertRaises(webob.exc.HTTPForbidden, self.controller.update,
another_request, created_image.image_id, changes)
-
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "modify_image": "role:member"
+ })
+ self.controller.policy = enforcer
another_request = unit_test_utils.get_fake_request(roles=['member',
'spl_role'])
output = self.controller.update(another_request,
@@ -1679,6 +1708,11 @@ class TestImagesController(base.IsolatedUnitTest):
extra_properties={},
tags=[])
roles = ['fake_member']
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "modify_image": "role:fake_member"
+ })
+ self.controller.policy = enforcer
another_request = unit_test_utils.get_fake_request(roles=roles)
changes = [
{'op': 'add', 'path': ['x_owner_foo'], 'value': 'bar'},
@@ -1762,6 +1796,11 @@ class TestImagesController(base.IsolatedUnitTest):
created_image = self.controller.create(request, image=image,
extra_properties=extra_props,
tags=[])
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "modify_image": "role:fake_role"
+ })
+ self.controller.policy = enforcer
another_request = unit_test_utils.get_fake_request(roles=['fake_role'])
changes = [
{'op': 'replace', 'path': ['x_owner_foo'], 'value': 'baz'},
@@ -1806,6 +1845,11 @@ class TestImagesController(base.IsolatedUnitTest):
created_image = self.controller.create(request, image=image,
extra_properties=extra_props,
tags=[])
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "modify_image": "role:fake_role"
+ })
+ self.controller.policy = enforcer
another_request = unit_test_utils.get_fake_request(roles=['fake_role'])
changes = [
{'op': 'remove', 'path': ['x_owner_foo']}
@@ -3420,7 +3464,12 @@ class TestImagesController(base.IsolatedUnitTest):
def test_image_import_not_allowed(self, mock_get, mock_new_task):
# NOTE(danms): FakeImage is owned by utils.TENANT1. Try to do the
# import as TENANT2 and we should get an HTTPForbidden
- request = unit_test_utils.get_fake_request(tenant=TENANT2)
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "modify_image": "'{0}':%(owner)s".format(TENANT2)
+ })
+ request = unit_test_utils.get_fake_request()
+ self.controller.policy = enforcer
mock_get.return_value = FakeImage(status='uploading')
self.assertRaises(webob.exc.HTTPForbidden,
self.controller.import_image,
@@ -6008,7 +6057,13 @@ class TestMultiImagesController(base.MultiIsolatedUnitTest):
{'method': {'name': 'glance-direct'}})
def test_delete_from_store_as_non_owner(self):
+ enforcer = unit_test_utils.enforcer_from_rules({
+ "get_image": "",
+ "delete_image_location": "'TENANT4':%(owner)s",
+ "get_image_location": ""
+ })
request = unit_test_utils.get_fake_request()
+ self.controller.policy = enforcer
self.assertRaises(webob.exc.HTTPForbidden,
self.controller.delete_from_store,
request,
diff --git a/releasenotes/notes/enable-enforce-scope-and-new-defaults-ef543183e6c2eabb.yaml b/releasenotes/notes/enable-enforce-scope-and-new-defaults-ef543183e6c2eabb.yaml
new file mode 100644
index 000000000..dcfdf7a7e
--- /dev/null
+++ b/releasenotes/notes/enable-enforce-scope-and-new-defaults-ef543183e6c2eabb.yaml
@@ -0,0 +1,14 @@
+---
+upgrade:
+ - |
+ The Glance service enables the API policies (RBAC) new defaults and scope by
+ default. The Default value of config options ``[oslo_policy] enforce_scope``
+ and ``[oslo_policy] oslo_policy.enforce_new_defaults`` have been changed
+ to ``True``.
+
+ If you want to disable them then modify the below config options value in
+ ``glance-api.conf`` file::
+
+ [oslo_policy]
+ enforce_new_defaults=False
+ enforce_scope=False
diff --git a/requirements.txt b/requirements.txt
index 0554a3647..3e823077a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -41,7 +41,7 @@ oslo.log>=4.5.0 # Apache-2.0
oslo.messaging>=5.29.0,!=9.0.0 # Apache-2.0
oslo.middleware>=3.31.0 # Apache-2.0
oslo.reports>=1.18.0 # Apache-2.0
-oslo.policy>=3.8.1 # Apache-2.0
+oslo.policy>=3.11.0 # Apache-2.0
retrying!=1.3.0,>=1.2.3 # Apache-2.0
osprofiler>=1.4.0 # Apache-2.0