blob: f5b4c001e600676ae30aa8f2b18ff6c2ad432fa8 [file] [log] [blame]
Felipe Monteiroc4589322017-06-09 19:42:50 +01001========================
2Team and repository tags
3========================
4
5.. image:: http://governance.openstack.org/badges/patrole.svg
6 :target: http://governance.openstack.org/reference/tags/index.html
7
8..
9
10=========================================
11Patrole - RBAC Integration Tempest Plugin
12=========================================
DavidPurcell663aedf2017-01-03 10:01:14 -050013
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010014Patrole is a tool for verifying that Role-Based Access Control is being
15correctly enforced.
DavidPurcell663aedf2017-01-03 10:01:14 -050016
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010017Patrole allows users to run API tests using specified RBAC roles. This allows
DavidPurcell663aedf2017-01-03 10:01:14 -050018deployments to verify that only intended roles have access to those APIs.
19This is critical to ensure security, especially in large deployments with
20custom roles.
21
22* Free software: Apache license
Van Hung Pham31b968d2017-06-05 18:45:16 +070023* Documentation: https://docs.openstack.org/developer/patrole
24* Source: https://git.openstack.org/cgit/openstack/patrole
25* Bugs: https://bugs.launchpad.net/patrole
DavidPurcell663aedf2017-01-03 10:01:14 -050026
27Features
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010028========
29Patrole offers RBAC testing for various OpenStack RBAC policies. It includes
DavidPurcell45bc1a62017-01-19 17:21:27 -050030a decorator that wraps around tests which verifies that when the test calls the
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010031corresponding API endpoint, access is only granted for correct roles.
32
33Currently, Patrole supports policies contained in code and in policy.json files.
34If both exist, the policy actions in the policy.json are prioritized.
35
Samantha Blancobbde0222017-05-04 15:29:56 -040036Stable Interface
37----------------
38Patrole offers a stable interface that is guaranteed to be backwards compatible and
39can be directly consumed by other projects. Currently, rbac_exceptions.py and
40rbac_policy_parser.py are guaranteed to be stable.
41
42Release Versioning
43------------------
44`Patrole Release Notes <https://docs.openstack.org/releasenotes/patrole/>`_ show
45what changes have been released.
46
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010047.. _test-flows:
48
49Test Flows
50----------
DavidPurcell45bc1a62017-01-19 17:21:27 -050051There are several possible test flows.
52
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010053If the ``rbac_test_role`` is allowed to access the endpoint:
DavidPurcell45bc1a62017-01-19 17:21:27 -050054
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010055* The test passes if no 403 ``Forbidden`` or ``RbacActionFailed`` exception is raised.
56
57If the ``rbac_test_role`` is not allowed to access the endpoint:
58
59* If the endpoint returns a 403 `Forbidden` exception the test will pass.
60* If the endpoint returns successfully, then the test will fail with an
61 ``RbacOverPermission`` exception.
62* If the endpoint returns something other than a 403 ``Forbidden`` to indicate
63 that the role is not allowed, the test will raise an ``RbacActionFailed`` exception.
64
65.. note::
66
67 Certain services like Neutron *intentionally* raise a 404 instead of a 403
68 for security concerns. Patrole accomodates this behavior by anticipating
Samantha Blancobbde0222017-05-04 15:29:56 -040069 a 404 instead of a 403, using the ``expected_exception`` argument. For more
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010070 information about Neutron's policy enforcement, see:
71 `<https://docs.openstack.org/developer/neutron/devref/policy.html#request-authorization>`__.
72
73How It Works
74============
75Patrole leverages oslo_policy (OpenStack's policy enforcement engine) to
76determine whether a given role is allowed to perform a policy action given a
77specific rule and OpenStack service. This is done before test execution inside
78the ``rbac_rule_validation.action`` decorator. Then, inside the test, the API
79that does policy enforcement for the same rule is called. The outcome is
80compared against the result from oslo_policy and a pass or fail is determined
Samantha Blanco94c9a472017-06-09 11:54:39 -040081as outlined above: `Test Flows`_.
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010082
83.. note::
84
85 Currently, Patrole does not support checking multiple rules against a single
86 API call. Even though some APIs enforce multiple rules (some indirectly),
87 it is increasingly difficult to maintain the tests if multiple policy
88 actions are expected to be called.
89
90Test Execution Workflow
91-----------------------
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +010092The workflow is as follows:
93
94#. Each test uses the ``rbac_rule_validation.action`` decorator, like below: ::
95
96 @rbac_rule_validation.action(
97 service="nova",
98 rule="os_compute_api:servers:stop")
99 @decorators.idempotent_id('ab4a17d2-166f-4a6d-9944-f17baa576cf2')
100 def test_stop_server(self):
101 # Set the primary credential's role to "rbac_test_role".
102 self.rbac_utils.switch_role(self, toggle_rbac_role=True)
103 # Call the API that enforces the policy action specified by "rule".
104 self._test_stop_server()
105
106 The ``service`` attribute accepts an OpenStack service and the ``rule`` attribute
107 accepts a valid OpenStack policy action, like "os_compute_api:servers:stop".
108
109#. The ``rbac_rule_validation.action`` decorator passes these attributes,
110 along with user_id and project_id information derived from the primary
111 Tempest credential (``self.os.credentials.user_id`` and ``self.os.credentials.project_id``),
112 to the ``rbac_policy_parser``.
113
114#. The logic in ``rbac_policy_parser`` then passes all this information along
115 and the role in ``CONF.rbac.rbac_test_role`` to oslo_policy to determine whether
116 the ``rbac_test_role`` is authorized to perform the policy action for the given
117 service.
118
119#. After all of the logic above has executed inside the rbac decorator, the
120 test is executed. The test then sets up test-level resources, if necessary,
121 with **admin** credentials implicitly. This is accomplished through
Samantha Blanco94c9a472017-06-09 11:54:39 -0400122 ``rbac_utils.switch_role(toggle_rbac_role=False)``, which is done as part of
123 client setup (inside the call to ``rbac_utils.RbacUtils``): ::
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +0100124
125 @classmethod
126 def setup_clients(cls):
127 super(BaseV2ComputeRbacTest, cls).setup_clients()
Samantha Blanco94c9a472017-06-09 11:54:39 -0400128 cls.auth_provider = cls.os_primary.auth_provider
129 cls.rbac_utils = rbac_utils.RbacUtils(cls)
130 ...
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +0100131
132 This code has *already* executed when the test class is instantiated, because
133 it is located in the base rbac test class. Whenever ``cls.rbac_utils.switch_role``
134 is called, one of two behaviors are possible:
135
136 #. The primary credential's role is changed to admin if ``toggle_rbac_role=False``
137 #. The primary credential's role is changed to ``rbac_test_role`` if
138 ``toggle_rbac_role=True``
139
140 Thus, at the *beginning* of every test and during ``resource_setup`` and
141 ``resource_cleanup``, the primary credential has the admin role.
142
143#. After preliminary test-level setup is performed, like creating a server, a
144 second call to ``self.rbac_utils.switch_role`` is done: ::
145
146 self.rbac_utils.switch_role(cls, toggle_rbac_role=True)
147
148 Now the primary credential has the role specified by ``rbac_test_role``.
149
Samantha Blanco94c9a472017-06-09 11:54:39 -0400150#. The API endpoint in which policy enforcement of "os_compute_api:servers:stop"
Felipe Monteiro7bc35dc2017-04-19 21:11:46 +0100151 is performed can now be called.
152
153 .. note:
154
155 To determine whether a policy action is enforced, refer to the relevant
156 controller code to make sure that the policy action is indeed enforced.
157
158#. Now that a call is made to "stop_server" with the primary credentials having
159 the role specified by ``rbac_test_role``, either the nova contoller will allow
160 or disallow the action to be performed. Since the "stop_server" policy action in
161 nova is defined as "base.RULE_ADMIN_OR_OWNER", the API will most likely
162 return a successful status code. For more information about this policy action,
163 see `<https://github.com/openstack/nova/blob/master/nova/policies/servers.py>`__.
164
165#. As mentioned above, the result from the API call and the result from oslo_policy
166 are compared for consistency.
167
168#. Finally, after the test has executed, but before ``tearDown`` or ``resource_cleanup``
169 is called, ``self.rbac_utils.switch_role(cls, toggle_rbac_role=False)`` is
170 called, so that the primary credential yet again has admin permissions for
171 test clean up. This call is always performed in the "finally" block inside
172 the ``rbac_rule_validation`` decorator.
173
174.. warning::
175
176 Failure to call ``self.rbac_utils.switch_role(cls, toggle_rbac_role=True)``
177 inside a test with the ``rbac_rule_validation`` decorator applied results
178 in a ``RbacResourceSetupFailed`` being raised, causing the test to fail.