libamxa
0.11.0
Access control verification
|
Disclaimer: this documentation is not final and is subject to change during development.
[[TOC]]
Access control is important when dealing with untrusted parties. Access rights must be verified at the border of the host resident firmware. Internal components (within the firmware) are assumed to be trusted and can communicate freely using the available bus. This means that ACL verification is needed when
Note that this last type of request will pass through the host system before being forwarded to the container.
Access control verification within Ambiorix is based on the USP Role Based Access Control (RBAC) system. A process at the gateway border (typically a USP agent) will verify the role of the entity that wishes to interact with the gateway data model (typically a USP controller). Based on its role, the requestor is allowed to access or prevented from accessing certain data model elements.
Note: To simplify the syntax in the remainder of this document, we will speak of a USP agent as the process that verifies ACLs and a USP controller as the requesting process. However, when the gateway is accessed through the web-ui for example, ACLs must also be verified using the same mechanisms as for a USP agent.
To validate the ACLs, a USP agent will need the following things:
ACL verification within Ambiorix is implemented based on the USP RBAC system, which can be summarized by the Device.LocalAgent.ControllerTrust.Role.{i}.
data model. Any USP controller will have one or multiple roles, which are listed in this data model. Each Role.{i}.
object has a set of Role.{i}.Permission.{i}.
elements specifying the permissions that correspond to the Role.
A permission object has the following parameters to set/restrict access rights:
Param
: permission information related to parameters.Obj
: permission information related to objects.InstantiatedObj
: permission information related to instances.CommandEvent
: permission information related to commands and events.Each of these parameters is a string of 4 characters "rwxn", where each character represents a permission ("r" for Read, "w" for Write, "x" for Execute and "n" for Notify). The string is always in the same order (rwxn) and the lack of a permission is signified by using a "-" character (e.g. "r--n" would imply read permission and permission to receive notifications for the targeted data model).
For detailed information explaining what each character gives access to, refer to the TR-181 data model
Besides the permission parameters, the Permission
object also has a Targets
parameter to indicate which data model path the permissions apply to and an Order
parameter, to handle overlapping Targets
. A higher Order
means the permissions of overlapping Targets
will be overridden. This is mainly important when using search paths in the Targets
.
The Ambiorix ACL system reuses the parameters of this Permission object for specifying the various permissions, however, instead of dumping all that information in the data model, ACL files in JSON format are used.
Take a look at the section about Roles (Access Control) in the USP specification for more information about RBAC.
An ACL file will have the following format:
It is important to note that by default no permissions are granted. Each permission explicitly needs to be set with one of the rwxn
strings. Note that the following 2 ACL files give the exact same permissions:
In the first file, all parameter access is disabled by using dashes -
for each character in the Param
string. In the second file, the entire Param
section is missing, which also implies no parameter access is granted for the user.
Also note that when permissions are granted for a root object, users with the role to which the permissions apply will have access to everything under the root object. For example:
will give access to everything under the Device.IP.
object (as specified in TR-181). There is no need to add separate rules for granting access to sub-objects. It is of course possible to further restrict access to certain sub-objects by adding an extra rule:
Note that the second rule has a higher order, so it will take precedence over the first rule. If the orders were swapped, the second rule would have no effect (think about this).
ACL rules can also be written with USP search paths:
Finally note that the above 2 rules could be written in a single ACL file or in 2 separate ACL files. The acl-manager
will make sure they are merged together.
Now that you understand what ACL files look like, it is important to know how they can be applied to the different roles. By default 4 roles will be defined:
All ACL files for a role need to be installed in the /etc/acl/<role>/
directory. The acl-manager
will make sure the files are merged together to a single file per role for easy verification of access rights. More on this in the next section.
As explained above, ACL files can contain rules with overlapping targets, different orders, search paths and can be written in one or multiple files. That's why there is a need for an acl-manager
. The acl-manager
is responsible for reading all ACL files that belong to a certain role and merging them together to a single "master" ACL file. This "master" ACL file will serve as the single source of truth for handling ACL verification and must be used by the USP agent (or other processes at the gateway borders).
Access rules can generally be defined in 2 ways:
Device.LocalAgent.ControllerTrust.Role.{i}.Permission.{i}.
data modelOn startup the acl-manager
will copy all files from /etc/acl/
to /cfg/etc/acl/
, which is guaranteed to be a writable directory on the devices we use. It will merge files together to a single file in /cfg/etc/acl/merged/<role>.json
, which can be used to verify access rights for the role.
At any time, these rules can be updated by adding extra ACL files to /cfg/etc/acl/
or new instances in the ControllerTrust
data model (which will in turn add ACL files to /cfg/etc/acl/
).
NOTE:
At compile time/install time all known ACL files are installed to the/etc/acl/<role>/
directory, which is a reboot persistent directory. Depending on the embedded target and chosen filesystem, the directory will be read-only. Because the/cfg/
directory is writable on all devices we use, all ACL files are copied here on startup of theacl-manager
. If anything is added dynamically at runtime, it should also be added to/cfg/etc/acl/<role>/
.
NOTE:
/etc/acl/
and/cfg/etc/acl/
are the default directories used for ACL files. It is recommended to make these paths configurable, similar to how it was done for the acl-manager.
Whenever something changes, the correct access rights need to be recalculated because these changes could override any of the existing rules. Therefore, the acl-manager
will monitor the acl directories and recalculate the master acl file for a role every time a file is changed, added or removed. Instead of collecting and merging the access rules every time a request arrives, it is only done once at boot time and repeated if something changes. This simplifies ACL verification to a quick look-up in a file (after search paths have been resolved).
ACL rules can contain search paths which need to be resolved before it is known which instances they apply to. A set of permissions could for example be specified for the path Device.WiFi.Radio.[Enable == False].
if a controller is only allowed to read and configure things for disabled radios. The Enable
parameter of each radio could change at any time, which makes it impossible to resolve this search path in advance. It can only be resolved once a request for Device.WiFi.Radio.
arrives.
So the master ACL file for each role can contain search paths that need to be resolved before you can figure out if the requestor has the right permissions. To minimize the overhead introduced by search paths, they will only be resolved for paths starting from a root path. In other words, if a request arrives for Device.WiFi.
or one of its child objects, then search paths will only be resolved if they start with Device.WiFi.
.
Some extra information about the acl-manager
can be found in its README.md file.
libamxa
has been written to make it easy for several border control processes to validate ACLs using the same ACL files and APIs. Verifying the access rights requires several steps. In this section the different steps will be explained and the required APIs that are needed will be discussed.
libamxa
provides a function amxa_get_filters to get a list of objects that need to be filtered from a request or response. It takes a bitmask
as input argument which is different for the available operations. For a get
operation it would be AMXA_PERMIT_GET
. A full list of bitmasks will be provided in a table below.get
operation, you also need to check if you are allowed to use search paths, which can be done with amxa_is_search_path_allowed. For some reason, you don't need to check this for the other operations (refer to TR-181 for more information).get
this can be done with amxa_is_get_allowed.amxb
call, for example is amxb_get
.get
, get_supported
or get_instances
operation, you also need to filter the output, because it is possible that you had access to certain parameters, but not to others. The ones you don't have access to need to be filtered out with amxa_filter_get_resp. This is the last step of the ACL verification process, so the remaining output (or error) can be forwarded to the requestor.Note that we are working on streamlining this process. For a get
, set
and get_instances
operation, there already exist API functions to do all of the above steps for you.
The other operators will hopefully have similar functions in the near future.
The use of the aforementioned bitmask is inspired by the code in obuspa. The following bitmasks are defined.
The following table shows which bits are enabled by the Param
, Obj
, InstantiatedObj
and CommandEvent
entries in the Permission.{i}.
data model:
Data model param | rwxn | Bit |
---|---|---|
Param | r | AMXA_PERMIT_GET |
w | AMXA_PERMIT_SET | |
x | ||
w | AMXA_PERMIT_SUBS_VAL_CHANGE | |
Obj | r | AMXA_PERMIT_OBJ_INFO |
w | AMXA_PERMIT_ADD | |
x | ||
w | AMXA_PERMIT_SUBS_OBJ_ADD | |
InstantiatedObj | r | AMXA_PERMIT_GET_INST |
w | AMXA_PERMIT_DEL | |
x | ||
w | AMXA_PERMIT_SUBS_OBJ_DEL | |
CommandEvent | r | AMXA_PERMIT_CMD_INFO |
w | ||
x | AMXA_PERMIT_OPER | |
w | AMXA_PERMIT_SUBS_EVT_OPER_COMP |
Note that some characters in the rwxn
string don't have any use. This is because it doesn't make sense to execute a parameter for example.
TODO: Update GSDM validation now that it is possible to invoke a GSDM request on an instance path. Before anything can be updated, BBF first needs to decide how this should work. The discussion can be followed in USP-778.
The r
flag used in Param
, Obj
and CommandEvent
permissions indicates whether meta-data can be read from parameters, objects, commands and events using GSDM messages. Note that the target paths for these rules work a bit different than for the other operations. It does not make sense to restrict GSDM access when the target path is an instance or wildcard, because it is not possible to execute a GSDM operation on these types of paths (in version 1.1 of the USP specification).
Consider the following example:
! WARNING ! Some people within BBF believe that wildcarded paths do make sense for supported paths. It is possible that paths containing an asterisk should be replaced by supported paths with {i} before evaluating the ACLs. This is currently undocumented anywhere in TR-369 and TR-181, so it is left up to the implementation.
The first rule makes sense for Get messages to prevent a controller from reading parameter values, but it does not make sense for GSDM messages, because it is not possible to invoke a GSDM operation using DHCPv4.Client.1.
as an input path.
! WARNING ! In USP version 1.2 it will be allowed to execute a get supported dm operation on an instance path. This is useful when different instances have diverging paths (e.g. different parameters). Perhaps it will then make sense to take search paths, wildcards and instance numbers into account. See USP-542 for details.
If there is a need to restrict access to meta-data for Client objects, an additional rule must be added with a target path of DHCPv4.Client.
and with an order that is lower than the first rule. If the order for the rule with DHCPv4.Client.
is higher than the order for DHCPv4.Client.1.
, then only the first rule will be used, because it applies recursively to all sub-objects and it has precedence due to its higher order.
Both the second and third rule don't make any sense. They only restrict access to meta-data for objects, commands or events using a GSDM message, but it is not possible to use wildcards or search paths in GSDM messages. Consequently, neither of these rules will do anything and there is also no need to resolve search paths or wildcards present in the ACL rules before fitering GSDM responses. If access to meta-information must be restricted for the Pool
or Forwarding
object, the rules should be applied to the parent path path i.e. DHCPv4.Server.Pool.
or DHCPv4.Relay.Forwarding.
.
Interesting note from USP-542:
If the Agent encounters a diverging Supported Data Model, e.g. due to the use of different Mounted Objects underneath a Mountpoint, the Agent will skip the traversal of the children Objects without adding any information to the Response and continue processing with the next unambiguous Object. The Supported Data Model of such divergent Objects can only be obtained by specifically using Instantiated Object Paths in the
obj_paths
field.
It is possible to add ACL files in the component repository. This gives the implementor of the component the ability to define which roles are allowed to access its data model. During installation, they can then be installed in a designated directory which should be /etc/acl
by default. The permissions of this directory should be limited at runtime. Only the acl-manager
is supposed to have read access to this directory such that is can copy the files to /cfg/etc/acl
which can be updated at runtime. This directory should also have restricted access rights.
It is also possible to define all or a subset of ACL files at config level. It does not matter how many files there are as long as they are written in the correct format.
At run time it is also possible to override or extend ACL rules by using the LocalAgent.ControllerTrust.
data model directly. Permissions that are added to this data model will result in extra ACL files in /cfg/etc/acl/<role>
, which will be picked up by the acl-manager
.
Some parts of the data model will be provided by USP Services in the cloud or in a container. These USP Services need to be able to publish their ACLs to restrict access rights to the data models they provide. This could be accomplished in either of two ways:
Device.LocalAgent.ControllerTrust.Role.{i}.Permission.{i}.
data model with permissions for the USP Service's data model.