Monday, June 20, 2016

Apache Fortress instead of policy.json in Openstack Keystone

Openstack uses json file (policy.json) to set rules for Role Based Access Control. But this approach is not very elegant and has several problems.
Let's take a look how we can replace policy.json by Apache Fortress - access management system based on ANSI Role-Based Access Control (INCITS 359) standard. Apache Fortress stores rules in OpenLDAP or ActiveDirectory and has a nice Web interface:


File policy.json

 File policy.json stores rules. Usually it looks like this:

{
    "admin_required": "role:admin or is_admin:1",
    "service_role": "role:service",
    "service_or_admin": "rule:admin_required or rule:service_role",
    "owner" : "user_id:%(user_id)s",
    "admin_or_owner": "rule:admin_required or rule:owner",
    "token_subject": "user_id:%(target.token.user_id)s",
    "admin_or_token_subject": "rule:admin_required or rule:token_subject",
    "service_admin_or_token_subject": "rule:service_or_admin or rule:token_subject",

    "default": "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_required",
    "identity:delete_user": "rule:admin_required",
    "identity:change_password": "rule:admin_or_owner",

    "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",

....
}
The meaning is very simple:
  • There is an object "identity"
  • The object "identity" has operations: "get_user", "list_users", ...
  • For each pair of object and operation there is rule
  • Rules are described in the top of file
This is very simple and flexible implementation of RBAC. But there are some problems:
  1. What if we already have rules and permissions and want to map them? In this case we have to manually create policy.json file and this task could be a real problem.
  2. We have to restart service after each change in policy.json file.
  3. json file is just not easy to manage for human. Humans likes to have some interface for management.

Apache Fortress

Apache Fortress has the following components:
  • Core - Java Access Management SDK
  • Realm - Java EE security for Apache Tomcat
  • Rest - HTTP protocol wrappers for the APIs
  • Web - HTML pages for the APIs
Apache Fortress uses OpenLDAP or ActiveDirectory as a storage.


Actually it is very similar to what we have in policy.json file:
  • There is an object "identity" (ftObjNm=identity)
  • The object identity has operations: "list_roles", "list_users"
  • For each pair of object and operation there is permission (we call it 'rule' in policy.json file)
  • Permissions can be granted to some role
Now you can see that we can transfer data from policy.json file into OpenLDAP by using Apache Fortress schema.
Apache Fortress implements ANSI specification of RBAC. This specification can be illustrated by following picture:


Apache Fortress also has Web and REST interfaces. Let's take a look at it Web interface.
Here is users-management page:

We are going to follow user "steve". Steve has role "user".
Let's take a look at roles-management page:

 There is also objects-management page. And we have an object "identity" there:


And finally there is permissions-management page where all entities comes together:


 Users with role "user" allowed to "list_roles" for object "identity".

How to use Apache Fortress in OpenStack?

  1. Store users in OpenLDAP or ActiveDirectory
  2. Install Apache Fortress: http://xuctarine.blogspot.ru/2015/10/how-to-install-apache-fortress-with.html
  3. Create entities you need: objects, operations, permissions.
  4. Extend oslo.policy. There is 2 possible ways to communicate with Apache Fortress:
    1. by REST API (https://review.openstack.org/#/c/237521/)
    2. by LDAP protocol (https://review.openstack.org/#/c/244059/)
  5. Use new oslo.policy class in application. For Keystone it means that you have to replace "Enforcer" with "FortressEnforcer" in one place of code.
And it really works! To prove it I have a video demo of Apache Fortress usage instead of policy.json file (Videos are in HD format, so set HD format by clicking  "HD" in right-bottom corner of player if Vimeo is not set it by default for you)
  1.  REST API: https://vimeo.com/143715477
  2. LDAP: https://vimeo.com/146109801

No comments:

Post a Comment