11. Access Control¶
This section introduces the RDFox access control model, beginning with an explanation of key concepts and progressing to practical aspects of securing an RDFox server.
In RDFox we can define groups of users and assign access privileges to each group over the different information resources described in Section 4 (e.g., data stores, tuple tables, and so on). This section provides a detailed overview of the types of access privileges that can be assigned to resources and how these are managed.
11.1. Key Concepts¶
To work with RDFox access control it is essential to understand the key concepts role, resource and access type and some other general principles of the system described in this section.
11.1.1. Roles¶
Roles represent users or groups of users. To interact with an RDFox server (see RDFox Concepts), a user must obtain a connection to it by authenticating as one of the roles in the server’s role database. When an operation is requested via a given connection, RDFox checks whether the role authenticated on that connection has sufficient privileges to perform the operation and stops immediately if not.
Roles receive privileges by having them directly assigned or by inheriting them
from other roles of which they are a member. Role membership is a transitive
relationship so that if role C
is a member of role B
and B
is a
member of of role A
then role C
is also a member of role A
.
11.1.2. Resources¶
Resources, in the context of access control, are the individual parts of an RDFox server to which access can be controlled. Every resource has a unique name and to make it clear which resources are contained within other resources, the names of contained resources begin with the name of the resource that contains them. Combined with the recursivity specifier (see Resource Specifiers), this also makes it easy to specify simple policies succinctly.
The following table shows the different types of resource within an RDFox server with the corresponding resource name format. Braces ({}) indicate list-element segments.
Description |
Resource name format |
---|---|
The server itself. |
|
The list of data stores within a server. |
|
A specific data store within the server. |
|
The set of axioms loaded inside a data store. |
|
The list of data sources registered with a data store. |
|
A specific data source registered with a data store. |
|
The dictionary of resources loaded inside a data store. |
|
The Datalog program loaded inside a data store. |
|
The list of tuple tables within a data store. |
|
A specific tuple table within a data store. |
|
The list of roles known to the server. |
|
A specific role known to the system. |
|
11.1.2.1. Resource Specifiers¶
Resource specifiers enable administrators to specify sets of resources for the purpose of granting or revoking privileges. All valid resource names may be resource specifiers on their own. Additionally, resource specifiers may have the following elements:
*
, the list element wildcard. This may appear as the final segment of a resource specifier if and only if that segment is a list-element segment, and signifies that a privilege applies to all possible values in that segment as determined at the time authorization is checked. For example, in a server containing rolesa
,b
andc
and no other roles, the resource specifier|roles|*
specifies exactly the resources|roles|a
,|roles|b
and|roles|c
.>
, the recursivity indicator. A specifier beginning with>
instead of the initial|
character specifies the same resources that would be specified by the nonrecursive version plus all of their subordinate resources. For example, in a server with a data store calledds
containing data sourcesone
andtwo
, the resource specifier>datastores|ds|datasources
specifies exactly the resources|datastores|ds|datasources
,|datastores|ds|datasources|one
and|datastores|ds|datasources|two
. It is an error to use the recursivity indicator to begin the name of a resource with no subordinate resources.
The list element wildcard and recursivity indicator may be combined freely
(subject to their individual rules). For example, if we want to grant a
privilege over every part of every data store within a server but not over the
list of data stores itself, we can use the resource specifier
>datastores|*
. To also include the list of data stores, we can use
>datastores
.
Resource specifiers have their own set of escaping rules which ensure that they do not impose any restrictions on list element names. The rules are as follow:
Names beginning with
*
must have the initial*
escaped as**
. For example the correct specifier for a role with name*abc
would be|roles|**abc
. No escaping is required for*
s at any other position within a name.Names containing
|
must have each|
escaped as||
. For example, the correct specifier for a data store with namemy|store
would be|datastores|my||store
.
11.1.2.2. Access Types¶
Access types describe the various different ways the system’s resources may be
accessed. RDFox defines three access types; read
, write
and grant
.
The read
access type covers all retrieval of information from the system.
The write
access type covers addition, mutation and deletion of
information. The grant
access type is used to restrict which roles can
grant and revoke privileges over a resource to or from other roles.
Multiple access types can be specified at once in a comma-separated list, e.g.,
read,write
. To save typing in situations where a role should have full
control of one or more resources, RDFox accepts the access type name full
which allows all of the above access types. Note that the full
privilege
for a resource specifier is stored separately from the read
, write
and
grant
privileges. This means that revoking full
access type must be
done explicitly, i.e. revoking read
access from a role which has full
access has no impact on what the role can actually do.
11.1.2.3. Creation and Deletion¶
Creating new resources (data stores, data sources, tuple tables or roles)
requires write privilege over the containing list resource, e.g., over
/datastores
for creating data stores. Deleting these elements requires
write privilege over both the containing list resource and the element to be
deleted.
Whenever a new resource is created, privileges enabling full control of the resource and any resources it contains are granted to the creating role. When a resource is deleted, privileges specific to the resource are deleted too to help ensure that the system never stores privileges over nonexistent resources.
11.1.2.4. Granting and Revoking Privileges on Resources¶
Granting and revoking privileges requires two privileges: grant
over the
resource to which access is being granted and write
over the role which
will receive or, in the case of revocation, lose the privilege. For example,
granting the power to create data stores to a role named datastore-creators
requires privileges sufficient for the following accesses:
Resource |
Type of access |
---|---|
|datastores |
grant |
|roles|datastore-creators |
write |
Granting and revoking membership of one role to another role works in a similar
way. To grant membership of role group
to role user
, the granting role
must have privileges sufficient to allow these accesses:
Resource |
Type of access |
---|---|
|roles|group |
grant |
|roles|user |
write |
It is important to note that a privilege granted using one resource specifier cannot be revoked with any other resource specifier, regardless of any intersection between the sets of resources specified by the two. Furthermore, granting and revocation operations do not raise errors or warnings when the system is already in the desired state, e.g., revoking a privilege from a role which does not have that privilege. For these reasons, it is essential to compare the role’s privileges before granting or revoking with those after the operation to ensure the desired change is reflected.
11.1.2.5. Built-in Policies¶
In most situations, access to a resource is determined solely by the policies set by the user of the system, however there are two built-in policies controlling a role’s access to itself which override the user’s policies. The first of these ensures that every role can read its own privileges and memberships and the second policy prevents any role from writing its own privileges and memberships.
11.2. Securing an RDFox Server¶
This section gives practical information on how to set up a secure RDFox server using examples entered into the RDFox shell. The shell snippets throughout this section form a running example of the procedure.
11.2.1. Initialization¶
At least one role must exist before an RDFox server can be started. When no
roles can be loaded from the configured server directory (see
Persistence), RDFox will check the process’s command line arguments and
environment variables for the name and password to use for the first role. If
either value is missing after that process, the behavior then depends on which
mode RDFox has been started. In shell
mode, the user is prompted to provide
the missing values as follows:
Enter the name of the first role: admin
Enter the first role password:
Confirm the password:
See Section 16.1 for more details on how to start RDFox.
When using file-based role persistence, RDFox will next determine the parameters for hashing passwords on the local hardware. This may take a minute or more but will only happen the first time file-based persistence is used with a given server directory. A successful initialization will continue as follows:
Initializing access control (may take a minute or more)...
Access control has been initialized by creating the first role with name "admin".
At this point, the first role holds the privilege full >
, giving it full
control over the server and all its resources, including the power to configure
access control. If RDFox was started in an interactive mode (shell
or
sandbox
), the credentials used to create the first role will then be used
to log in to the shell:
You are logged into the shell as "admin".
>
Note RDFox uses argon2i to compute hashes for storage when file-backed role persistence is enabled.
11.2.2. Managing Roles¶
In the shell, the role command provides several subcommands for
managing the roles in the system. The create
subcommand creates a new role
once the role’s password has been provided interactively. For example:
> role create user1
Enter the password for the new role:
Confirm the password:
A new role was created with name "user1".
> role create group
Enter the password for the new role:
Confirm the password:
A new role was created with name "group".
To see the currently active role, issue role
with no subcommand. To list
the server’s roles, use role list
and to switch to another role, use role
switch <role-name>
(you will be prompted to enter the role’s password).
role delete <role-name>
can be used to delete a role which is no longer
needed. Note that RDFox will not allow a role which has an active connection to
the server to be deleted.
To change a role’s password, log into the shell as that role and issue the password command.
11.2.3. Assigning Privileges Directly¶
In the shell, privileges are granted or revoked with the privileges
subcommand of the grant or revoke commands.
Privileges are formed from a list of access types followed by a resource
specifier. For example the following script grants read
, write
and
grant
privileges over all data stores to user1
and then revokes the
write
and grant
privileges:
> grant privileges read,write,grant >datastores|* to user1
The privileges 'read,write,grant' over resource specifier ">datastores|*" were granted to the role "user1" (if not already present).
> revoke privileges write,grant >datastores|* from user1
The privileges 'write,grant' over resource specifier ">datastores|*" were revoked from the role "user1" (if they were present).
As mentioned in the section Granting and Revoking Privileges on Resources, RDFox does not raise
an error if the role losing privileges does not have them to begin with so we
must inspect the role’s privileges after revocation. For this purpose, as well
as for inspecting a role’s direct members and memberships, the
role command provides the show
subcommand:
> role show user1
'user1' has the following directly assigned privileges:
==============================================
Resource specifier Allowed access types
----------------------------------------------
>datastores|* read
==============================================
'user1' is a direct member of the following roles:
================
Memberships
----------------
================
The following roles are direct members of 'user1':
============
Members
------------
============
11.2.4. Discovering Privilege Requirements¶
In order to determine which privileges are needed for a particular operation, attempt the operation as an completely unprivileged role and examine any resulting error message to identify which privilege was required but missing, if any. For example:
> role switch user1
Password:
Switched to role "user1".
> role list
An error occurred while executing the command:
The role 'user1' is not authorized to read the resource '|roles'.
The above process should be repeated until the operation is completely successful as, although some operations access several different resources, the failure message will only ever reveal one missing privilege.
11.2.5. Assigning Privileges via Membership¶
Roles can be arranged into hierarchies using the role
subcommand of the
grant command:
> role switch admin
Password:
Switched to role "admin".
> grant role group to user1
Membership of the role "group" was granted to the role "user1" (if not already present).
and remove from them using the role
subcommand of the revoke
command:
> revoke role group from user1
Membership of the role "group" was revoked from the role "user1" (if it was present).
A role may be a member of as many others roles as is necessary however RDFox will prevent cycles: a role cannot be a member of a role which is a member of it. RDFox will also not allow roles with more than zero members to be deleted.
11.2.6. Securing the REST Endpoint¶
On receipt of an anonymous REST request (one with no Authorization
header),
RDFox will attempt to create a new connection for the request by authenticating
with role name guest
and password guest
. To enable anonymous REST
access, administrators should therefore create the guest
role and grant it
the privileges to perform any operation which should be available to any
client which can reach the REST endpoint. As a corollary, anonymous REST access
can be completely disabled by ensuring the absence of a role named guest
from the server’s role list. Note that RDFox will not allow the guest
role
to be created with any password other than guest
, nor will it allow this
role’s password to be changed.
Warning
Since RDFox’s REST endpoint supports only the Basic
authentication
scheme, which requires transmission of plaintext passwords, it is essential
to use one of the secure communication types (HTTPS) if authenticated usage
of the REST endpoint is intended. See the endpoint.channel
variable and
related variables in Section 13.2 for details of how to set
up HTTPS.
11.2.7. Controlling Access to Named Graphs¶
RDFox stores all the triples for a given named graph in a tuple table with the
same name. Given a named graph with IRI http://example.com/graph
within a
data store called myDataStore
, privileges controlling access to the named
graph would use the resource specifier:
|datastores|myDataStore|tupletables|http://example.com/graph
RDF technologies supporting the concept of named graphs, such as TriG and
SPARQL, also support import or querying outside the context of a named graph.
In these cases, the target of the import or query is the“default” graph. RDFox
reserves the tuple table name internal:triple
within each data store to act
as that data store’s default graph. For the same data store as above, access to
the default graph would be granted using the resource specifier:
|datastores|myDataStore|tupletables|internal:triple
11.2.8. Testing the Setup¶
Verifying that your access control policy is correct is an essential step in establishing a secure RDFox server. Oxford Semantic Technologies recommends comprehensive tests including both positive (checking that a given role can perform the operations it should be authorized to perform) and negative (check that a given role cannot perform the operations it should not be authorized to perform) tests.
11.2.9. Persistence¶
RDFox allows users to specify, via the -persist-roles
server parameter (see
Section 16.2.2), whether a server’s access control configuration is
loaded and saved from and to the server directory. When -persist-roles
is
set to off
, credentials for the first role must always be supplied on
startup and all roles created within the server cease to exist when the server
is deleted (usually when the containing process terminates). When
-persist-roles
is set to file
, RDFox will attempt to load existing
roles from the server directory on startup, initializing access control if none
are found, and will thereafter persist all changes to the server directory.
11.3. Examples¶
This section contains several additional examples of access control policies.
The scripts in this section are written assuming they are being run by a role
with the all-powerful full >
privilege as assigned to the first role when a
server is initialized.
11.3.1. Anonymous, Read-only REST Access¶
The following shell example shows how to enable anonymous (unauthenticated) access to the parts of the RDFox REST API which involve only read access:
> role create guest
A new role was created with name "guest".
> grant privileges read > to guest
The privilege 'read' over resource specifier ">" was granted to the role "guest" (if not already present).
> endpoint start
The REST endpoint was successfully started at port number/service name 12110 with 11 threads.
See Securing the REST Endpoint for more details.
11.3.2. Self-service Creation of Private Data Stores¶
The following examples shows how to allow a group of users to create private data stores in a shared server instance:
> role create datastore-creators
...
A new role was created with name "datastore-creators".
> grant privileges read,write |datastores to datastore-creators
The privileges 'read,write' over resource specifier "|datastores" were granted to the role "datastore-creators" (if not already present).
Additional commands would be needed to create a role for each user and add them
to the datastore-creators
role.
Note that the resource specifier used above to grant read,write
access over
the data store list does not specify recursivity so the privilege does not
grant any powers over any specific data store - only the list of data stores.
When a member of the datastore-creators
role uses their write privilege by
creating a data store though, they, as the creator of the new store, are
automatically granted full control over it. This ensures that they can also
delete their own stores but not those created by others (unless they are
granted additional privileges by the admin).
11.3.3. Delegating Administration of a Data Store¶
To minimize the work that must be done as the most powerful role, it may be desirable to create separate roles to administrate each data store. To do this, first create the data store and its administrator role and ensure that the role has full control over the data store as follows:
> dstore create ds par-complex-nn
A new data store, 'ds', of type "par-complex-nn" was created and initialized.
> active ds
Data store 'ds' is active.
> role create ds-admin
...
A new role was created with name "ds-admin".
> grant privileges full >datastores|ds to ds-admin
The privilege 'full' over resource specifier ">datastores|ds" was granted to the role "ds-admin" (if not already present).
Finally, to ensure that ds-admin
is able to grant and revoke privileges
over parts of the data store to other roles we simply grant it write access
over all roles as follows:
> grant privileges read |roles to ds-admin
The privilege 'read' over resource specifier "|roles" was granted to the role "ds-admin" (if not already present).
> grant privileges read,write |roles|* to ds-admin
The privileges 'read,write' over resource specifier "|roles|*" were granted to the role "ds-admin" (if not already present).