📜 ⬆️ ⬇️

Implementation of the access system in its own corporate messenger: part one

Recently, we have implemented an access system in the corporate messenger of the company and would like to share with those who have little experience in solving such problems their own developments in a small series of articles. For convenience of presentation, we have divided the material into two parts: this article will describe in detail all the components of the system, and we will devote a separate post to the explanation of their interaction and working principles in the near future.


Backend for the messenger is written in Go, so the examples will be in this language. Not wanting to reinvent the wheel, we decided to base XACML - the standard for ABAC (Attribute-Based Access Control) - and simplify it as much as possible so that it is suitable for our task. We want to note that we did not set a goal to write our own implementation of XACML. It was taken as an example of a working system from which we could extract the experience we needed.

There are excellent articles for exploring XACML and ABAC:
')
Introduction to XACML - a standard for Attribute-Based Access Control
Access Control Approaches: RBAC vs. ABAC

Basic system objects and AttributeCalculater interface


Immediately tell about the interface AttributeCalculater , as it will be found below. In fact, it consists of three other interfaces, but for brevity, we will limit ourselves to simply writing down all of its methods. It must be implemented by all objects of the application model that interact with the access system.

type AttributeCalculater interface {   Counter() (AttributeCalculater, error)   Equally(Getter) bool   Belong(Getter) bool   GetType() string   GetValue() (AttributeCalculater, error)   GetValueField(string) (AttributeCalculater, error)   GetInt() (int, error)   GetBool() (bool, error)   GetString() (string, error) } 

The system uses two main types of objects: Rules and Policies. This is enough for our task, so we did not use groups of politicians as superfluous.

Rule


A rule is the simplest object in the system that is used to describe business rules. Here is its structure:

 type rule struct {  Name     string  Condition condition  Effect   ruleEffect } func (r *rule) calculate(cntx *Context) calculateResult {} 

The calculate method calculates a rule, that is, returns a value that says whether the request can be executed or not, or reports an error that has occurred. To do this, the method is passed a context that contains all the necessary information for the calculation.

 type Context struct { Object   AttributeCalculater Subject  AttributeCalculater Target   Action } 

A context consists of an object (object) - an entity that implements the AttributeCalculater interface and with which the access system performs some actions, a subject (subject) - an entity that also supports the AttributeCalculater interface and is usually a user who wants to perform a specific action in an application. The target is an enum that lists all possible actions supported by the access system. For example: add a user to the correspondence, write a message, assign an administrator of the correspondence, etc.

Name (name) of the rule is necessary first of all for the person who works with him - it does not affect the process of calculation in any way.

The effect (effect) shows how the result of the condition calculation will be processed. An effect can be permitting ( permitEffect ) or disabling ( denyEffect ). Say, if the result of the condition evaluation is true , and the effect is given as permitEffect , then the result of the rule calculation will also be true . If the effect is registered as denyEffect , then the result of the rule will be false .

Condition (condition) is the most important part of the rule, in which, in fact, the condition for it is described and calculated.

 type condition struct { FirstOperand Attribute SecondOperand Attribute Operator conditionOperator } func (c *condition) calculate(cntx *Context) (bool, error) {} 

The calculate method calculates a condition. It is similar to the similar method for a rule, only its return values ​​are different. The condition may be true, incorrect, or report an error.

The operator is responsible for comparing the two operands. Accepts the following values:


As can be seen from the structure, the condition can be calculated only for two operands, that is, one rule does not assume to consider complex use cases that arise when working with an access system. To do this, use a combination of rules.

The data type of the operands is Attribute (attribute). It contains information for calculating conditions.

 type Attribute struct { NameObject string Field   string Type    TypeAttribute Object   AttributeCalculater } func (a *Attribute) getValue(c *Context) (AttributeCalculater, error) {} 

The getValue method returns the attribute value. It is returned as an object that has the AttributeCalculater interface implemented.

NameObject (object name) from which the value from the Field is taken when calculating an attribute. The object itself is in the Object field.

Politics


Policies are used to describe business rules with one or more rules.

 type politic struct { Name       string Target      Action Rules      []rule CombineAlgorithm combineAlgorithm } func (p *politic) calculate(cntx *Context) calculateResult {} 

Name (name) of a policy, like a rule, is needed only for the person who works with it.

Targer (target) is used to search for policies. For simplicity in our system, each goal has its own policy.

Rules (rules) - a set of simple rules that complement each other can describe complex business rules.

CombineAlgorithm of rules specifies how to process the results of the calculation of policy rules. In XACML, these algorithms can be quite complex, but in our case, all these delights are not needed. Therefore, we have so far only two simple algorithms, permitIfAllPermitted (allow, if everyone is allowed) and permitIfOnePermitted (allow, if one is allowed). For example, if the permitIfAllPermitted algorithm is installed , the result of the policy calculation will be positive only if all the rules in this policy also had a positive result.

Here are the main parts that make up our access system. In the next article we will take a closer look at how this all works.

Source: https://habr.com/ru/post/329760/


All Articles