Warning: This document is for an old version of RDFox. The latest version is 7.1.

12. Access Control

This section introduces RDFox’s access control system. The key concepts and general principles of the system are explained first followed by a practical guide on how to secure an RDFox server and, finally, some examples of access control policies.

Access control settings may be persisted between sessions or for replication purposes. See Section 13 for more information.

12.1. Key Concepts

To work with RDFox access control it is essential to understand the key concepts role, resource and access type which are described in this section.

12.1.1. Roles

A role represents a user, or group of users, of an RDFox server.

Roles hold privileges that determine which resources (see Section 12.1.2) within the server they can access and how (see Section 12.1.3). Privileges may be held as a result of direct assignment to the role or by inheritance from another role of which the role is a member. The effective privileges available to a role are the union of those directly assigned to it with those directly assigned to all roles of which it is a member. Note that 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.

To begin interacting with an RDFox server or data store, a user must obtain a connection to it by authenticating as one of the roles in the server’s role database. If authentication is successful, RDFox compiles a snapshot of the role’s effective privileges and permanently associates this with the new connection. This determines which operations the connection will be authorized to perform during its lifetime.

Warning

Changes to a role’s privileges do not affect the privileges associated with any existing connections belonging to the role, only to new connections created after that point.

12.1.2. Resources

A resource represents a component of an RDFox server to which access can be controlled. As described in Section 4, the set of resources within each server form a containment hierarchy with the server itself at the root.

Every resource has a unique name relative to the server. 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.

|datastores

A specific data store within the server.

|datastores|{data-store-name}

The list of data sources registered with a data store.

|datastores|{data-store-name}|datasources

A specific data source registered with a data store.

|datastores|{data-store-name}|datasources|{data-source-name}

The Datalog program loaded inside a data store.

|datastores|{data-store-name}|rules

The OWL axioms loaded inside a data store.

|datastores|{data-store-name}|axioms

The list of tuple tables within a data store.

|datastores|{data-store-name}|tupletables

A specific tuple table within a data store.

|datastores|{data-store-name}|tupletables|{tuple-table-name}

A specific named graph within a data store.

|datastores|{data-store-name}|namedgraphs|{graph-name}

The list of roles in the server’s role database.

|roles

A specific role in the server’s role database.

|roles|{role-name}

Note

Graph names appearing in access control resource names must be valid Turtle literals. For convenience, IRIs may be specified using prefixes defined within the referenced data store, or as relative IRIs against the data store’s base IRI. Named graph resource names will usually be output using fully-expanded IRIs in the graph name segment, regardless of how they were input.

12.1.2.1. Resource Specifiers

Resource specifiers enable administrators to specify sets of resources for the purpose of granting or revoking privileges over them. All valid resource names are also valid resource specifiers. 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 roles a, b and c and no other roles, the resource specifier |roles|* specifies exactly the resources |roles|a, |roles|b and |roles|c. If role d is added, it too will be included in the set specified by |roles|*.

  • >, the recursivity indicator. A specifier beginning with > instead of the initial | character specifies the same resources that would be specified by the non-recursive version plus all of their subordinate resources. For example, in a server with a data store called ds containing data sources one and two, 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 name my|store would be |datastores|my||store.

12.1.3. Access Types

An access type represents a general type of access to a server’s resources.

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.

12.2. General Principles

Building on the key concepts, it is also important to understand a few general principles of RDFox’s access control system described in this section.

12.2.1. Creation and Deletion

Creating new resources (data stores, data sources, tuple tables or roles) requires a write privilege over the containing list resource, e.g., over /datastores for creating data stores. Deleting resources requires a write privilege over both the containing list resource and the element to be deleted.

12.2.2. 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 user1, the granting role must have privileges sufficient to allow these accesses:

Resource

Type of access

|roles|group

grant

|roles|user1

write

It is important to note that a privilege granted using one resource specifier can only be revoked with the exact same resource specifier.

12.2.3. 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.

12.2.4. Enforcement of Access Control Policies

In general, if an operation requires access to a resource in a way that is not authorized, the operation is immediately aborted. If, instead, all required accesses are authorized, the operation proceeds and is not otherwise affected by access control. In other words, a role’s level of access to the server, in the majority of cases, determines only whether it can perform an operation and not what the operation does if it is permitted. The exception to this rule is for read accesses to named graphs as described in the next section.

12.2.4.1. Named Graph Access Control

In contrast to the behaviour described above, read accesses to named graphs do not produce errors even when the associated privilege is unavailable. Instead, RDFox enforces the access control policy by behaving as if any named graph or graphs that are not readable do not exist. This has the consequence that different users may receive different answers for the same query depending on which set of named graphs they have privileges to read.

Note that all operations that read named graphs also require read access to the containing data store and its Quads tuple table. If the privileges for these accesses are absent, the operation will be aborted as described above.

Note that SPARQL updates involving DELETE/INSERT WHERE, COPY, ADD, or MOVE statements, are separately sensitive to which graphs are readable and writable by the role as illustrated in the following example.

The following SPARQL update copies all of the triples from graph :G1 to graph :G2. Let’s assume that graph :G1 is not empty and that the prefix : is defined in the data store.

INSERT { GRAPH :G2 { ?S ?P ?O } }
WHERE  { GRAPH :G1 { ?S ?P ?O } }

Imagine we have a role with read and write privileges over the Quads table within the data store but no privileges over any named graphs. When the role invokes the above query, no authorization error is raised even though the INSERT clause specifies an unwritable graph. This is because access control prevented the body of the query (the WHERE clause) from matching the triple in the unreadable graph :G1 so there was no attempt to write a triple into the unwritable graph :G2.

If we grant the role a read privilege over graph :G1 and reevaluate the update (on a fresh connection), an error will be produced. This time, the query body was allowed to match the triple in :G1 and an attempt to write it to :G2 was made. This resulted in the operation being immediately aborted.

Finally, if we grant a write privilege over graph :G2 and reevaluate once more (again, on a fresh connection), no error is produced. If we were to inspect graph :G2 as a role with read permisson over it, we would find the triples from :G1 there.

12.3. Securing an RDFox Server

This section gives practical information on how to set up a secure RDFox server. Examples are given for the RDFox executable and shell but all steps can also be achieved programmatically using the APIs described in Section 16.

12.3.1. Initialization

At least one role must exist within a RDFox server’s role database before that server can be used. When the role database is empty at startup, either because the server directory has not been initialized for role persistence, or because role persistence is disabled, RDFox will check the process’s command line arguments and environment variables for the name and password to use for the first role. After that, if either value is missing after that, the behavior then depends on which mode RDFox has been started in. 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 18 for more details on how to start the RDFox executable.

When using 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 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:

A new server connection was opened as role 'admin' and stored with name 'sc1'.
>

Note

RDFox uses argon2i to compute hashes for storage when role persistence is enabled.

12.3.2. Managing Roles

In the shell, the role command provides several subcommands for managing the roles in the system. It uses the shell’s active server connection to perform operations. To understand how the shell manages server and data store connections, see Section 15.1.

The command role create <role-name> creates a new role, prompting for the role’s password to be provided and confirmed. 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 list the roles in the server’s role database, use role list. To delete a role which is no longer needed, use role delete <role-name>.

To change a role’s password, ensure that the active server connection is authenticated as the role whose password is to be changed and issue the password command.

Note

Commands that require interactive password entry cannot be used in the remote shell.

12.3.3. Assigning Privileges Directly

In the shell, privileges are granted or revoked with the privileges subcommand of the grant or revoke commands. Privileges must be given as 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 the resource specifier ">datastores|*" were granted to the role "user1".
> revoke privileges write,grant >datastores|* from user1
The privileges 'write,grant' over resource specifier ">datastores|*" were revoked from the role "user1".

To check that the role’s privileges are now as we expect, we can use the show subcommand of the role command which prints all of the specified role’s privileges, memberships and members:

> role show user1

Password hash for 'user1' is <password-hash>

'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
------------
============

12.3.4. Discovering Privilege Requirements

Individual operations may require several privileges depending on which resources they access. To determine which privileges are needed for a particular operation, attempt the operation as a completely unprivileged role and examine the resulting error message to identify the first required privilege. For example, the error messages in the following shell session tells us that in order to list the roles, a role must have a read privilege over the |roles resource.

> srvconn open user1-connection as user1
Password for 'user1':
A new server connection was opened and stored with name 'user1-connection'.
> srvconn active user1-connection
Server connection 'user1-connection' is active.
> role list
An error occurred while executing the command:
    The role 'user1' is not authorized to read the resource '|roles'.

Next, grant the missing privilege:

> srvconn active sc1
Server connection 'user1-connection' is active.
> grant privileges read |roles to user1
The privilege 'read' over the resource specifier "|roles" was granted to the role "user1".

Although the privileges were successfully granted to the role, the server connection we opened earlier as user1 will not have been modified. To exercise the new privileges available to user1, we first close the existing server connection and open and activate a new one:

> srvconn close
The active server connection was closed.
> srvconn open user1-connection as user1
Password for 'user1':
A new server connection was opened and stored with name 'user1-connection'.
> srvconn active user1-connection
Server connection 'user1-connection' is active.

Finally, retry the operation:

> role list
=========
Name
---------
admin
group
user1
=========

The command is now successful. For other commands, multiple iterations of the above process may be needed before the command succeeds. For security reasons, RDFox only reveals the missing privileges for one resource at a time.

12.3.5. Assigning Privileges via Membership

Roles can be arranged into hierarchies using the role subcommand of the grant command:

> srvconn active sc1
Server connection 'sc1' is active.
> grant role group to user1
Membership of the role 'group' was granted to the role 'user1'.

and removed 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 other roles as is necessary however RDFox will prevent cycles: a role cannot be a member of itself either directly or indirectly. RDFox will also not allow roles with one or more members to be deleted.

12.3.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 19.2 for details of how to set up HTTPS.

12.3.7. 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.

12.3.8. Persistence

When persistence (see Section 13) is enabled, RDFox saves relevant parts of the server’s content to the server directory. An attacker with access to that directory will be able to tamper with any persisted access control policies. For this reason, it is vital to also tightly control access to the server directory when role persistence is enabled.

12.4. 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 is assigned to the first server role.

12.4.1. Anonymous, Read-only REST Access

The following shell example shows how to enable anonymous (unauthenticated), read-only access to the entire server:

> role create guest
A new role was created with name "guest".
> grant privileges read > to guest
The privilege 'read' over the resource specifier ">" was granted to the role "guest".
> 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.

12.4.2. 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
A new data store 'ds' was created and initialized.
> active ds
Data store connection '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 the resource specifier ">datastores|ds" was granted to the role "ds-admin".

Finally, to ensure that ds-admin is able to grant and revoke privileges over the data store to and from other roles, we grant it write access over all roles as follows:

> grant privileges read |roles to ds-admin
The privilege 'read' over the resource specifier "|roles" was granted to the role "ds-admin".
> grant privileges read,write |roles|* to ds-admin
The privileges 'read,write' over the resource specifier "|roles|*" were granted to the role "ds-admin".