Access control - remiges-tech/crux GitHub Wiki

The authorisation model and access control

Crux is multi-tenant

This means that Crux is designed from Day 1 to run as a shared service and maintain water-tight separation between organisations or user-groups, each of whom will have full access to manage their own Crux data.

Of realms, applications and capabilities

Crux supports the idea of user realms. A user is a member of one and only one realm. In the real world, a realm may map onto an organisation or a user group. If Crux is operated as a SaaS service, a realm may map onto a customer.

Within a realm, an authorised user with sufficient rights can perform all operations which Crux supports. All data, configuration and resources used by Crux are owned by a realm. No user has rights to perform any operation across more than one realm.

No user may define a new realm in Crux. Realms are defined via channels other than the Crux API. (This typically means a command-line program will be run on a server which has direct access to the Crux data store, and will add and remove realms. Therefore, realm management will be done by the same team which installs new versions of Crux software, takes data backups, etc.)

Within a realm, Crux allows the creation of one or more "apps" or applications. Schema and rulesets belong to one or other app within a realm. No schema or rulesets can be defined in Crux unless it is tied to an app.

The right to do something on a Crux system is called a "capability". Crux supports a set of capabilities; each has a name. Some capabilities are realm-wide, others are per-app. If a user is assigned a capability, she can perform the corresponding operations. Querying the BRE or WFE for business rules or stepping through a workflow are app-level capabilities. Managing capabilities of users is a realm-level capability -- a user who has this capability can grant and revoke capabilities for any user in a realm.

How a Crux instance is bootstrapped

At the most fundamental level, Crux is all about operating a business rules engine or workflow engine -- everything else are wrappers. These engines work with rules which the client defines in Crux. All rules belong to one app or other. Users and apps belong to realms -- these are N-to-1 relationships.

Therefore, when the Crux API is first used by a new organisation, this organisation must have a realm already defined, and one user with root privileges belonging to this realm already defined in the identity management system (IMS) which Crux is using. This is the starting point. From this point, this one user can create apps under her realm, and give users access to these apps, and then others can start creating rule schema, then rules, and then start querying the engine.

The list of capabilities

This is the list of capabilities Crux supports:

  • root: Everything which the Crux API allows any user to do will be permitted for a user with this capability. This applies to a realm.
  • config: This allows the user to edit configuration parameters of the Crux instance. This applies at the realm level.
  • auth: allows the user to grant and revoke capabilities for a user. Realm-level capability.
  • report: allows the user to extract information, pull out reports, get lists of records, from the system. Realm-level capability.
  • schema: allows the user to manage the rule schema for a given app. This user will be able to define and edit the schema. This is an app-level capability, i.e. the capability will apply only for one or more apps.
  • rules: allows the user to manage the rulesets for a given app. This user will be able to define and edit rules and rulesets. App-level capability.

There is no capability to allow a user to query the Crux engine. Any business application can query the Crux engine, with the right credentials, but without user-level capabilities.

None of the capabilities imply any other capability, they are all orthogonal to each other. Of course, in reality, any user with the root or auth capability can grant himself or herself any other capability, therefore these two capabilities indirectly imply the potential to own all other capabilities.

There are no capabilities which allow a user to create other user accounts, delete user accounts, etc. This is because user management is not part of the functional scope of Crux. Users will need to be managed in an identity management system and Crux will use its services.

Web service calls and capabilities

Capabilities are the gates which web service calls enforce when a client makes a request to Crux.

Every web service call in Crux is authenticated. This means that the caller must have a record in the IMS integrated with Crux, and must first authenticate herself using that IMS, and get a token which must be passed on to Crux for every call.

WHen Crux receives a request, it checks whether the calling user has the capability to perform the operation requested. Some calls require realm-level capabilities, others require app-level ones. Those WSC which require app-level capabilities will always accept an app as a parameter, and will match the calling user's capabilities against that app.

Identity management

Crux integrates with any identity management system which can offer a set of services which fit into Crux. Crux defines an interface which the identity management system must implement. The IMS must support the idea of mutually exclusive sets of user identities as separate realms. A realm defined in Crux must map onto a realm in the IMS.

The following operations must be supported by the IMS to integrate with Crux:

  • verify an authentication token submitted by a caller to Crux
  • fetch the list of users belonging to a realm
  • verify that a given user belongs to a given realm
  • fetch a user's account details including the realm the user belongs to

The first version of Crux will be released with an integration with IDshield. A future version will offer an optional simple IMS which will be based on a relational database and a set of basic features.

Crux does not create users, delete users, or provide a login screen to allow a user to log in. Crux expects the IMS to provide these functions and handle these operations. If the IMS stores personally identifiable information about users, Crux does not require access to those attributes. The IMS must maintain the mapping of user to realm.

Caching the results of authorization checks

A typical WSC will go through the following checks to decide authorization for a request

  1. Call the IMS, verify that the authentication token is valid, get back from the IMS the user ID and realm.
  2. Use the user ID and realm thus received and check the deactivated table to check whether first, the realm and then, the user has been deactivated.
  3. Then use the user ID and realm, plus the app name passed in the request (if present) to check the capgrant table to see if the calling user has the capability to perform the operation. (This step will be skipped if the call does not require per-user authorization.)

Then get into the actual performance of the operation.

Thus, three lookups are required. One is an inter-service WSC, and the other two are database lookups. Therefore, one or two Go packages must be developed to ferry these lookups through a caching layer. There may be a verifyToken() call to check the token (step 1) followed by a verifyAuthz() call to check the authorization (steps 2 and 3), or there may be a single call to do both. Whatever be the approach, it is a good idea to cache the results of these lookups inside the functions in private in-memory caches, so that lookups may be speeded up. There should also be accompanying cacheCapGrant() and cacheCapRevoke() functions in these packages so that when capGrant() and capRevoke() web service requests are received, these functions can be called to remove cache entries. Similar calls may be needed called cacheUserDeactivate(), cacheUserActivate(), cacheDeactivate() and cacheActivate(), for cache management for other web service calls.

Note that the verifyToken() call is not just an authentication check, it's also an authorization check, because the IMS may have some logic or rules to inform Crux whether the calling user is authorized to access Crux at all. This may be based on service-specific rules in the IMS (Crux is a service). Therefore, even if an outer layer like an API gateway does token validation, a second call fron Crux may be needed.