Jump to: navigation, search

PolicyDatabase

Revision as of 12:31, 3 March 2015 by David Chadwick (talk | contribs) (Database Schema)

Policy Relational Database Schema for Openstack

Overview

This document describes a relational database schema that stores security policies for Openstack.

An OpenStack Policy file comprises a set of policy rules. For example, "identity:create_region": "role:admin or is_admin:1" may be a policy rule from Keystone's policy file. This says that the principal must either be the administrator or have the role of admin in order to create a region with the identity API. A policy rule logically comprises a set of conditions. The example policy rule comprises the following conditions: service equals the identity API AND action equals create_region AND (role equals admin OR is_admin equals TRUE).

OpenStack policies are stored in the database in Disjunctive Normal Form (DNF). The DNF stores sets of simple conditions combined by the AND logical operator, and each set is combined by the OR logical operator. Each policy rule will form one or more sets of simple conditions.

The DNF policy structure can be represented by the tree structure below.

                    OR  
                /    |    \
             AND    AND    AND .......
           /  | \    |    /   \
          C1 C2 C3  C4   C5   C6

Using the example policy rule from above, this converts into the following simple conditions:

  • C1: role = "admin"
  • C2: is_admin = TRUE
  • C3: service = "identity"
  • C4: action = "create_region"


The policy rule in DNF forms two sets of simple conditions, namely:

(C3 and C4 and C1) or (C3 and C4 and C2)

Database Schema

The following figure presents the database schema to store security policies in Openstack.

Policy Database Schema

Each of these tables are detailed below.

Policy

Represents the Openstack Policy.

The id is the unique key for this policy.

The description field is optional, and describes the meaning of the Policy.

AND Rule

Each "AND rule" comprises the following.

The id is the unique key for this AND rule

policy_id is the ID of the policy that this rule is for.

description is the optional description of this AND rule.

Enabled is a Boolean saying whether this AND rule is active or not. The default value is True. By setting the value to False this allows us to remove this whole set of ANDed conditions from the policy.

Condition

A condition represents the basic element of a policy. A condition comprises an attribute, an operator and a value. The policy engine will verify if the value of the "attribute" from the request matches with the "value" field in the condition, according to the operator.

A value can be a literal (e.g. a string or a number) or a variable (e.g., %(user_id)s) which will be evaluated by the Policy Engine.

Attributes can be of different types, for instance:

  • Service

Services are represented in the policy.json file by "service:action" entries e.g. "identity:create_protocol", where "identity" is the service.

  • Action

Actions are represented in the policy.json file by "service:action" entries e.g. "identity:create_protocol", where "create_protocol" is the service.

  • Role

Roles in Openstack represent Subjects. A user in a domain or project can be directly assigned to roles, or can be part of a group which is assigned to a role.

  • Other types

Despite the fact that Openstack uses an RBAC engine, it allows other types of attribute checking in its policies, for example, user_id and project_id.


And_Rule_has_Condition

Conditions are combined in the And_Rule_has_Condition table. This table represent a many to many relationship between conditions and AND rules.

This allows a single condition to be part of multiple "AND Rules".

Supported Operations

Policies stored in the database will support CRUD operations on policies, and also complex SQL queries, for instance, to find out which are the necessary conditions to perform a given action.

Besides these, two operations will also be supported:

  • Import policy.json file into the database: In this operation, policies conflicts will be eliminated. Duplicate rules will also be removed.
  • Export policies from database to new policy.json files. These new files will reflect the managed set of rules. It's important to say that, since rules are decomposed to DNF and not stored in it's original syntax, the new generated policy files will be semantically equivalent to their original, but can be syntactically different.

Importing a policy file to the Database Schema

Introduction

In order to show how the Database Scheme is applicable, we present a database representation for the following lines from Keystone's policy.json.

   "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",
   "identity:list_regions": "",
   "identity:create_region": "rule:admin_required",
   "identity:ec2_create_credential": "rule:admin_or_owner",
   "identity:create_trust": "user_id:%(trust.trustor_user_id)s",
   "identity:ec2_delete_credential": "rule:admin_required or (rule:owner and user_id:%(target.credential.user_id)s)",

Labels

The 5 first lines constitute a set of conditions combined with AND or OR operators, which are assigned to a "label" in the syntax below.

"<label>" : "<conditions>"

Labels act as macros, in order to simplify the policies to be read by humans. Labels are not singly evaluated, since they are not assigned to any service/action. Because of that, they are stored as one or more conditions, which are not necessarily attached to the DNF structure or to a Policy.

Rules

The last 5 lines constitute of rules which are evaluated when an action (API entry) is called in a Service. Rules are represented by the following syntax:

"<service>:<action>" : "<conditions>"

Services are attached to the DNF structure, which is attached to a Policy.

Converting entries in Conditions

Each line of the example will be converted in one or more condition. A condition is composed by an attribute and a value.

Conditions are represented in this example as:

C<id>: <attr> = <value>
Labels

   "admin_required": "role:admin or is_admin:1",

  • C1: role = "admin"
  • C2: is_admin = 1
    • L("admin_required"): C1 or C2

   "service_role": "role:service",

  • C3: role = "service"
    • L("service_role"): C3

   "service_or_admin": "rule:admin_required or rule:service_role",

Rules elements points to labels.

    • L("service_or_admin"): L("admin_required") or L("service_role")
    • L("service_or_admin"): (C1 or C2) or C3

   "owner" : "user_id:%(user_id)s",

  • C4: user_id = "%(user_id)s"
    • L("owner"): C4

   "admin_or_owner": "rule:admin_required or rule:owner",

    • L("admin_or_owner"): L("admin_required") or L("owner")
    • L("admin_or_owner"): (C1 or C2) or C4
Rules

   "identity:list_regions": "",

  • C5: service = "identity"
  • C6: action = "list_regions"
    • R("identity:list_regions"): C5 and C6

   "identity:create_region": "rule:admin_required",

  • C7: action = "create_region"
    • R("identity:create_region"): C5 and C7 and L("admin_required")
    • R("identity:create_region"): C5 and C7 and (C1 or C2)
    • R("identity:create_region"): (C5 and C7 and C1) or (C5 and C7 and C2) in DNF

   "identity:ec2_create_credential": "rule:admin_or_owner",

  • C8: action = "ec2_create_credential"
    • R("identity:ec2_create_credential"): C5 and C8 and L("rule:admin_or_owner")
    • R("identity:ec2_create_credential"): C5 and C8 and (C1 or C2 or C4)
    • R("identity:ec2_create_credential"): (C5 and C8 and C1) or (C5 and C8 and C2) or (C5 and C8 and C4) in DNF

   "identity:create_trust": "user_id:%(trust.trustor_user_id)s",

  • C9: action = "create_trust"
  • Ca: user_id = "%(trust.trustor_user_id)s"
    • R("identity:create_trust"): C5 and C9 and CA

   "identity:ec2_delete_credential": "rule:admin_required or (rule:owner and user_id:%(target.credential.user_id)s)",

  • Cb: action = "ec2_delete_credential"
  • Cc: user_id = "%(target.credential.user_id)s"
    • R("identity:ec2_delete_credential"): C5 and Cb and (L("admin_required") or (L("owner") and Cc))
    • R("identity:ec2_delete_credential"): C5 and Cb and ((C1 or C2) or (C4 and Cc))
    • R("identity:ec2_delete_credential"): C5 and Cb and ((C1 or C2) or (C4 and Cc))
    • R("identity:ec2_delete_credential"): C5 and Cb and (C1 or C2 or (C4 and Cc))
    • R("identity:ec2_delete_credential"): (C5 and Cb and C1) or (C5 and Cb and C2) or (C5 and Cb and C4 and Cc) in DNF

Conditions C1 to Cc are candidate to be stored in the "condition" table.

Building the AND_Rule and And_Rule_has_Condition tables

Each "AND" block from the rules above represents an entry in the AND table. We will illustrate them below. The association of And Rules and Conditions are stored in the "and_rule_has_condition" table.

  • R("identity:list_regions"): C5 and C6
    • A1: C5 and C6
  • R("identity:list_regions"): A1


  • R("identity:create_region"): (C5 and C7 and C1) or (C5 and C7 and C2)
    • A2: C5 and C7 and C1
    • A3: C5 and C7 and C2
  • R("identity:create_region"): A2 or A3


  • R("identity:ec2_create_credential"): (C5 and C8 and C1) or (C5 and C8 and C2) or (C5 and C8 and C4)
    • A4: C5 and C8 and C1
    • A5: C5 and C8 and C2
    • A6: C5 and C8 and C4
  • R("identity:ec2_create_credential"): A4 or A5 or A6


  • R("identity:create_trust"): C5 and C9 and CA
    • A7: C5 and C9 and CA
  • R("identity:create_trust"): A7


  • R("identity:ec2_delete_credential"): (C5 and Cb and C1) or (C5 and Cb and C2) or (C5 and Cb and C4 and Cc)
    • A8: C5 and Cb and C1
    • A9: C5 and Cb and C2
    • Aa: C5 and Cb and C4 and Cc
  • R("identity:ec2_delete_credential"): A8 or A9 or Aa

Since all Roles are combined in a unique "Or" entry, roles are not directly represented in the Database schema. Nevertheless, they can be easily recovered by searching for entries of the same "service"+"action" from the "AND_Rule" table.

Tables

All tables in this section are populated according to the example above.

policy
id description or_rule_id version enabled scope_id
"a2f57b" "Openstack Security Policy" "5e98b2" "2015-02-26 14:00:00" TRUE NULL
or_rule
id label version enabled
"5e98b2" "OR Rule for Openstack Security Policy" "2015-02-26 14:00:01" TRUE
and_rule
id label version enabled
"000001" "identity:list_regions" "2015-02-26 14:01:01" TRUE
"000002" "identity:create_region_001" "2015-02-26 14:01:02" TRUE
"000003" "identity:create_region_002" "2015-02-26 14:01:03" TRUE
"000004" "identity:ec2_create_credential_001" "2015-02-26 14:01:04" TRUE
"000005" "identity:ec2_create_credential_002" "2015-02-26 14:01:05" TRUE
"000006" "identity:ec2_create_credential_003" "2015-02-26 14:01:06" TRUE
"000007" "identity:create_trust" "2015-02-26 14:01:07" TRUE
"000008" "identity:ec2_delete_credential_001" "2015-02-26 14:01:08" TRUE
"000009" "identity:ec2_delete_credential_002" "2015-02-26 14:01:09" TRUE
"00000A" "identity:ec2_delete_credential_003" "2015-02-26 14:01:10" TRUE
or_rule_has_and_rule
or_rule_id and_rule_id
"5e98b2" "000001"
"5e98b2" "000002"
"5e98b2" "000003"
"5e98b2" "000004"
"5e98b2" "000005"
"5e98b2" "000006"
"5e98b2" "000007"
"5e98b2" "000008"
"5e98b2" "000009"
"5e98b2" "00000A"
"5e98b2" "00000B"
"5e98b2" "00000C"
"5e98b2" "00000D"
"5e98b2" "00000E"
"5e98b2" "00000F"
attribute
id description
"A00001" "service"
"A00002" "action"
"A00003" "role"
"A00004" "is_admin"
"A00005" "user_id"
condition
id label attribute_id value version enabled
"C00001" "role:admin" "A00003" "admin" "2015-02-26 14:02:01" TRUE
"C00002" "is_admin:1" "A00004" "1" "2015-02-26 14:02:02" TRUE
"C00003" "role:service" "A00003" "service" "2015-02-26 14:02:03" TRUE
"C00004" "user_id:%(user_id)s" "A00005" "%(user_id)s" "2015-02-26 14:02:04" TRUE
"C00005" "service_identity" "A00001" "identity" "2015-02-26 14:02:05" TRUE
"C00006" "action_list_regions" "A00002" "list_regions" "2015-02-26 14:02:06" TRUE
"C00007" "action_create_region" "A00002" "create_region" "2015-02-26 14:02:07" TRUE
"C00008" "action_ec2_create_credential" "A00002" "ec2_create_credential" "2015-02-26 14:02:08" TRUE
"C00009" "action_create_trust" "A00002" "create_trust" "2015-02-26 14:02:09" TRUE
"C0000A" "user_id:%(trust.trustor_user_id)s" "A00005" "%(trust.trustor_user_id)s" "2015-02-26 14:02:10" TRUE
"C0000B" "action_ec2_delete_credential" "A00002" "ec2_delete_credential" "2015-02-26 14:02:11" TRUE
"C0000C" "user_id:%(target.credential.user_id)s" "A00005" "%(target.credential.user_id)s" "2015-02-26 14:02:12" TRUE
and_rule_has_condition
and_rule_id condition_id
"000001" "C00005"
"000001" "C00006"
"000002" "C00005"
"000002" "C00007"
"000002" "C00001"
"000003" "C00005"
"000003" "C00007"
"000003" "C00002"
"000004" "C00005"
"000004" "C00008"
"000004" "C00001"
"000005" "C00005"
"000005" "C00008"
"000005" "C00002"
"000006" "C00005"
"000006" "C00008"
"000006" "C00004"
"000007" "C00005"
"000007" "C00009"
"000007" "C0000A"
"000008" "C00005"
"000008" "C0000B"
"000008" "C00001"
"000009" "C00005"
"000009" "C0000B"
"000009" "C00002"
"00000A" "C00005"
"00000A" "C0000B"
"00000A" "C00004"
"00000A" "C0000C"