# Grants and Rules
The primary purpose of using embedded Grant rules is to manage access rights that allow for limiting access to a subset of permissions. At first glance, Grant rules may look complex, but they serve specialized purposes.
The role must include permissions referenced by the rules in part. The Condition allows to set limits over resources, and Traversal denotes a set of roots (starting points) for that Information Model to traverse.
# Condition
A Condition is a specific filter expressed in Query Expression Language (QEL) based on the selected properties of a Permission. It has a dual purpose. The primary use is to limit grants based on certain properties specific for each Permission. In more elaborate examples, it allows to define a starting point and boundaries of DSL traversal.
Supported properties
Conditions can only contain properties supported by all accessed resources.
As a rule of thumb, it's better to start with creating the most detailed rules first and finish with the most common. This will allow us to create less complex rules and avoid overlapping.
The Admin Portal provides dynamic suggestions of condition content suggestions based on the selected Resource.
# Sample rule without Traversal - walkthrough
Let's assume that we would like to limit the user to only see the alarms of a single device (single object model). To achieve this, follow these short instructions:
- In the Solution tab of our web app, create a Role and Grant, and add a Permission to read alarms.
- In the Grant tab, add a Rule to limit read alarms Permission to a single objectId
By doing this, users with this Grant will have a combination of two limitations upon requesting a JWT token:
- the user can interact with the token's Tenant (Principal Manager API automatically adds this)
- the ability to query alarms is limited to just a single object model
# Traversal
Traversal allows creating a more elaborate set of rules based on the current state of the traversable data source, namely the Information Model. This capability is possible by utilizing a subset of a DSL query language for denoting a traversal for the Rule.
Graph representation
Traversals are only applicable for resources with a graph representation. If a Traversal is not present, only the resources that match the above Condition will be accessible.
This fact means that not all DSL constructs cannot be mapped directly into Traversal and required conscious action by the solution development team to split it between:
- Condition - used to define the root of a traversable tree in the QEL
- Traversal - used to define the route from the root to the desired leaf elements using DSL, and to specify the range of object models to which the Grant rule applies
# Combining Conditions and Traversals in practice
We can now dive deeper into more complex examples with a traversable Information Model.
In this case, we would like to limit the user to only read the object model properties of a specific object model (02fe1668-b100-4435-aca8-3f700954125a
) and its references (thermostats
) using Conditions and Traversals.
Let's start from the DSL query below to define the correct rule limitation.
models('abb.ability.device').hasObjectId('02fe1668-b100-4435-aca8-3f700954125a').outReference('thermostats').toModel()
Based on what we already know from this article, we have to split this query into a Condition and a Traversal, where the root would need to be defined as a Condition and the route as a Traversal.
Possible validation issues
Since there are multiple ways to write Conditions and Traversals, some of the combinations would result in validation issues. For example:
Condition: model= 'abb.ability.device'
Traversal: hasObjectId('02fe1668-b100-4435-aca8-3f700954125a').outReference('thermostats').toModel()
Permissions: object_model_read
This is an incorrect setup, since the root object has been defined partially in a Condition model= 'abb.ability.device'
and partially in a traversal hasObjectId('02fe1668-b100-4435-aca8-3f700954125a')
.
To correct this, we would need to move this part of the rule from the Traversal into a Condition or, as shown in the image above, move hasObjectId('02fe1668-b100-4435-aca8-3f700954125a')
into a Condition, since it's enough to define the root object for a Traversal.
After reviewing the JWT token, we can see how each rule impacts
claims. Be aware, that in
this case additional .repeat
and .until
add more tenancy constraints on the rule.