Pass Targets to Glance's Policy Enforcer
SecurityImpact Change-Id: If5047942f03915cc4b1e42a586cf403a4eceab58
This commit is contained in:
parent
224ade269d
commit
a9fde2dee6
248
specs/kilo/pass-targets-to-policy-enforcer.rst
Normal file
248
specs/kilo/pass-targets-to-policy-enforcer.rst
Normal file
@ -0,0 +1,248 @@
|
||||
..
|
||||
This work is licensed under a Creative Commons Attribution 3.0 Unported
|
||||
License.
|
||||
|
||||
http://creativecommons.org/licenses/by/3.0/legalcode
|
||||
|
||||
========================================
|
||||
Pass Targets to Glance's Policy Enforcer
|
||||
========================================
|
||||
|
||||
https://blueprints.launchpad.net/glance/+spec/pass-targets-to-policy-enforcer
|
||||
|
||||
Currently it's possible to define custom rules in Glance's ``policy.json``
|
||||
that rely on attributes other than a user's roles. Unfortunately, if you
|
||||
attempt to apply one of those rules, it will always cause the user to be
|
||||
prevented from performing the associated action. This specification proposes
|
||||
that we pass the proper target objects to the enforcer so these rules can be
|
||||
used and properly enforced.
|
||||
|
||||
|
||||
Problem description
|
||||
===================
|
||||
|
||||
Currently, Glance promises that permissions can be configured in the
|
||||
``policy.json`` file but any rule other than a role check currently
|
||||
results in a ``403 Forbidden`` response. As this is a promised feature,
|
||||
implementing this specification is merely fixing the already promised
|
||||
behaviour.
|
||||
|
||||
It is not possible to restrict access to actions in Glance's ``policy.json``
|
||||
based on anything other than a user's roles. The policy enforcer that Glance
|
||||
extends from oslo expects a dictionary-like object to be passed as a target of
|
||||
the action. Every method that uses the policy enforcer and enforces the policy
|
||||
defined for the corresponding action currently passes an empty dictionary
|
||||
(``{}``) which provides absolutely no data about the actual target.
|
||||
|
||||
If we define a rule similar to the following::
|
||||
|
||||
"tenant_is_owner": "tenant%(owner)s"
|
||||
|
||||
And we apply it to an action, e.g.,
|
||||
|
||||
::
|
||||
|
||||
"delete_image": "rule:tenant_is_owner"
|
||||
|
||||
Then every request to delete any image will be denied with a 403
|
||||
(Unauthorized) response from Glance's API. The reason stems from how the rule
|
||||
is parsed and the target is passed in. The ``"rule:tenant_is_owner"`` rule
|
||||
will be parsed as a ``GenericCheck``. These checks are split on the ``:`` into
|
||||
a ``kind`` and a ``match`` (roughly, ``"<kind>:<match>"``). The match portion
|
||||
is then interpolated with the target, i.e.,
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
match = self.match % target
|
||||
|
||||
So using our example above, we would do
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
match = "%(owner)s" % {}
|
||||
|
||||
Except that this raises a ``KeyError`` which means the check immediately
|
||||
returns ``False`` and fails. In this particular instance (deleting an image),
|
||||
if we passed an instance of ``glance.api.policy.ImageTarget``, then what would
|
||||
instead happen is that the interpolation would succeed.
|
||||
|
||||
|
||||
Proposed change
|
||||
===============
|
||||
|
||||
The solution for image-based resources is simple. We have the ``image`` on the
|
||||
policy proxies that relate to images. We simply pass that to
|
||||
``glance.api.policy.ImageTarget`` and pass the resulting instance to the
|
||||
policy enforcer so it can be accessed like a dictionary when interpolated.
|
||||
For members and tasks, there is no target class that we can use. These are
|
||||
very thin classes that could easily be written.
|
||||
|
||||
Once we have the appropriately defined target classes, we would then update
|
||||
the places where the policy is enforced to use instances of those target
|
||||
classes.
|
||||
|
||||
With proper targets in place, we can also implement safer default policy rules
|
||||
for operators who rely solely on the default ``policy.json`` file.
|
||||
|
||||
Alternatives
|
||||
------------
|
||||
|
||||
Custom rule creation based on attributes of the target object could be
|
||||
disabled. This would severely limit an operator's ability to restrict actions
|
||||
based on a user's tenant and other properties of the target of the action.
|
||||
|
||||
Data model impact
|
||||
-----------------
|
||||
|
||||
None
|
||||
|
||||
REST API impact
|
||||
---------------
|
||||
|
||||
None
|
||||
|
||||
Security impact
|
||||
---------------
|
||||
|
||||
This will give operators a significant amount of control over the security of
|
||||
their Glance installations. Currently they can only restrict actions based on
|
||||
roles which may be sufficient in some cases. If the operator, however, wishes
|
||||
to restrict access based on other factors (besides role) they cannot do this.
|
||||
If they try to do it, there is no indication that it will not work but they
|
||||
can essentially produce a Denial of Service to users who should be able to
|
||||
perform actions based on the policy defined.
|
||||
|
||||
Notifications impact
|
||||
--------------------
|
||||
|
||||
None
|
||||
|
||||
Other end user impact
|
||||
---------------------
|
||||
|
||||
None
|
||||
|
||||
Performance Impact
|
||||
------------------
|
||||
|
||||
None
|
||||
|
||||
Other deployer impact
|
||||
---------------------
|
||||
|
||||
To leverage the fixes in this specification, operators need to update their
|
||||
versions of ``policy.json`` used in their deployments. To write a rule,
|
||||
operators need to know that there are three values provided by glance that can
|
||||
be used in a rule on the left side of the colon (``:``). Those values are the
|
||||
current user's credentials in the form of:
|
||||
|
||||
- role
|
||||
- tenant
|
||||
- owner
|
||||
|
||||
The left side of the colon can also contain any value that Python can
|
||||
understand, e.g.,:
|
||||
|
||||
- ``True``
|
||||
- ``False``
|
||||
- ``"a string"``
|
||||
- &c.
|
||||
|
||||
Role checks are going to continue to work exactly as they already do. If the
|
||||
role defined in the check is one that the user holds, then that will pass,
|
||||
e.g., ``role:admin``.
|
||||
|
||||
Using ``tenant`` and ``owner`` will only work with Images or actions that
|
||||
interact with an image. Consider the following rule::
|
||||
|
||||
tenant:%(owner)s
|
||||
|
||||
This will use the ``tenant`` value of the currently authenticated user. It
|
||||
will also use ``owner`` from the image it is acting upon. If those two
|
||||
values are equivalent the check will pass. All attributes on an image (as well
|
||||
as extra image properties) are available for use on the right side of the
|
||||
colon. The most useful are the following:
|
||||
|
||||
- ``owner``
|
||||
- ``protected``
|
||||
- ``is_public``
|
||||
|
||||
An operator, therefore, could construct a set of rules like the following::
|
||||
|
||||
{
|
||||
"not_protected": "False:%(protected)s",
|
||||
"is_owner": "tenant:%(owner)s",
|
||||
"not_protected_and_is_owner": "rule:not_protected and rule:is_owner",
|
||||
"delete_image": "rule:not_protected_and_is_owner"
|
||||
}
|
||||
|
||||
Developer impact
|
||||
----------------
|
||||
|
||||
None
|
||||
|
||||
|
||||
Implementation
|
||||
==============
|
||||
|
||||
Assignee(s)
|
||||
-----------
|
||||
|
||||
Primary assignee:
|
||||
icordasc
|
||||
|
||||
Reviewers
|
||||
---------
|
||||
|
||||
Core reviewer(s):
|
||||
nikhil-komawar
|
||||
jokke
|
||||
|
||||
Other reviewer(s):
|
||||
kragniz
|
||||
|
||||
Work Items
|
||||
----------
|
||||
|
||||
- Create appropriate target classes
|
||||
- Use target classes to proxy targets to the policy enforcer
|
||||
- Add tests demonstrating that generic checks now work
|
||||
- Add better documentation surrounding policy rules to the existing
|
||||
documentation
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
None
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
Functional tests will be added where specific ``policy.json`` files are loaded
|
||||
to test access control of different targets.
|
||||
|
||||
|
||||
Documentation Impact
|
||||
====================
|
||||
|
||||
There is no direct impact, but the existing ``policy.json`` documentation is
|
||||
thin and only describes what each rule controls. It does not describe the
|
||||
available target information or how to write rules.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
Related bugs:
|
||||
|
||||
- https://bugs.launchpad.net/glance/+bug/1253963
|
||||
- https://bugs.launchpad.net/glance/+bug/1346648
|
||||
|
||||
Initial work at an implementation:
|
||||
|
||||
- https://review.openstack.org/#/c/146651/
|
||||
|
||||
Glance meeting discussion on 2015 January 15:
|
||||
|
||||
- http://eavesdrop.openstack.org/meetings/glance/2015/glance.2015-01-15-14.02.log.html
|
Loading…
Reference in New Issue
Block a user