Value comparisons are dependent on order

Bug #1749727 reported by Pierre Riteau
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
oslo.policy
Triaged
Medium
Unassigned

Bug Description

The documentation at https://docs.openstack.org/oslo.policy/latest/admin/policy-json-file.html#syntax says that two values can be compared in the following way:

    "value1 : value2"

and that values can have various types. No mention is made of ordering, or that value1 or value2 are restricted to a subset of the allowed data types.

However, I have noticed that a rule using a target object attribute as value1 and string as value2 doesn't work. The service using the following policy (Gnocchi on Ocata) is showing the backtrace displayed below.

    "services_project": "%(created_by_project_id)s:'services_project_uuid'",

The opposite order works successfully though:

    "services_project": "'services_project_uuid':%(created_by_project_id)s",

I am seeing this issue with python2-oslo-policy-1.18.0-1.el7.noarch from RDO Ocata.

In addition, changing the order of arguments in oslo_policy.tests.test_checks:test_constant_string_accept in master makes the test fail too, so this bug may still be in the latest code.

[Thu Feb 15 09:06:44.803271 2018] [:error] [pid 77563] [remote 10.20.111.244:56] mod_wsgi (pid=77563): Exception occurred processing WSGI script '/var/www/cgi-bin/gnocchi/app'.
[Thu Feb 15 09:06:44.803315 2018] [:error] [pid 77563] [remote 10.20.111.244:56] Traceback (most recent call last):
[Thu Feb 15 09:06:44.803335 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
[Thu Feb 15 09:06:44.803363 2018] [:error] [pid 77563] [remote 10.20.111.244:56] resp = self.call_func(req, *args, **self.kwargs)
[Thu Feb 15 09:06:44.803374 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
[Thu Feb 15 09:06:44.803387 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return self.func(req, *args, **kwargs)
[Thu Feb 15 09:06:44.803398 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/oslo_middleware/base.py", line 126, in __call__
[Thu Feb 15 09:06:44.803411 2018] [:error] [pid 77563] [remote 10.20.111.244:56] response = req.get_response(self.application)
[Thu Feb 15 09:06:44.803419 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/request.py", line 1299, in send
[Thu Feb 15 09:06:44.803430 2018] [:error] [pid 77563] [remote 10.20.111.244:56] application, catch_exc_info=False)
[Thu Feb 15 09:06:44.803438 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/request.py", line 1263, in call_application
[Thu Feb 15 09:06:44.803448 2018] [:error] [pid 77563] [remote 10.20.111.244:56] app_iter = application(self.environ, start_response)
[Thu Feb 15 09:06:44.803463 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/paste/urlmap.py", line 203, in __call__
[Thu Feb 15 09:06:44.803481 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return app(environ, start_response)
[Thu Feb 15 09:06:44.803492 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
[Thu Feb 15 09:06:44.803542 2018] [:error] [pid 77563] [remote 10.20.111.244:56] resp = self.call_func(req, *args, **self.kwargs)
[Thu Feb 15 09:06:44.803550 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
[Thu Feb 15 09:06:44.803561 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return self.func(req, *args, **kwargs)
[Thu Feb 15 09:06:44.803571 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/oslo_middleware/base.py", line 126, in __call__
[Thu Feb 15 09:06:44.803581 2018] [:error] [pid 77563] [remote 10.20.111.244:56] response = req.get_response(self.application)
[Thu Feb 15 09:06:44.803588 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/request.py", line 1299, in send
[Thu Feb 15 09:06:44.803598 2018] [:error] [pid 77563] [remote 10.20.111.244:56] application, catch_exc_info=False)
[Thu Feb 15 09:06:44.803620 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/request.py", line 1263, in call_application
[Thu Feb 15 09:06:44.803633 2018] [:error] [pid 77563] [remote 10.20.111.244:56] app_iter = application(self.environ, start_response)
[Thu Feb 15 09:06:44.803641 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
[Thu Feb 15 09:06:44.803651 2018] [:error] [pid 77563] [remote 10.20.111.244:56] resp = self.call_func(req, *args, **self.kwargs)
[Thu Feb 15 09:06:44.803661 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
[Thu Feb 15 09:06:44.803670 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return self.func(req, *args, **kwargs)
[Thu Feb 15 09:06:44.803677 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/keystonemiddleware/auth_token/__init__.py", line 335, in __call__
[Thu Feb 15 09:06:44.803689 2018] [:error] [pid 77563] [remote 10.20.111.244:56] response = req.get_response(self._app)
[Thu Feb 15 09:06:44.803697 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/request.py", line 1299, in send
[Thu Feb 15 09:06:44.803706 2018] [:error] [pid 77563] [remote 10.20.111.244:56] application, catch_exc_info=False)
[Thu Feb 15 09:06:44.803713 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/request.py", line 1263, in call_application
[Thu Feb 15 09:06:44.803723 2018] [:error] [pid 77563] [remote 10.20.111.244:56] app_iter = application(self.environ, start_response)
[Thu Feb 15 09:06:44.803730 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/webob/exc.py", line 1162, in __call__
[Thu Feb 15 09:06:44.803741 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return self.application(environ, start_response)
[Thu Feb 15 09:06:44.803753 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/gnocchi/rest/app.py", line 68, in __call__
[Thu Feb 15 09:06:44.803765 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return self.app(environ, start_response)
[Thu Feb 15 09:06:44.803772 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/pecan/middleware/recursive.py", line 56, in __call__
[Thu Feb 15 09:06:44.803783 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return self.application(environ, start_response)
[Thu Feb 15 09:06:44.803790 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/pecan/core.py", line 835, in __call__
[Thu Feb 15 09:06:44.803801 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return super(Pecan, self).__call__(environ, start_response)
[Thu Feb 15 09:06:44.803808 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/pecan/core.py", line 678, in __call__
[Thu Feb 15 09:06:44.803818 2018] [:error] [pid 77563] [remote 10.20.111.244:56] self.invoke_controller(controller, args, kwargs, state)
[Thu Feb 15 09:06:44.803828 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/pecan/core.py", line 569, in invoke_controller
[Thu Feb 15 09:06:44.803838 2018] [:error] [pid 77563] [remote 10.20.111.244:56] result = controller(*args, **kwargs)
[Thu Feb 15 09:06:44.803848 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/gnocchi/rest/__init__.py", line 396, in get_measures
[Thu Feb 15 09:06:44.803859 2018] [:error] [pid 77563] [remote 10.20.111.244:56] self.enforce_metric("get measures")
[Thu Feb 15 09:06:44.803866 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/gnocchi/rest/__init__.py", line 375, in enforce_metric
[Thu Feb 15 09:06:44.803883 2018] [:error] [pid 77563] [remote 10.20.111.244:56] enforce(rule, json.to_primitive(self.metric))
[Thu Feb 15 09:06:44.803891 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/gnocchi/rest/__init__.py", line 79, in enforce
[Thu Feb 15 09:06:44.803923 2018] [:error] [pid 77563] [remote 10.20.111.244:56] if not pecan.request.policy_enforcer.enforce(rule, target, creds):
[Thu Feb 15 09:06:44.803931 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/oslo_policy/policy.py", line 724, in enforce
[Thu Feb 15 09:06:44.803942 2018] [:error] [pid 77563] [remote 10.20.111.244:56] result = self.rules[rule](target, creds, self)
[Thu Feb 15 09:06:44.803952 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/oslo_policy/_checks.py", line 160, in __call__
[Thu Feb 15 09:06:44.804066 2018] [:error] [pid 77563] [remote 10.20.111.244:56] if rule(target, cred, enforcer):
[Thu Feb 15 09:06:44.804080 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/oslo_policy/_checks.py", line 204, in __call__
[Thu Feb 15 09:06:44.804095 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return enforcer.rules[self.match](target, creds, enforcer)
[Thu Feb 15 09:06:44.804104 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib/python2.7/site-packages/oslo_policy/_checks.py", line 304, in __call__
[Thu Feb 15 09:06:44.804118 2018] [:error] [pid 77563] [remote 10.20.111.244:56] test_value = ast.literal_eval(self.kind)
[Thu Feb 15 09:06:44.804158 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib64/python2.7/ast.py", line 49, in literal_eval
[Thu Feb 15 09:06:44.804270 2018] [:error] [pid 77563] [remote 10.20.111.244:56] node_or_string = parse(node_or_string, mode='eval')
[Thu Feb 15 09:06:44.804283 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "/usr/lib64/python2.7/ast.py", line 37, in parse
[Thu Feb 15 09:06:44.804297 2018] [:error] [pid 77563] [remote 10.20.111.244:56] return compile(source, filename, mode, PyCF_ONLY_AST)
[Thu Feb 15 09:06:44.804334 2018] [:error] [pid 77563] [remote 10.20.111.244:56] File "<unknown>", line 1
[Thu Feb 15 09:06:44.804341 2018] [:error] [pid 77563] [remote 10.20.111.244:56] %(created_by_project_id)s
[Thu Feb 15 09:06:44.804344 2018] [:error] [pid 77563] [remote 10.20.111.244:56] ^
[Thu Feb 15 09:06:44.804347 2018] [:error] [pid 77563] [remote 10.20.111.244:56] SyntaxError: invalid syntax

Revision history for this message
Lance Bragstad (lbragstad) wrote :

Do you happen to have a link to the Gnocchi policy that breaks this? Just curious because this is the first time I've seen a policy rule built like that, as opposed to the following syntax:

  "'services_project_uuid':%(created_by_project_id)s"

Revision history for this message
Pierre Riteau (priteau) wrote :

Hi Lance,

This is a policy file that I modified myself. Compared to the default Gnocchi policy, I added the "services_project" rule, and modified the "get resource", "get metric", and "get measures" rules to use the new rule. The intent was to make resource, metrics, and measures created by a specific project readable by every OpenStack user.

The following policy works:

    "services_project": "'d41d8cd98f00b204e9800998ecf8427e':%(created_by_project_id)s",
    "get resource": "rule:admin_or_creator or rule:resource_owner or rule:services_project",
    "get metric": "rule:admin_or_creator or rule:metric_owner or rule:services_project",
    "get measures": "rule:admin_or_creator or rule:metric_owner or rule:services_project",

I first tried to write the "services_project" rule in the opposite order, which doesn't work:

    "services_project": "%(created_by_project_id)s:'d41d8cd98f00b204e9800998ecf8427e'",

I first tried it this way because intuitively it felt like the right order: I write my code as `if x == some_value`, rather than `if some_value == x`.

Anyway, the documentation doesn't say anything about order being important. Do you know if this is a gap in the documentation or a bug in oslo.policy?

Revision history for this message
Morgan Fainberg (mdrnstm) wrote :

This is very much an odditiy in how oslo_policy does the creds dict lookup. Basically the first value is always a direct lookup of the creds dict, so you do creds_dict[<key, first value>] compared with the literal string of the second value.

We should improve documentation. Order isn't really the issue here.

Ben Nemec (bnemec)
Changed in oslo.policy:
status: New → Triaged
importance: Undecided → Medium
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.