Make image location ops policy configurable

Some users may not want *_image_location operations to be
restricted to role:admin so this patch allows that to be
configurable and sets the default to be False since
enabling this by default is breaking RBD COW clones in
Nova for non-admin users (and anywhere else that relies
on that information).

Change-Id: I8c293d6036bc1d6104dab5458f6915968459a09e
Closes-Bug: #1786144
This commit is contained in:
Edward Hope-Morley 2018-08-31 15:25:27 +01:00
parent 097d322b89
commit 9e2af26b6d
3 changed files with 45 additions and 2 deletions

@ -126,6 +126,18 @@ options:
Expose underlying image locations via the API when using Ceph for image Expose underlying image locations via the API when using Ceph for image
storage. Only disable this option if you do not wish to use storage. Only disable this option if you do not wish to use
copy-on-write clones of RAW format images with Ceph in Cinder and Nova. copy-on-write clones of RAW format images with Ceph in Cinder and Nova.
restrict-image-location-operations:
type: boolean
default: False
description: |
If this is set to True, all *_image_location operations in the Glance api
will be restricted to role:admin which will result in non-admin users no
longer being able to view the "locations" information for an image.
This only affects environments that have expose-image-locations set to
True.
WARNING: enabling this restriction will cause Nova to no longer be able
to create COW clones or snapshots for non-admin users when using the
RBDImageBackend in the nova-compute charm.
rabbit-user: rabbit-user:
type: string type: string
default: glance default: glance

@ -562,7 +562,11 @@ def update_image_location_policy():
log("key '{}' not found in policy file".format(policy_key), log("key '{}' not found in policy file".format(policy_key),
level=INFO) level=INFO)
policy_value = 'role:admin' if config('restrict-image-location-operations'):
policy_value = 'role:admin'
else:
policy_value = ''
log("Updating Glance policy file setting policy " log("Updating Glance policy file setting policy "
"'{}':'{}'".format(policy_key, policy_value), level=INFO) "'{}':'{}'".format(policy_key, policy_value), level=INFO)
update_json_file(GLANCE_POLICY_FILE, {policy_key: policy_value}) update_json_file(GLANCE_POLICY_FILE, {policy_key: policy_value})

@ -297,13 +297,19 @@ class TestGlanceUtils(CharmTestCase):
def test_is_api_ready_false(self): def test_is_api_ready_false(self):
self._test_is_api_ready(False) self._test_is_api_ready(False)
@patch.object(utils, 'config')
@patch.object(utils, 'json') @patch.object(utils, 'json')
@patch.object(utils, 'update_json_file') @patch.object(utils, 'update_json_file')
@patch.object(utils, 'kv') @patch.object(utils, 'kv')
@patch.object(utils, 'os_release') @patch.object(utils, 'os_release')
def test_update_image_location_policy(self, mock_os_release, mock_kv, def test_update_image_location_policy(self, mock_os_release, mock_kv,
mock_update_json_file, mock_json): mock_update_json_file, mock_json,
mock_config):
db_vals = {} db_vals = {}
config = {'restrict-image-location-operations': False}
def fake_config(key):
return config.get(key)
def fake_db_get(key): def fake_db_get(key):
return db_vals.get(key) return db_vals.get(key)
@ -313,6 +319,8 @@ class TestGlanceUtils(CharmTestCase):
db_obj.get.side_effect = fake_db_get db_obj.get.side_effect = fake_db_get
db_obj.set = MagicMock() db_obj.set = MagicMock()
mock_config.side_effect = fake_config
fake_open = mock_open() fake_open = mock_open()
with patch.object(utils, 'open', fake_open, create=True): with patch.object(utils, 'open', fake_open, create=True):
mock_json.loads.return_value = {'get_image_location': '', mock_json.loads.return_value = {'get_image_location': '',
@ -326,6 +334,25 @@ class TestGlanceUtils(CharmTestCase):
mock_os_release.return_value = 'kilo' mock_os_release.return_value = 'kilo'
utils.update_image_location_policy() utils.update_image_location_policy()
self.assertTrue(mock_kv.called) self.assertTrue(mock_kv.called)
mock_update_json_file.assert_has_calls([
call('/etc/glance/policy.json',
{'get_image_location': ''}),
call('/etc/glance/policy.json',
{'set_image_location': ''}),
call('/etc/glance/policy.json',
{'delete_image_location': ''})])
mock_update_json_file.reset_mock()
config['restrict-image-location-operations'] = True
utils.update_image_location_policy()
mock_update_json_file.assert_has_calls([
call('/etc/glance/policy.json',
{'get_image_location': 'role:admin'}),
call('/etc/glance/policy.json',
{'set_image_location': 'role:admin'}),
call('/etc/glance/policy.json',
{'delete_image_location': 'role:admin'})])
db_obj.get.assert_has_calls([call('policy_get_image_location'), db_obj.get.assert_has_calls([call('policy_get_image_location'),
call('policy_set_image_location'), call('policy_set_image_location'),
call('policy_delete_image_location')]) call('policy_delete_image_location')])