summaryrefslogtreecommitdiff
path: root/oslo_policy/generator.py
diff options
context:
space:
mode:
authorBen Nemec <bnemec@redhat.com>2020-01-15 22:10:16 +0000
committerBen Nemec <bnemec@redhat.com>2020-06-26 14:55:26 +0000
commit283768e910257f81b599d2c409bf4a021bc50eae (patch)
treedda611ba471f8f4c474887bc66bcf2a3aa6f5217 /oslo_policy/generator.py
parent719435f7323e55ee6b890f622d0fe9533b635adb (diff)
downloadoslo-policy-283768e910257f81b599d2c409bf4a021bc50eae.tar.gz
Add oslopolicy-validator tool
As requested in the referenced RFE bug, this is a validator tool similar to the oslo.config validator tool that operators can use to look for basic errors in their policy files. It's very similar to the redundant rule tool, but I decided not to combine them because I feel like the target use cases are enough different to warrant separate tools. Specifically, the redundant rule tool is looking for perfectly valid rules that just happen to be unnecessary. The validator is looking for errors in the policy file. While it's unlikely someone looking for redundant rules wouldn't also want to know if there is something broken in their policy file, it's likely that someone just looking to sanity check their policy before deployment wouldn't want to see a bunch of messages about redundant rules that won't cause any problems. Change-Id: I799a754aceac080c11baffd7ff635b2a9cb825f7 Closes-Bug: 1853038
Diffstat (limited to 'oslo_policy/generator.py')
-rw-r--r--oslo_policy/generator.py69
1 files changed, 68 insertions, 1 deletions
diff --git a/oslo_policy/generator.py b/oslo_policy/generator.py
index 48a9972..40f374d 100644
--- a/oslo_policy/generator.py
+++ b/oslo_policy/generator.py
@@ -328,12 +328,70 @@ def _list_redundant(namespace):
enforcer.load_rules()
for name, file_rule in enforcer.file_rules.items():
- reg_rule = enforcer.registered_rules.get(name, None)
+ reg_rule = enforcer.registered_rules.get(name)
if reg_rule:
if file_rule == reg_rule:
print(reg_rule)
+def _validate_policy(namespace):
+ """Perform basic sanity checks on a policy file
+
+ Checks for the following errors in the configured policy file:
+
+ * A missing policy file
+ * Rules which have invalid syntax
+ * Rules which reference non-existent other rules
+ * Rules which form a cyclical reference with another rule
+ * Rules which do not exist in the specified namespace
+
+ :param namespace: The name under which the oslo.policy enforcer is
+ registered.
+ :returns: 0 if all policies validated correctly, 1 if not.
+ """
+ return_code = 0
+ enforcer = _get_enforcer(namespace)
+ # NOTE(bnemec): We don't want to see policy deprecation warnings in the
+ # output of this tool. They tend to overwhelm the output that the user
+ # actually cares about. If we check for deprecated rules in this tool,
+ # we need to do it another way.
+ enforcer.suppress_deprecation_warnings = True
+ # Disable logging from the parser code. We'll be printing any errors we
+ # find below.
+ logging.disable(logging.ERROR)
+ # Ensure that files have been parsed
+ enforcer.load_rules()
+
+ if enforcer._informed_no_policy_file:
+ print('Configured policy file "%s" not found' % enforcer.policy_file)
+ # If the policy file is completely missing then the rest of our checks
+ # don't make sense.
+ return 1
+
+ # Re-enable logging so we get messages for things like cyclical references
+ logging.disable(logging.NOTSET)
+ result = enforcer.check_rules()
+ if not result:
+ print('Invalid rules found')
+ return_code = 1
+
+ # TODO(bnemec): Allow this to handle policy_dir
+ with open(cfg.CONF.oslo_policy.policy_file) as f:
+ unparsed_policies = yaml.safe_load(f.read())
+ for name, file_rule in enforcer.file_rules.items():
+ reg_rule = enforcer.registered_rules.get(name)
+ if reg_rule is None:
+ print('Unknown rule found in policy file:', name)
+ return_code = 1
+ # If a rule has invalid syntax it will be forced to '!'. If the literal
+ # rule from the policy file isn't '!' then this means there was an
+ # error parsing it.
+ if str(enforcer.rules[name]) == '!' and unparsed_policies[name] != '!':
+ print('Failed to parse rule:', unparsed_policies[name])
+ return_code = 1
+ return return_code
+
+
def on_load_failure_callback(*args, **kwargs):
raise
@@ -423,3 +481,12 @@ def list_redundant(args=None):
conf(args)
_check_for_namespace_opt(conf)
_list_redundant(conf.namespace)
+
+
+def validate_policy(args=None):
+ logging.basicConfig(level=logging.WARN)
+ conf = cfg.CONF
+ conf.register_cli_opts(ENFORCER_OPTS)
+ conf.register_opts(ENFORCER_OPTS)
+ conf(args)
+ sys.exit(_validate_policy(conf.namespace))