Inject os_glance.* section in the property protection file

Users who use a property protection file and use either the import
workflow or the metadata injection plugin will get a
glance.common.exception.ReservedProperty exception because we try to add
os_glance_* properties to their images.

To work around this issue, users could add the following lines to their
property protection file:

[os_glance.*]
create = @
read = @
update = @
delete = @

However, it is not something users should have to do. This patch
automatically injects this section into the config we read from the
property protection file.

Change-Id: Iea2fffa75b973b5a34da6fc4145841888ea19034
Closes-Bug: #2085321
Signed-off-by: Cyril Roelandt <cyril@redhat.com>
This commit is contained in:
Cyril Roelandt
2025-10-22 01:41:51 +02:00
parent ffd134553f
commit 613cc42a39
3 changed files with 85 additions and 2 deletions

View File

@@ -13,6 +13,7 @@
# under the License.
import configparser
import io
import re
from oslo_config import cfg
@@ -108,10 +109,51 @@ class PropertyRules(object):
self.prop_prot_rule_format = self.prop_prot_rule_format.lower()
self._load_rules()
def _inject_os_glance_section(self):
# Inject an 'os_glance.*' section to work around bug #2085321.
# https://bugs.launchpad.net/glance/+bug/2085321
# An exception will be raised if a property protection file is in
# use and does not contain the os_glance.* section. Since this is
# internal to Glance, the users should not have to specify that
# section in the config file themselves. We therefore inject it
# here on their behalf.
#
# We also remove all sections starting with 'os_glance' since the
# keyword is reserved for internal use.
#
# See:
# glance/tests/etc/property-protections-policies.conf
# glance/tests/etc/property-protections.conf
global CONFIG
for section in CONFIG.sections():
if section.startswith('os_glance'):
CONFIG.remove_section(section)
# We want to insert the [os_glance.*] section at the top of the config,
# so it is not shadowed by sections such as [.*]. To do this, we:
# 1) Dump the user config into a StringIO
# 2) Init a new ConfigParser object
# 3) Read our [os_glance.*] section
# 4) Read the user config
txt_config = io.StringIO()
CONFIG.write(txt_config)
CONFIG = configparser.ConfigParser()
CONFIG.read_dict({
'os_glance.*': {
'create': '@',
'read': '@',
'update': '@',
'delete': '@',
}
})
CONFIG.read_string(txt_config.getvalue())
def _load_rules(self):
try:
conf_file = CONF.find_file(CONF.property_protection_file)
CONFIG.read(conf_file)
self._inject_os_glance_section()
except Exception as e:
msg = (_LE("Couldn't find property protection file %(file)s: "
"%(error)s.") % {'file': CONF.property_protection_file,

View File

@@ -20,6 +20,7 @@ import glance.context
from glance.tests.unit import base
CONFIG_SECTIONS = [
'os_glance.*', # Automatically injected at the top
'^x_owner_.*',
'spl_create_prop',
'spl_read_prop',
@@ -47,7 +48,40 @@ def create_context(policy, roles=None):
policy_enforcer=policy)
class TestPropertyRulesWithRoles(base.IsolatedUnitTest):
class TestPropertyRules():
def test_inject_os_glance(self):
'''Test that the os_glance.* section has been injected.'''
rules = {'x_foo': {'create': ['fake-role'],
'read': ['member'],
'update': ['fake-role'],
'delete': ['fake-role']},
'os_glance_store': {'create': '!',
'read': '!',
'update': '!',
'delete': '!'}}
self.set_property_protection_rules(rules)
self.rules_checker = property_utils.PropertyRules()
# The x_foo section should still be here
self.assertTrue(self.rules_checker.check_property_rules('x_foo',
'read', create_context(self.policy, ['member'])))
# The os_glance_store section should not have been here (users must not
# specify any section that starts with 'os_glance'. Our 'os_glance.*'
# section should now be here.
self.assertIn('os_glance.*', property_utils.CONFIG.sections())
self.assertNotIn('os_glance_store', property_utils.CONFIG.sections())
# And we should have the right permissions for all operations in the
# os_glance.* section.
context = create_context(self.policy, [''])
for operation in ['create', 'read', 'update', 'delete']:
self.assertTrue(
self.rules_checker.check_property_rules(
'os_glance.*', operation, context))
class TestPropertyRulesWithRoles(base.IsolatedUnitTest, TestPropertyRules):
def setUp(self):
super(TestPropertyRulesWithRoles, self).setUp()
@@ -321,7 +355,7 @@ class TestPropertyRulesWithRoles(base.IsolatedUnitTest):
create_context(self.policy, ['member'])))
class TestPropertyRulesWithPolicies(base.IsolatedUnitTest):
class TestPropertyRulesWithPolicies(base.IsolatedUnitTest, TestPropertyRules):
def setUp(self):
super(TestPropertyRulesWithPolicies, self).setUp()

View File

@@ -0,0 +1,7 @@
---
fixes:
- |
`Bug #2085321 <https://bugs.launchpad.net/glance/+bug/2085321>`_:
Fixed an issue that prevented users from using property protection files
and image import or the inject metadata plugin. A valid "os_glance.*"
section is now automatically added to the property protection file.