-
Notifications
You must be signed in to change notification settings - Fork 1
Overview
PyPElib is a small library that provides programmers with abstractions so they can build Policy Engine(s) within a certain scope of action. It is part of the OFELIA Control Framework software, which has been developed within joint activities between OFELIA and FIBRE EU-BR FP7 projects.
It supports:
- Rule-based policy enforcement
- Rule-based action triggering, logging
- Multiple scope support within an application
- Multi-syntax support
- Flexible syntax customization (
Resolver
and mappings ) - Multiple persistence back-ends
The aim of the library has been to encapsulate the basic policy engine code and to be used in several different software components of the CF --therefore allowing to easily customize the behavior for each of those components-- but maintaining a common policy management base code.
The library is meant to provide Rule-based policy enforcement mechanisms; one could easily find similarities with IPtables. The main interface for the programmer to do so is using so-called RuleTable
class.
####RuleTable
Each RuleTable
instance is meant to encapsulate a set of policies for a certain scope (e.g. processing interface requests). The result of an evaluation will always be a True/False value. Each table has a set of rules and a default policy (DENY/ACCEPT) in case no rules match.
The following diagram exposes a simple workflow:
evaluate()
's RuleTable
method expects an object as input, which generally encapsulates the basic information which needs to be checked (typical examples, requests, RSPECs...), and verifies against the ruleset (in order). However, rules may interact with other classes/functions or modules of the application to obtain extra information (see Condition
and mappings for more information).
Rules can be modified, reordered or deleted on the fly and --if required-- persisted using a back-end.
####Rule
Rules are internal objects used to represent a specific policy. In general they are not meant to be used by the users of the library but rather used through a parser/crafter to construct such objects.
There are fundamentally two types of rules:
- Terminal rules: which upon a match of the condition, break the rule lookup loop and return Rule's ACCEPT/DENY value.
- Non-terminal rules (a.k.a action rules): they do not break the rule lookup loop in case of match, and they are meant to perform actions without returning any value (a typical example is for logging and statistical purposes).
####Conditions, Resolver, Mappings and parsing modules
Conditions, as rules, are internal objects which in general are not meant to be used by the users of the library, but rather used through a parser/crafter to construct such objects. Each rule must have a condition which might be simple (e.g. A<5) or complex, containing sub-conditions.
However, is interesting to expose how using the mappings --and regardless of the parsing module-- syntax can be customized and adapted without touching the parsing modules. Consider the following rule definition, specifically the condition clause (RegexParser
):
if vm.memory > 256 then DENY denyMessage Memory limit is 256MB
Indeed one can use this simple notation to access vm.memory
field, without having to explicitly modify the parser, add special parsing routines and so on thanks to the mappings and the Resolver
class.
Consider the following mappings for the example above:
_mappings = {
"vm.name":"metaObj['name']", #metaObj is the object passed to evaluate() routine of RuleTable
"vm.memory":"metaObj['memory']",
#...
}
Mappings are used as follows to instantiate a RuleTable
:
myTable = RuleTable("My Engine",_mappings,defaultParser=RegexParser, pType=False)
Note that you can easily point these keywords to any object contained in the metaObj
, any static value or any global function that returns required value, without touching the parsing modules (parser treats those keywords as strings, bypassing them):
_mappings = {
"vm.name":"metaObj['name']",
"vm.memory":"metaObj['memory']",
"project.vms":"app.models.Project.getVms" #function must be defined as "def getVms(metaObj)"
"staticValue": "10",
#...
}
###Supported syntax parsers
Current supported parsers:
-
RegexParser
: simple regular expression-based parser
####RegexParser
Syntax is as follows:
if <[not] cond> then <return_value> [nonterminal] [do <action>] [denyMessage <error_message>] [#<rule_comment>]
-
<return_value>
: must be accept or deny -
<cond>
: must be a simple or complex condition- Simple conditions:
- Operators:
- Comparison:
<
,>
,<=
,>=
,=
or!=
- Ranges:
in range [<rangeBoundaries>]
orin range {<rangeBoundaries>}
(boundaries included or excluded) - Collection:
in collection [<itemsCollection>]
- Comparison:
- Operators:
- Complex conditions
- Operators: boolean
&&
or||
- Optional
not
particle, negates condition
- Operators: boolean
- Simple conditions:
Optional parameters:
-
nonterminal
:Rule
is nonterminal (a.k.a. action rules). An action must be specified -
do <action>
: action must be a keyword resolvable byResolver
-
denyMessage <error_message>
: text to be displayed when action is denied, where action must be a keyword to be resolved byResolver
-
#<rule_comment>
: comment to be displayed only for debugging while using pypelib
Examples (not in order):
if ( vm.RAM < 128 ) then accept
if not request.user in collection {user1,user2,user3} then deny do log # Deny requests from user1, 2 and 3
if not vm.RAM in range [64,256] then deny # Accept only VMs with RAM between 64 and 256Mb
if ( vm.RAM > 128 ) && (user.id = myUser) then deny <denyMessage> # Specific user filter
- RAWFile: raw file serialization backend (mainly to use in testing environment)
- Django: Django SQL based backend (Django framework is required to use this driver)
-
Note: when using this back-end make sure to modify the 'Meta' information for both
Rule
andRuleTable
models:-
app_label
(your database name) -
db_table
(your table name)
-
-
Note: when using this back-end make sure to modify the 'Meta' information for both
The example contained in the package emulates a simple entry point interface, in which certain policies need to be applied. The example emulates a couple of queries and plays with the policy table.
Main files:
- main.py: emulates the interface client
- interface.py: defines interface function/method (e.g. an XMLRPC method)
-
MyPolicyEngine.py: contains the
RuleTable
instance. An application may have multiple engines orRuleTable
instances - database/: database contents
To run the example simply execute:
apt-get install python-pyparsing
cd pypelib/example
python main.py