diff --git a/README.rst b/README.rst index e9c03c8e..2028536c 100644 --- a/README.rst +++ b/README.rst @@ -31,6 +31,8 @@ documentation. * Bugs: https://bugs.launchpad.net/patrole * Release notes: https://docs.openstack.org/releasenotes/patrole/ +.. _design-principles: + Design Principles ----------------- @@ -59,6 +61,9 @@ but not all, as its testing scope is confined to policies. Realistically this is not always possible because some services have not yet moved to policy in code. +* *Customizable*. Patrole should be able to validate custom policy overrides to + ensure that those overrides enhance rather than undermine the cloud's RBAC + configuration. In addition, Patrole should be able to validate any role. * *Self-cleaning*. Patrole should attempt to clean up after itself; whenever possible we should tear down resources when done. diff --git a/doc/source/index.rst b/doc/source/index.rst index 560857ea..2dbf63b1 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -10,6 +10,14 @@ Overview overview +RBAC Overview +------------- + +.. toctree:: + :maxdepth: 2 + + rbac-overview + User's Guide ============ diff --git a/doc/source/rbac-overview.rst b/doc/source/rbac-overview.rst new file mode 100644 index 00000000..5eefa5cc --- /dev/null +++ b/doc/source/rbac-overview.rst @@ -0,0 +1,254 @@ +================================== +Role-Based Access Control Overview +================================== + +Introduction +------------ + +Role-Based Access Control (RBAC) is used by most OpenStack services to control +user access to resources. Authorization is granted if a user has the necessary +role to perform an action. Patrole is concerned with validating that each of +these resources *can* be accessed by authorized users and *cannot* be accessed +by unauthorized users. + +OpenStack services use `oslo.policy`_ as the library for RBAC authorization. +Patrole relies on the same library for deriving expected test results. + +.. _policy-in-code: + +Policy in Code +-------------- + +Services publish their policy-to-API mapping via policy in code documentation. +This mapping includes the list of APIs that authorize a policy, for each +policy declared within a service. + +For example, Nova's policy in code documentation is located in the +`Nova repository`_ under ``nova/policies``. Likewise, Keystone's policy in +code documentation is located in the `Keystone repository`_ under +``keystone/common/policies``. The other OpenStack services follow the same +directory layout pattern with respect to policy in code. + +The policy in code `governance goal`_ enumerates many advantages with following +this RBAC design approach. A so-called library of in-code policies offers the +following advantages, with respect to facilitating validation: + +* includes every policy enforced by an OpenStack service, enabling the + possibility of complete Patrole test coverage for that service (otherwise + one has to read the source code to discover all the policies) +* provides the policy-to-API mapping for each policy which can be used + to write correct Patrole tests (otherwise reading source code and + experimentation are required to derive this mapping) +* by extension, the policy-to-API mapping facilitates writing multi-policy + Patrole tests (otherwise even more experimentation and code reading is + required to arrive at all the policies enforced by an API) +* policy in code documentation includes additional information, like + descriptions and (in the case of some services, like Keystone) + `scope types`_, which help with understanding how to correctly write + Patrole tests +* by extension, such information helps to determine whether a Patrole test + should assume :term:`hard authorization` or :term:`soft authorization` + +Policy in Code (Default) Validation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, Patrole validates default OpenStack policies. This is so that +the out-of-the-box defaults are sanity-checked, to ensure that OpenStack +services are secure, from an RBAC perspective, for each release. + +Patrole strives to validate RBAC by using the policy in code documentation, +wherever possible. + +.. _custom-policies: + +Custom Policies +--------------- + +Operators can override policy in code defaults using `policy.yaml`_. While +this allows operators to offer more fine-grained RBAC control to their tenants, +it opens the door to misconfiguration and bugs. Patrole can be used to validate +that custom policy overrides don't break anything and work as expected. + +Custom Policy Validation +^^^^^^^^^^^^^^^^^^^^^^^^ + +While testing default policy behavior is a valid use case, oftentimes default +policies are modified with custom overrides in production. OpenStack's +`policy.yaml`_ documentation claims that "modifying policy can have unexpected +side effects", which is why Patrole was created: to ensure that custom +overrides allow the principle of least privilege to be tailor-made to exact +specifications via policy overrides, without: + +* causing unintended side effects (breaking API endpoints, breaking + cross-service workflows, breaking the policy file itself); or +* resulting in poor RBAC configuration, promoting security vulnerabilities + +This has implications on Patrole's :ref:`design-principles`: validating custom +overrides requires the ability to handle arbitrary roles, which requires logic +capable of dynamically determining expected test behavior. See +:ref:`rbac-validation` for more details. + +Note that support for custom policies is limited. This is because custom +policies can be arbitrarily complex, requiring that tests be very robust +in order to handle all edge cases. + +.. _multiple-policies: + +Multiple Policies +----------------- + +Behind the scenes, many APIs enforce multiple policies, for many reasons, +including: + +* to control complex cross-service workflows; +* to control whether a server is booted from an image or booted from a volume + (for example); +* to control whether a response body should contain additional information + conditioned upon successful policy authorization. + +This makes `policy in code`_ especially important for policy validation: it +is difficult to keep track of all the policies being enforced across all the +individual APIs, without policy in code documentation. + +Multi-Policy Validation +^^^^^^^^^^^^^^^^^^^^^^^ + +Patrole offers support for validating APIs that enforce multiple policies. +Perhaps in an ideal world each API endpoint would enforce only one policy, +but in reality some API endpoints enforce multiple policies. Thus, to offer +accurate validation, Patrole handles multiple policies: + +* for services *with* policy in code documentation: this documentation + indicates that a single API endpoint enforces multiple policy actions. +* for services *without* policy in code documentation: the API code clearly + shows multiple policy actions being validated. Note that in this case some + degree of log tracing is required by developers to confirm that the expected + policies are getting enforced, prior to the tests getting merged. + +.. todo:: + + Link to multi-policy validation documentation section once it has been + written. + +.. _error-codes: + +Error Codes +----------- + +Most OpenStack services raise a ``403 Forbidden`` following failed +:term:`hard authorization`. Neutron, however, can raise a ``404 NotFound`` +as well. See Neutron's `authorization policy enforcement`_ documentation +for more details. + +Glossary +-------- + +The following nomenclature is used throughout Patrole documentation so it is +important to understand what each term means in order to understand concepts +related to RBAC in Patrole. + +.. glossary:: + + authorize + + The act of ``oslo.policy`` determining whether a user can perform a + :term:`policy` given his or her :term:`role`. + + enforce + + See :term:`authorize`. + + hard authorization + + The `do_raise`_ flag controls whether policy authorization should result + in an exception getting raised or a boolean value getting returned. + Hard authorization results in an exception getting raised. Usually, this + results in a ``403 Forbidden`` getting returned for unauthorized requests. + (See :ref:`error-codes` for further details.) + + Related term: :term:`soft authorization`. + + oslo.policy + + The OpenStack library providing support for RBAC policy enforcement across + all OpenStack services. See the `official documentation`_ for more + information. + + policy + + Defines an RBAC rule. Each policy is defined by a one-line statement in + the form "" : "". For more information, reference OpenStack's + `policy documentation`_. + + policy action + + See :term:`policy target`. + + policy file + + Prior to `governance goal`_ used by all OpenStack services to define + policy defaults. Still used by some services, which is why Patrole + needs to read the policy files to derive policy information for testing. + + policy in code + + Registers default OpenStack policies for a service in the service's code + base. + + Beginning with the Queens release, policy in code became a + `governance goal`_. + + policy rule + + The policy rule determines under which circumstances the API call is + permitted. + + policy target + + The name of a policy. + + requirements file + + Requirements-driven approach to declaring the expected RBAC test results + referenced by Patrole. Uses a high-level YAML syntax to crystallize policy + requirements concisely and unambiguously. See :ref:`requirements-authority` + for more information. + + role + + A designation for the set of actions that describe what a user can do in + the system. Roles are managed through the `Keystone Roles API`_. + + Role-Based Access Control (RBAC) + + May be formally defined as "an approach to restricting system access to + authorized users." + + rule + + See :term:`policy rule`. Note that currently the Patrole code base + conflates "rule" with :term:`policy target` in some places. + + soft authorization + + The `do_raise`_ flag controls whether policy authorization should result + in an exception getting raised or a boolean value getting returned. + Soft authorization results in a boolean value getting returned. When policy + authorization evaluates to true, additional operations are performed as a + part of the API request or additional information is included in the + response body (see `response filtering`_ for an example). + + Related term: :term:`hard authorization`. + +.. _Nova repository: https://github.com/openstack/nova/tree/master/nova/policies +.. _Keystone repository: https://github.com/openstack/keystone/tree/master/keystone/common/policies +.. _governance goal: https://governance.openstack.org/tc/goals/queens/policy-in-code.html +.. _scope types: https://docs.openstack.org/keystone/latest/admin/identity-tokens.html#authorization-scopes +.. _policy.yaml: https://docs.openstack.org/ocata/config-reference/policy-yaml-file.html +.. _oslo.policy: https://docs.openstack.org/oslo.policy/latest/ +.. _policy documentation: https://docs.openstack.org/kilo/config-reference/content/policy-json-file.html +.. _do_raise: https://docs.openstack.org/oslo.policy/latest/reference/api/oslo_policy.policy.html#oslo_policy.policy.Enforcer.enforce +.. _authorization policy enforcement: https://docs.openstack.org/neutron/latest/contributor/internals/policy.html +.. _official documentation: https://docs.openstack.org/oslo.policy/latest/ +.. _Keystone Roles API: https://developer.openstack.org/api-ref/identity/v3/#roles +.. _response filtering: https://docs.openstack.org/neutron/latest/contributor/internals/policy.html#response-filtering