6.10.94-stable

Permissions

GreyCat relies on a Role Based Access Control (RBAC) to enforce fine-grain security controls.

Permissions are simply rights to read or write within a particular resource.

Permission is then associated with the user through the notion of roles.

Roles are simply collections of permissions associated with various Users.

One user can only be linked to a single Role.

GreyCat standard library already defined a few:

  • public: default, associated with anonymous users.
  • web: access to WebRoot hosted files using HTTP GET request.
  • api: the ability to execute remote procedure call on the GreyCat server (should be used together with abi permission).
  • abi: the ability to use ABI Protocol to query the GreyCat server (if none is selected, JSON is the only RPC option).
  • graph.read: the ability to read the Graph (aka any nodes) using reflection methods such nodeIndex::sample etc…
  • graph.write: the ability to execute a request or task that mutates any nodes of the graph.
  • files.read: enables to fetch files using HTTP GET queries under a path like /files/<user_id>/file_name.txt.
  • files.write: enables to push files using HTTP PUT queries under a path like /files/<user_id>/file_name.txt.
  • files.all.write: enables to push files using HTTP PUT queries under any path like /files/*/file_name.txt.
  • files.all.read: enables to fetch files using HTTP GET queries under any path like /files/*<user_id>*/file_name.txt.
  • task.read: the ability to view tasks only executed by the current user.
  • task.write: the ability to cancel a task only executed by the current user.
  • task.all.write: the ability to cancel any task of the platform.
  • task.all.read: the ability to view any task of the platform.
  • task.periodic.write: the ability to modify scheduled tasks.
  • task.periodic.read: the ability to view list of scheduled tasks of the platform.
  • task.periodic: ability to edit periodic tasks.
  • policy.write: the ability to change the SecurityPolicy field only for current user (like changing passwords).
  • policy.all.write: the ability to change SecurityPolicy field only for any users or roles (like changing password).
  • policy.all.read: the ability to read the SecurityPolicy of users or roles.
  • sys.snapshot: ability to create backup
  • sys.exe: ability to execute system call (avoid as much as possible)

Function permissions decorator

Permission must be declared in a decorator of at least of function in the program.

The following snippet illustrates the syntax:

@expose
@permission("api")
native fn modules(): Array<ModDesc>;

Now the function modules can only be called by a user who has the permission api in his token.

Several permissions can be composed in the same decorator, and then the semantic applied is a OR, as follows:

@permission("super", "normal")
fn test(){
    if(User::hasPermission("normal")){
        // normal user
    } else {
        // super
    }
}

The test can now be applied by a users which has either super or normal permission.

In case the permission influences the result, it can be dynamically checked by the helper hasPermission.

The same helper exists in SDK like TS for WebApplication that need

if(greycat.default.hasPermission("normal")){
    // call rpc
}

Permission is therefore the checkpoint that developers should rely on for adaptative applications.

Roles should only be used for configuration and never for dynamic checks!

Standard defaults roles

By default the standard library defines some roles that are pre-configured to ease all standard usages.

  • public: role associated with an anonymous user
    • public
  • superadmin: enable superuser to execute and manage everything, especially can add additional users
    • all
  • admin: can view and edit any part of the graph and task
    • public,web,abi,api,files.read,policy.write,graph.write,files.write,graph.read,task.read,task.write,files.write,files.all.write,policy.all.read,task.all.read,task.all.write,task.periodic.read,task.periodic.write
  • user: can view only API related data
    • public,web,abi,api,files.read,policy.write,graph.write
  • user_ex: can view any part of the graph and can upload files
    • public,web,abi,api,files.read,policy.write,graph.write,files.write,graph.read,task.read,task.write,task.periodic.read

Default init of roles

Most applications need to define in addition to standard roles their permissions. To do so, the type UserRole from the runtime module has two static methods all() and get(), see the following example:

fn main() {
  if (init == null || !init) {
    for (_, role in UserRole::all()) {
      if (role.name == "admin") {
        role.permissions.add("app.custom");
        UserRole::set(role);
      } else if (role.name === "user") {
        role.permissions.add("app.other");
        UserRole::set(role);
      }
    }
  }
}