Created
May 13, 2024 15:44
-
-
Save markus-hentsch/54adc0bd5bc7c5799199bf11bf1b8abf to your computer and use it in GitHub Desktop.
OpenStack oslo.policy batch default policy generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Generates default API policy files for a list of OpenStack services. | |
SERVICES=( | |
cinder | |
glance | |
keystone | |
neutron | |
nova | |
octavia | |
placement | |
barbican | |
cloudkitty | |
designate | |
gnocchi | |
heat | |
ironic | |
manila | |
masakari | |
) | |
python3 -m venv .venv | |
. .venv/bin/activate | |
PIP_LIST="$(pip3 list)" | |
for SVC in ${SERVICES[*]} | |
do | |
# naming redirects as per pypi.org | |
if [ "$SVC" = "placement" ]; then | |
SVC="openstack-placement" | |
fi | |
if [ "$SVC" = "heat" ]; then | |
SVC="openstack-heat" | |
fi | |
case "$PIP_LIST" in | |
*"$SVC "*) | |
echo "$SVC is already installed." | |
;; | |
*) | |
echo "Installing $SVC ..." | |
pip3 install $SVC | |
;; | |
esac | |
done | |
for SVC in ${SERVICES[*]} | |
do | |
echo "$SVC" | |
python3 in-code-policy-generator.py $SVC | |
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""oslo.policy unmodified policy generator | |
Mimicks the behavior of oslopolicy-policy-generator with a few key differences: | |
- outputs the unmodified policy rules as directly defined in the service's | |
code without merging any deviations resulting from config files into it | |
- (oslopolicy-policy-generator always merges any adjustments resulting | |
from /etc/<service/<service>.conf and the likes) | |
- outputs two sets of policy files: one with deprecated rules included and one | |
without | |
- (oslopolicy-policy-generator always excludes deprecated rules even if | |
they are still the default setting) | |
- this circumvents cases where oslopolicy-policy-generator would generate | |
policy files not actually matching an API's default behavior | |
This script takes a single argument, which is the namespace like it would be | |
passed to oslopolicy-policy-generator, e.g. "keystone". | |
Requires the service in question to be installed as a Python package since | |
policies will be directly retrieved from its code implementation. | |
""" | |
from oslo_policy import generator, policy | |
import sys | |
import os | |
assert len(sys.argv) > 1, "Namespace argument missing" | |
namespace = str(sys.argv[1]) | |
# truncate sys.argv to a length of 1 (remove any passed arguments) | |
# this is necessary because _get_enforcer() will fail for some namespaces | |
# if sys.argv contains additional arguments | |
del sys.argv[1:] | |
print(f"Generating default policy files for {namespace} ...") | |
def ruledefault_to_yaml_entry(ruledefault: policy.RuleDefault) -> str: | |
""" | |
Returns a YAML-formatted string representation of a policy.RuleDefault. | |
""" | |
return generator._format_rule_default_yaml( | |
ruledefault, include_help=False, comment_rule=False, | |
add_deprecated_rules=False | |
) | |
def get_default_policy_rules(namespace: str, | |
use_deprecated: bool | |
) -> list[policy.RuleDefault]: | |
""" | |
Returns the list of policy.RuleDefaults of all in-code policies within | |
an OpenStack service's namespace. | |
""" | |
# mimick a code path which is only needed for Octavia and its absence | |
# would otherwise throw an exception on _get_enforcer() below | |
if namespace == "octavia": | |
from oslo_config import cfg | |
cfg.CONF() | |
enforcer = generator._get_enforcer(namespace) | |
enforcer.load_rules() | |
rules = [] | |
for name, default in enforcer.registered_rules.items(): | |
if use_deprecated and default.deprecated_rule: | |
rule = default.deprecated_rule.check_str | |
else: | |
rule = default.check_str | |
rules.append(policy.RuleDefault(name, rule)) | |
return rules | |
def main(): | |
policies = get_default_policy_rules(namespace, False) | |
deprecated_policies = get_default_policy_rules(namespace, True) | |
os.makedirs("policies", exist_ok=True) | |
fp = open(os.path.join("policies", f"{namespace}.yaml"), 'w') | |
fp.writelines([ | |
ruledefault_to_yaml_entry(rule_default) | |
for rule_default in policies | |
]) | |
os.makedirs("policies-deprecated", exist_ok=True) | |
fp = open(os.path.join( | |
"policies-deprecated", f"{namespace}.yaml"), 'w') | |
fp.writelines([ | |
ruledefault_to_yaml_entry(rule_default) | |
for rule_default in deprecated_policies | |
]) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment