Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

SensiNact/Gateway Security

The concepts behind the security

A first level of security is reached by the way of some of available security "tools" in the OSGi environment: ServicePermission and ConditionalPermissionAdmin. The ServicePermission is a module's authority to register or use a service:

  • The register action allows a module to register a service on the specified names.
  • The get action allows a module to detect a service and use it.

Permission to use a service is required in order to detect events regarding the service. Untrusted modules should not be able to detect the presence of certain services unless they have the appropriate ServicePermission to use the specific one. The ConditionalPermissionAdmin is framework service to administer conditional permissions that can be added to, retrieved from, and removed from the framework.

The sensiNact gateway defines service permissions in such a way that access to the ones it provides is forbidden excepted if a specific condition is met (a sensiNact specific conditional permission). This condition being that the client is the sensiNact SecuredAccess service. sensiNact services also have to use the SecuredAccess to be able to “talk” to each other’s; Modalities of such exchanges depend on the UserProfile of the user of these services (the user can be the system itself). A UserProfile can be defined at each level of the hierarchical sensiNact resource model: ServiceProvider, Service, and Resource. Five UserProfiles exist for which predefined access rights are defined:

  • Owner,
  • Administrator,
  • Authenticated,
  • Anonymous,
  • Unauthorized.

When asking for a data structure of the sensiNact resource model, the access rights of the user are retrieved; the set of this user's accessible AccessMethods for the specific data structure is built and returned as part of the description object. Each future potential interaction of the user on the data structure will be made by the way of this description object. For a remote access a security token is also generated and transmitted to the user, to avoid repeating the security policy processing. A token is defined for a user and a data structure (and so it previously created description object).

The Security & Dependability functional block is used for authentication and to retrieve identity material from which it will be possible to associate a user and a sensiNact resource model data structure to a UserProfile.

In addition to the database managed by the Security & Dependability functional block, used to authenticate a user and to retrieve its identity in the system, the sensiNact platform manages an internal database allowing to link this identity to a UserProfile for a specific data structure. For all data structures for which the user has not been registered the Anonymous user profile is used by default (except if the owner of a resource has defined this default profile to another one). The internal database also gathers information relative to the minimum required UserProfile to access to data structures. This definition can be made at each level of the resource model, knowing that if no UserProfile is defined for a data structure, the one specified for its parent is used.

For example, according to the figure below, a user trying to access to the ServiceProviderX for which its UserProfile is Anonymous will receive a description object in which only one Service will be referenced (ServiceX1), containing a single Resource (ResourceX1S2) providing two AccessMethods: GET and SUBSCRIBE.

sensiNact security

The security database

The default database available in sensiNact is a SQLite database. To interact with the database, you can use the command line tool SQLite3. The database is named sensinact.sqlite, in the datastore folder of your distribution (the current distribution may not include this file because the security is not enabled by default for development purpose).

The database is composed of 11 tables:

  • AGENT: this table is used to declare a trusted agent;
  • APPLICATION: this table is used to declare the applications allowed to run on the AppManager;
  • AUTHENTICATED: this table links the users from the SNAUSER table to the objects from the OBJECT table. It allows to fine tune the access right of the users on the sensiNact data model;
  • BUNDLE: this table is used to declare the trusted bundle allowed to register providers in sensiNact;
  • METHOD: this table describes the available methods in sensiNact. This table shouldn't be changed;
  • OBJECT: this table is used to declare the objects, i.e., providers, services and resources, and the bundle were they belong;
  • OBJECT_ACCESS: this table defines the groups of objects. This table shouldn't be changed;
  • OBJECT_PROFILE: this table describes level of access that can be associated to an object in the table OBJECT. This table shouldn't be changed;
  • OBJECT_PROFILE_ACCESS: this table defines relation between the table OBJECT_ACCESS and OBJECT_PROFILE. This table shouldn't be changed;
  • SNAUSER: this table is used to declare the users of the sensiNact gateway;
  • USER_ACCESS: this table defines the group of users. This table shouldn't be changed.

Among those 11 tables, only 4 are useful for a common usage of sensiNact: AUTHENTICATED, BUNDLE, OBJECT and SNAUSER. In the followings section, we present those 4 tables and provide examples of usage.

Add your bundle to sensiNact

(This section need to be consolidated)

sensiNact allows only the certified bundles to be able to provide data to the user. The bundles have to be signed using a certificate and the generated SHA has to be added into the database in order for sensiNact to validate a bundle at start. If the bundle is not valid, it will run but it will not have enough rights to access to the core of sensiNact.

To generate a new certificate, i.e., a file keystore.jks, you can use the following command (more information at the following address [1]):

keytool -keystore keystore.jks -genKey -alias <alias>

In the file sensinact.sqlite, in the datastore folder of your distribution, locates the BUNDLE table. In this table, create a new entry with the following values:

  • BID: a unique identifier (usually the higher number in the column increased by 1). This value is set automatically by the database when it creates the entry;
  • SAUTH: this field defines is the user has to been authenticated to see the object. This field is either 0 (does not require the authentication of the user) or 1 (requires the authentication of the user);
  • OPID: this field defines the minimal access level that the object will provide (cf. table OBJECT_PROFILE);
  • BNAME: the name of the bundle as it appears in the Manifest;
  • BSHA: the value of the SHA-256 as it appears in the SELFSIGN.SF file under the key SHA-256-Digest-Manifest.

In the following example, we add the simulated-slider bundle to the list of the trusted bundles. Its SHA is 3FOfRxBltGeCkq28Z097PQp0ETo4KKJipQi+AaJtj58=. We also want its objects to be accessed using an anonymous account, meaning that OPID is equal to 4. Finally, we do not need any authentication to access to the object.

INSERT INTO SNAUSER(SAUTH, OPID, BNAME, BSHA) VALUES ('0', '4', 'simulated-slider', '3FOfRxBltGeCkq28Z097PQp0ETo4KKJipQi+AaJtj58=');

Add an user

The addition of an user is done in the SNAUSER table. This table contains the following fields:

  • SUID: a unique identifier (usually the higher number in the column increased by 1). This value is set automatically by the database when it creates the entry;
  • SULOGIN: the username of the user;
  • SUPASSWORD: the MD5 encoded password (sensiNact does not encode the password);
  • SUMAIL: the e-mail of the user;
  • SUPUBLIC_KEY: the unique public key of the user. sensiNact does not generate this key. This key is meant to be shared with the owner of the providers in order for them to grant or deny access to an object to this user.

To add an user to the database, here is an example of the SQL command. We assume that the username is "alice" that has a mail account at eclipse.org. Her password is '123456' (that is a very common and secure password, isn't it). The MD password is then e10adc3949ba59abbe56e057f20f883e. The public key can be generated by various methods and its length does not matter. In this case, the public key is not associated to a private key but acts as a unique identifier in the sensiNact database to identify a user. In this example, we just hashed the text "let's create a public key" using the SHA-1 algorithm. The result is d96380bd6b924943dd954573e3edf13f7aa10f12.

INSERT INTO SNAUSER(SULOGIN, SUPASSWORD, SUMAIL, SUPUBLIC_KEY) VALUES ('alice', 'e10adc3949ba59abbe56e057f20f883e', 'alice@eclipse.org', 'd96380bd6b924943dd954573e3edf13f7aa10f12');

Add an object

The addition of an object, i.e., provider, service, resource, is done in the OBJECT table. This table contains the following fields:

  • OID: a unique identifier (usually the higher number in the column increased by 1). This value is set automatically by the database when it creates the entry;
  • BID: the bundle id (as defined in the BUNDLE table) to which the object belong;
  • SAUTH: this field defines is the user has to been authenticated to see the object. This field is either 0 (does not require the authentication of the user) or 1 (requires the authentication of the user);
  • OPID: this field defines the minimal access level that the object will provide (cf. table OBJECT_PROFILE);
  • NAME: this field defines the name of the object to consider or a regular expression to consider, e.g., [^/]+. This field does not need to be unique;
  • PATTERN: this field defines if the field NAME is a pattern. This field is either 0 (is not a pattern) or 1 (is a pattern);
  • PATH: the sensiNact URI of the object, e.g., /slider, /slider/cursor, /slider/[^/]+. This field is generated automatically based on the fields NAME and PARENT;
  • PARENT: the OID of the parent node.

By default, this table contains the root entry (OID = 0). This entry must not be deleted in any ways because all the object will be at least depending on this entry (in the PARENT field). As explained in the first section of this page, the objects inherit there rights from the parent node. Thus a resource inherits its rights from its parent service, and a service from its parent provider. The provider inherits its rights from the root.

Example 1: the object belongs to the simulated-slider bundle whose BID in the BUNDLE table is 5. We want this object to be visible even to not authenticated users, meaning SAUTH being set to 0. The OPID is set to DEFAULT (equals to 1). The NAME of the provider is "slider". Finally, the object we want to add is a direct child of the root, thus the PARENT is 0.

INSERT INTO OBJECT(BID, SAUTH, OPID, NAME, PATTERN, PARENT) VALUES ('5', '0', '1', 'slider', '0', '0');

The resulting rows will look like that:

OID BID SAUTH OPID NAME PATTERN PATH PARENT
0 0 1 / 0
1 5 0 1 slider 0 /slider 0

Example 2: in this example, we want to add a specific entry related to the services of the "slider" provider defined in the example 1. Most of the fields are similar to the example 1 (i.e., BID, SAUTH, OPID). The difference lies in the fields NAME, PATTERN and PARENT. Because, this entry targets the "slider, thus PARENT is set to 1 (we refer to the OID of the slider entry). And we also want to consider all the services of the slider: we can use a regular expression such as "[^/]+" in the NAME field, meaning that PATTERN must also be set to 1.

INSERT INTO OBJECT(BID, SAUTH, OPID, NAME, PATTERN, PARENT) VALUES ('5', '0', '1', '[^/]+', '1', '1');

OID BID SAUTH OPID NAME PATTERN PATH PARENT
0 0 1 / 0
1 5 0 1 slider 0 /slider 0
2 5 0 1 [^/]+ 1 /slider/[^/]+ 1

Provide access to an object for an user

To grant or deny access to an object for an user, we use the AUTHENTICATED table. This table contains the following fields:

  • PUBLIC_KEY: the public key of the user (cf. table SNAUSER);
  • OID: the object id (cf. table OBJECT);
  • UAID: this field defines the level required to access to the object (cf. USER_ACCESS table).

In the following example, we want to grant the user alice (defined in the table SNAUSER) the right to access to the slider (defined in the table OBJECT). To identify Alice, we use its public key: d96380bd6b924943dd954573e3edf13f7aa10f12. The slider has been added with the OID 1 (the attribution of the OID is done by the database). Finally, we want to allow Alice to have the "Authenticated" rights on this object, meaning that UAID is equal to 3.

INSERT INTO AUTHENTICATED(PUBLIC_KEY, OID, UAID) VALUES ('d96380bd6b924943dd954573e3edf13f7aa10f12', '1', '3');

Back to the top