Support YAML oslo policy file in sm-api

The usage of JSON oslo policy files was deprecated in Victoria [1]. This
change converts the current policy file of sm-api to YAML and adds the
support to load YAML files to the internal implementation of the policy
parser.

The policy file was converted to YAML, using the tool provided by oslo
('oslopolicy-convert-json-to-yaml').

[1] https://docs.openstack.org/releasenotes/oslo.policy/victoria.html

Test Plan:
PASS: Deploy AIO-SX (over master branch).
      Check that the YAML files are present.
PASS: Check the YAML rules using the oslo tool 'oslopolicy-checker'.

Story: 2011360
Task: 53167

Change-Id: I0c9d129a1075f98ce001e47d75636e069037e6bc
Signed-off-by: Marcelo de Castro Loebens <Marcelo.DeCastroLoebens@windriver.com>
This commit is contained in:
Marcelo de Castro Loebens
2025-11-20 16:03:15 -04:00
parent 54c9662395
commit d161c09207
6 changed files with 37 additions and 21 deletions
+1 -1
View File
@@ -283,7 +283,7 @@ function install_sm_api {
sudo install -m 644 -D scripts/sm-api.service $STX_SYSCONFDIR/systemd/system
sudo install -m 644 -D scripts/sm_api.ini $STX_SM_CONF_DIR
sudo install -m 644 scripts/sm-api.conf $STX_SYSCONFDIR/pmon.d
sudo install -m 644 -D etc/sm-api/policy.json $STX_SM_API_CONF_DIR
sudo install -m 644 -D etc/sm-api/policy.yaml $STX_SM_API_CONF_DIR
popd
}
@@ -1,6 +1,6 @@
etc/init.d/sm-api
etc/sm/sm_api.ini
etc/sm-api/policy.json
etc/sm-api/policy.yaml
lib/systemd/system/*
usr/bin/sm-api
usr/lib/python3*
@@ -1,5 +0,0 @@
{
"admin": "role:admin or role:administrator",
"admin_api": "is_admin:True",
"default": "rule:admin_api"
}
@@ -0,0 +1,3 @@
"admin": "role:admin or role:administrator"
"admin_api": "is_admin:True"
"default": "rule:admin_api"
@@ -15,7 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2014,2018,2025 Wind River Systems, Inc.
#
@@ -32,8 +32,8 @@ from sm_api.openstack.common import policy
policy_opts = [
cfg.StrOpt('policy_file',
default='policy.json',
help=_('JSON file representing policy')),
default='policy.yaml',
help=_('The file representing policy')),
cfg.StrOpt('policy_default_rule',
default='default',
help=_('Rule checked when requested rule is not found')),
@@ -69,7 +69,7 @@ def init():
def _set_rules(data):
default_rule = CONF.policy_default_rule
policy.set_rules(policy.Rules.load_json(data, default_rule))
policy.set_rules(policy.Rules.load(data, default_rule))
def enforce(context, action, target, do_raise=True):
@@ -15,7 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2014,2018,2021,2025 Wind River Systems, Inc.
#
@@ -64,6 +64,7 @@ import abc
import re
import six
import yaml
from sm_api.openstack.common.gettextutils import _
from sm_api.openstack.common import jsonutils
@@ -79,21 +80,38 @@ _rules = None
_checks = {}
def parse_file_contents(data):
"""Parse the raw contents of a policy file.
Parses the contents of a policy file which currently can be in either
yaml or json format. Both can be parsed as yaml.
:param data: A string containing the contents of a policy file.
:returns: A dict of of the form {'policy_name1': 'policy1',
'policy_name2': 'policy2,...}
"""
try:
parsed = jsonutils.loads(data)
except ValueError:
try:
parsed = yaml.safe_load(data) or {}
except yaml.YAMLError as e:
# For backwards-compatibility, convert yaml error to ValueError,
# which is what JSON loader raised.
raise ValueError(six.text_type(e))
return parsed
class Rules(dict):
"""
A store for rules. Handles the default_rule setting directly.
"""
@classmethod
def load_json(cls, data, default_rule=None):
"""
Allow loading of JSON rule data.
"""
# Suck in the JSON data and parse the rules
rules = dict((k, parse_rule(v)) for k, v in
jsonutils.loads(data).items())
def load(cls, data, default_rule=None):
"""Allow loading of YAML/JSON rule data."""
# Parse the rules
rules = {k: parse_rule(v) for k, v in parse_file_contents(data).items()}
return cls(rules, default_rule)
def __init__(self, rules=None, default_rule=None):