forked from openstack/horizon
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding RBAC policy system and checks for identity
Adding file based RBAC engine for Horizon using copies of nova and keystone policy.json files Policy engine builds on top of oslo incubator policy.py, fileutils was also pulled from oslo incubator as a dependency of policy.py When Horizon runs and a policy check is made, a path and mapping of services to policy files is used to load the rules into the policy engine. Each check is mapped to a service type and validated. This extra level of mapping is required because the policy.json files may each contain a 'default' rule or unqualified (no service name include) rule. Additionally, maintaining separate policy.json files per service will allow easier syncing with the service projects. The engine allows for compound 'and' checks at this time. E.g., the way the Create User action is written, multiple APIs are called to read data (roles, projects) and more are required to update data (grants, user). Other workflows e.g., Edit Project, should have separate save actions per step as they are unrelated. Only the applicable policy checks to that step were added. The separating unrelated steps saves will should be future work. The underlying engine supports more rule types that are used in the underlying policy.json files. Policy checks were added for all actions on tables in the Identity Panel only. And the service policy files imported are limited in this commit to reduce scope of the change. Additionally, changes were made to the base action class to add support or setting policy rules and an overridable method for determining the policy check target. This reduces the need for redundant code in each action policy check. Note, the benefit Horizon has is that the underlying APIs will correct us if we get it wrong, so if a policy file is not found for a particular service, permission is assumed and the actual API call to the service will fail if the action isn't authorized for that user. Finally, adding documentation regarding policy enforcement. Implements: blueprint rbac Change-Id: I4a4a71163186b973229a0461b165c16936bc10e5
- Loading branch information
Showing
20 changed files
with
1,801 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
============================================================ | ||
Horizon Policy Enforcement (RBAC: Role Based Access Control) | ||
============================================================ | ||
|
||
Introduction | ||
============ | ||
|
||
Horizon's policy enforcement builds on the oslo-incubator policy engine. | ||
The basis of which is ``openstack_dashboard/openstack/common/policy.py``. | ||
Services in OpenStack use the oslo policy engine to define policy rules | ||
to limit access to APIs based primarily on role grants and resource | ||
ownership. | ||
|
||
The Keystone v3 API provides an interface for creating/reading/updating | ||
policy files in the keystone database. However, at this time services | ||
do not load the policy files into Keystone. Thus, the implementation in | ||
Horizon is based on copies of policy.json files found in the service's | ||
source code. The long-term goal is to read/utilize/update these policy | ||
files in Horizon. | ||
|
||
The service rules files are loaded into the policy engine to determine | ||
access rights to actions and service APIs. | ||
|
||
Horizon Settings | ||
================ | ||
|
||
There are a few settings that must be in place for the Horizon policy | ||
engine to work. | ||
|
||
``POLICY_FILES_PATH`` | ||
--------------------- | ||
|
||
Default: ``os.path.join(ROOT_PATH, "conf")`` | ||
|
||
Specifies where service based policy files are located. These are used to | ||
define the policy rules actions are verified against. This value must contain | ||
the files listed in ``POLICY_FILES`` or all policy checks will pass. | ||
|
||
.. note:: | ||
|
||
The path to deployment specific policy files can be specified in | ||
``local_settings.py`` to override the default location. | ||
|
||
|
||
``POLICY_FILES`` | ||
---------------- | ||
|
||
Default: { 'identity': 'keystone_policy.json', 'compute': 'nova_policy.json'} | ||
|
||
This should essentially be the mapping of the contents of ``POLICY_FILES_PATH`` | ||
to service types. When policy.json files are added to the directory | ||
``POLICY_FILES_PATH``, they should be included here too. Without this mapping, | ||
there is no way to map service types with policy rules, thus two policy.json | ||
files containing a "default" rule would be ambiguous. | ||
|
||
.. note:: | ||
|
||
Deployment specific policy files can be specified in ``local_settings.py`` | ||
to override the default policy files. It is imperative that these policy | ||
files match those deployed in the target OpenStack installation. Otherwise, | ||
the displayed actions and the allowed action will not match. | ||
|
||
``POLICY_CHECK_FUNCTION`` | ||
------------------------- | ||
|
||
Default: ``policy.check`` | ||
|
||
This value should not be changed, although removing it would be a means to | ||
bypass all policy checks. | ||
|
||
|
||
How user's roles are determined | ||
=============================== | ||
|
||
Each policy check uses information about the user stored on the request to | ||
determine the user's roles. This information was extracted from the scoped | ||
token received from Keystone when authenticating. | ||
|
||
Entity ownership is also a valid role. To verify access to specific entities | ||
like a project, the target must be specified. See the section | ||
:ref:`rule targets <rule_targets>` later in this document. | ||
|
||
How to Utilize RBAC | ||
=================== | ||
|
||
The primary way to add role based access control checks to panels is in the | ||
definition of table actions. When implementing a derived action class, | ||
setting the :attr:`~horizon.tables.Action.policy_rules` attribute to valid | ||
policy rules will force a policy check before the | ||
:meth:`horizon.tables.Action.allowed` method is called on the action. These | ||
rules are defined in the the policy files point to by ``POLICY_PATH`` and | ||
``POLICY_FILES``. The rules are role based, where entity owner is also a | ||
role. The format for the ``policy_rules`` is a list of two item tuples. The | ||
first component of the tuple is the scope of the policy rule, this is the | ||
service type. This informs the policy engine which policy file to reference. | ||
The second component is the rule to enforce from the policy file specified by | ||
the scope. An example tuple is:: | ||
|
||
("identity", "identity:get_user") | ||
|
||
x tuples can be added to enforce x rules. | ||
|
||
.. note:: | ||
|
||
If a rule specified is not found in the policy file. The policy check | ||
will return False and the action will not be allowed. | ||
|
||
The secondary way to add a role based check is to directly use the | ||
:meth:`~openstack_dashboard.policy.check` method. The method takes a list | ||
of actions, same format as the :attr:`~horizon.tables.Action.policy_rules` | ||
attribute detailed above; the current request object; and a dictionary of | ||
action targets. This is the method that :class:`horizon.tables.Action` class | ||
utilizes. | ||
|
||
.. note:: | ||
|
||
Any time multiple rules are specified in a single `policy.check` method | ||
call, the result is the logical `and` of each rule check. So, if any | ||
rule fails verification, the result is `False`. | ||
|
||
.. _rule_targets: | ||
|
||
Rule Targets | ||
============ | ||
|
||
Some rules allow access if the user owns the entity. Policy check targets | ||
specify particular entities to check for user ownership. The target parameter | ||
to the :meth:`~openstack_dashboard.policy.check` method is a simple dictionary. | ||
For instance, the target for checking access a project looks like:: | ||
|
||
{"project_id": "0905760626534a74979afd3f4a9d67f1"} | ||
|
||
If the value matches the ``project_id`` to which the user's token is scoped, | ||
then access is allowed. | ||
|
||
When deriving the :class:`horizon.tables.Action` class for use in a table, if | ||
a policy check is desired for a particular target, the implementer should | ||
override the :meth:`horizon.tables.Action.get_policy_target` method. This | ||
allows a programatic way to specify the target based on the current datum. The | ||
value returned should be the target dictionary. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
{ | ||
"admin_required": [["role:admin"], ["is_admin:1"]], | ||
"service_role": [["role:service"]], | ||
"service_or_admin": [["rule:admin_required"], ["rule:service_role"]], | ||
"owner" : [["user_id:%(user_id)s"]], | ||
"admin_or_owner": [["rule:admin_required"], ["rule:owner"]], | ||
|
||
"default": [["rule:admin_required"]], | ||
|
||
"identity:get_service": [["rule:admin_required"]], | ||
"identity:list_services": [["rule:admin_required"]], | ||
"identity:create_service": [["rule:admin_required"]], | ||
"identity:update_service": [["rule:admin_required"]], | ||
"identity:delete_service": [["rule:admin_required"]], | ||
|
||
"identity:get_endpoint": [["rule:admin_required"]], | ||
"identity:list_endpoints": [["rule:admin_required"]], | ||
"identity:create_endpoint": [["rule:admin_required"]], | ||
"identity:update_endpoint": [["rule:admin_required"]], | ||
"identity:delete_endpoint": [["rule:admin_required"]], | ||
|
||
"identity:get_domain": [["rule:admin_required"]], | ||
"identity:list_domains": [["rule:admin_required"]], | ||
"identity:create_domain": [["rule:admin_required"]], | ||
"identity:update_domain": [["rule:admin_required"]], | ||
"identity:delete_domain": [["rule:admin_required"]], | ||
|
||
"identity:get_project": [["rule:admin_required"]], | ||
"identity:list_projects": [["rule:admin_required"]], | ||
"identity:list_user_projects": [["rule:admin_or_owner"]], | ||
"identity:create_project": [["rule:admin_required"]], | ||
"identity:update_project": [["rule:admin_required"]], | ||
"identity:delete_project": [["rule:admin_required"]], | ||
|
||
"identity:get_user": [["rule:admin_required"]], | ||
"identity:list_users": [["rule:admin_required"]], | ||
"identity:create_user": [["rule:admin_required"]], | ||
"identity:update_user": [["rule:admin_or_owner"]], | ||
"identity:delete_user": [["rule:admin_required"]], | ||
|
||
"identity:get_group": [["rule:admin_required"]], | ||
"identity:list_groups": [["rule:admin_required"]], | ||
"identity:list_groups_for_user": [["rule:admin_or_owner"]], | ||
"identity:create_group": [["rule:admin_required"]], | ||
"identity:update_group": [["rule:admin_required"]], | ||
"identity:delete_group": [["rule:admin_required"]], | ||
"identity:list_users_in_group": [["rule:admin_required"]], | ||
"identity:remove_user_from_group": [["rule:admin_required"]], | ||
"identity:check_user_in_group": [["rule:admin_required"]], | ||
"identity:add_user_to_group": [["rule:admin_required"]], | ||
|
||
"identity:get_credential": [["rule:admin_required"]], | ||
"identity:list_credentials": [["rule:admin_required"]], | ||
"identity:create_credential": [["rule:admin_required"]], | ||
"identity:update_credential": [["rule:admin_required"]], | ||
"identity:delete_credential": [["rule:admin_required"]], | ||
|
||
"identity:get_role": [["rule:admin_required"]], | ||
"identity:list_roles": [["rule:admin_required"]], | ||
"identity:create_role": [["rule:admin_required"]], | ||
"identity:update_role": [["rule:admin_required"]], | ||
"identity:delete_role": [["rule:admin_required"]], | ||
|
||
"identity:check_grant": [["rule:admin_required"]], | ||
"identity:list_grants": [["rule:admin_required"]], | ||
"identity:create_grant": [["rule:admin_required"]], | ||
"identity:revoke_grant": [["rule:admin_required"]], | ||
|
||
"identity:list_role_assignments": [["rule:admin_required"]], | ||
|
||
"identity:get_policy": [["rule:admin_required"]], | ||
"identity:list_policies": [["rule:admin_required"]], | ||
"identity:create_policy": [["rule:admin_required"]], | ||
"identity:update_policy": [["rule:admin_required"]], | ||
"identity:delete_policy": [["rule:admin_required"]], | ||
|
||
"identity:check_token": [["rule:admin_required"]], | ||
"identity:validate_token": [["rule:service_or_admin"]], | ||
"identity:validate_token_head": [["rule:service_or_admin"]], | ||
"identity:revocation_list": [["rule:service_or_admin"]], | ||
"identity:revoke_token": [["rule:admin_or_owner"]], | ||
|
||
"identity:create_trust": [["user_id:%(trust.trustor_user_id)s"]], | ||
"identity:get_trust": [["rule:admin_or_owner"]], | ||
"identity:list_trusts": [["@"]], | ||
"identity:list_roles_for_trust": [["@"]], | ||
"identity:check_role_for_trust": [["@"]], | ||
"identity:get_role_for_trust": [["@"]], | ||
"identity:delete_trust": [["@"]] | ||
} |
Oops, something went wrong.