FROST-Server Documentation

Live documentation for the development version.

Projects Data Model Plugin

A fine-grained security definition for FROST-Server, based on Projects.

Users, Projects, Roles, UserProjectRoles

Users are actors that can log in. Users are stored in the USERS table. Test users are:

The Users entity type is visible to all users, but normal users can only see their own User entry. Only global-admin users and project-admin users can see all users. Password are not visible to anyone, not even to admin users.

Users can change their own password.

Roles embody sets of permissions that a user can have. Roles are stored in the ROLES table. The default roles are:

The Roles entity type is only visible to admin users.

Users can have global Roles. The global roles are stored in the USER_ROLES table that directly links Users to Roles.

Projects are administrative entities grouping data (through Things). Projects are stored in the PROJECTS table. Projects can be public or private. Public projects, and their associated Things, Datastreams, etc., can be read by everyone. Private projects, and their associated Things, Datastreams, etc., can only be read by users associated to the project.

Users can have project-roles. Users are linked to a Project with a certain Role through the USER_PROJECT_ROLE table.

UserProjectRoles Link a User with a specific Role to a Project. A User can have multiple Roles in the same Project.

The UserProjectRoles entity type is only visible to admin users.

Users without a global “read” role, but with a project-related role can only read entities associated with a project they are related to, or entities that are related to a project that is public. This means they can not read entities that are not related to any projects.

Linking entities to Projects

Things, Locations, Sensors and FeaturesOfInterest link directly to one or more Projects. Datastreams link to Projects through their Thing. Observations link to Projects through their Datastream. When using the default access rules, users can only see entities that are linked to a Project that is ‘public’, or to a Project that they themselves are linked to. If an entity is linked to multiple Projects, only one of those Projects needs to be ‘public’ for the entity to be visible to non-project users. Entities that are not linked any projects are not visible to users that do not have global read rights.

Things, Locations, Datastreams and FeaturesOfInterest can be restricted. This means that even if they are associated with a public project, they can still only be read by users associated to that project. When not explicitly specified, these Entities will not be restircted by default.

Locations and FeaturesOfInterest have their normally hidden link exposed, that indicates that a FeatureOfInterest is autogenerated for a specific Location. This means that, when creating a Location, the FeatureOfInterest that will be used for Obserations that do not specify one, can directly be created as well. Automatically generated FeaturesOfInterest inherit their restricted setting and Project links from the Location the Feature is generated from, at the time of generation.

Auth Providers

Users, Roles and the links between those and Projects need to come from somewhere, and a client making a request needs to be able to authenticate as one of those users. These two processes are flexible and depend on the deployment. Creating users and linking users to Roles and Projects can be done from fully manual to fully automatic.

Logging in users is handled by an Auth Provider. FROST-Server comes with following two out of the box: Basic Auth and KeyCloak Auth.

Basic Auth

When using Basic Authentication the user/password table and the role mapping of users to roles are maintained in the SensorThings database. The Users and Roles tables are exposed through the API, and users can change their password using the API. Global admins can create users, links users to roles and to projects. Project admins can link users to projects.

KeyCloak Auth

When using KeyCloak Authentication the contents of the user and roles tables are automatically filled from the data supplied by KeyCloak.

The links between Projects and Users/Roles can also be decoded from the KeyCloak data, by using a userRoleDecoder. The ProjectRoleDecoder takes the list of roles (strings) that KeyCloak provides, uses a regular expression to extract a project name and a role name from each string, and creates a UserProjectRole for the user for each of these.

MQTT

Using MQTT a client can subscribe to almost any URL in the SensorThings API, and received notifications when something changes for that URL. Access rights in the MQTT protocol are checked when a user makes a subscription to a topic, and not when a message arrives on a topic. This means that, when combining MQTT with fine-grained authorisation, a user must only be allowed to make subscriptions on topics for which this user is allowed to see all messages.

A subscription on the topic v1.1/Observations must thus not be allowed, since that would allow the user to receive all Observations that are added to the server, even those in Datastreams he is not allowed to see.

In most cases, it is enough to restrict all upper-level topics, and only allow subscriptions to relative topics such as v1.1/Datastreams(5)/Observations. These restrictions can be made using the option auth.mqtt.topicAllowList. The suggested value for this option is: ^/[a-zA-Z0-9_-]+\((('[^']+')|([0-9]+))\)/[a-zA-Z0-9_-]+$.

Data Model

The image below shows the core STA data model in blue, with the security extension in yellow.

Data Model

Example Data

An example JSON-Batch document is available. When posting this Batch to v1.1/$batch it will create several Projects, User, Roles and STA entities linked to the Projects.

Project

A new project can be created by posting to v1.1/Projects:

{
    "name": "Project 1",
    "description": "The first, public, test project",
    "public": true
}

Location

A new location can be created by posting to v1.1/Locations, or any other path that represents a list of Locations. For users that do not have global create rights, the new Location must be linked to a Project that the user has create rights on. The location can be linked to multiple projects, but the user creating the Location must have create rights on all these projects.

{
    "name": "Location Station 1",
    "restricted": false,
    "description": "The location of the first station",
    "encodingType": "application/geo+json",
    "location": {"type": "Point", "coordinates": [ 8, 49 ]},
    "Projects": [{"@iot.id": 42}]
}

To make linking to the correct Project easier, the Location can also be created by posting to v1.1/Projects(42)/Locations. This will automatically link the new Location to the Project referenced in the URL.

Thing, Sensor

Like Locations, users that do not have global ceate rights must directly link created Things or Sensors to a Project they have create rights on.

{
    "name": "Station 1",
    "description": "The first station",
    "Locations": [{"@iot.id": 1}],
    "Projects": [{"@iot.id": 42}]
}

FeatureOfInterest

When features of interest are created manually, they too must be linked to a project the user has create rights on, if the user does not have global create rights.

When features are created automatically, they inherit the Projects and restricted setting from the Location the Feature is created from. When the Projects of the Location, or the restricted setting of the Location, is changed, the FeatureOfInterest is currently not updated.

ObservedProperties

Since ObservedProperties are inherently shared entities, they are not linked to Projects. Only users with global create rights and administrators can create or edit ObservedProperties.

Datastreams

Access rights on Datastreams are controlled through the Thing the Datastream is associated with. Users that want to create a Datastream must have create rights on a Project of the Thing the Datastream is associated with. At the same time, when creating a Datastream, it must be linked to a Sensor. To be able to create this link, the user creating the Datastream must have create rights on (a Project linked to) the Sensor.

Observations

Access rights on Observations are conntrolled through the Datastream the Observation is associated with, and thus through the Thing of the Datastream.

There are two user rights that give a user the right to create Observations: create and obscreate. Users with the right obscreate can only create observations, not other entities. Users can only create Observations in Datastreams in Things in Projects that they have one of these rights on.

Conformance Class

The conformance class this extension registers in the SensorThings (v1.1 and up) index document is:

https://fraunhoferiosb.github.io/FROST-Server/extensions/DataModel-Projects.html