Permissions
Overview
Deephaven enables fine-grained access control to data, queries and reports. This is accomplished through the individual authorization of users and groups, access control lists (ACLs) and account information.
Authorized users can edit the access settings and permissions by using the DB ACL Editor tool in the console, or through the command line tool, IrisDbUserMod
. The following command will run the tool:
sudo service iris irisdbuser_mod --interactive
Note: Adding a new user to IrisDbUserMod
or the ACL Editor does not add the new user to the Deephaven installation. The user must also be permitted to login to Deephaven, which is accomplished during the installation process.
ACL Editor
The ACL Editor can be accessed by clicking the Advanced button in the Deephaven Console.
Note: If you are not authorized by your enterprise to review or modify these settings, the ACL Editor option in the drop-down menu will not appear.
When selected, a dialog window will provide an option to rename the panel, as shown below.
You may rename the panel title or accept the defaults. Click OK to open the DB ACL Editor window, as shown below.
The following tabs are presented at the top of the resulting window:
- User/Groups
- Accounts (if configured)
- Table ACLs
- Input Tables
User/Groups
The User/Groups panel shows the available options to manage individual users and groups.
User Administration
The User Administration section (on the left side of panel) includes options for adding and deleting users, or changing an individual user's password, as shown below.
Adding Users
To add a new user, type the new user's username in the field directly under "User Administration". If Managed User Authentication is enabled, there will also be a field for the user's initial password. Click Add User to create the new user.
Note: Adding a new user in this panel only sets the permission/authorization level for a user. It does not add the user to the overall Deephaven application. Also, once a new user is added, the new user can change his/her password at anytime using the Change Password option after clicking the Advanced button in the Deephaven Console.
Deleting Users
To delete a user, select the user's name in the drop-down menu to the left of the Delete User button, then click Delete User. This will delete the user, the user's eponymous group, and all Table ACL entries associated with that user.
Changing Passwords
If Managed User Authentication is enabled, it is possible to change a user's password in the ACL editor. To change an existing user's password, select the user's name in the drop-down menu to the left of the Change Password button, enter the new password in the next field, and then click Change Password.
Note: Change Password operations are only available when iris.enableManagedUserAuthentication
is set to true. Additionally, the authentication server must have MySQL authentication enabled via these properties:
authentication.server.customauth.enabled=true
authentication.server.customauth.class=com.illumon.iris.db.v2.permissions.MysqlDbAclProvider
Group Administration
The Group Administration section (on the right side of panel) includes options for adding and deleting users or changing an individual user's password, as shown below.
- To add a user to a specific group, select the user's name in the drop-down menu directly below Group Administration. Then select the Group Name in the next drop-down field and click Add User to Group. Note: All new users automatically become a member of the
allusers
group. Each new user is also added to a group titled with their own username. However, the administration of a group named for an individual user cannot be processed in this panel. - To delete a Group, select the group name from the drop-down list to the left of the Delete Group button, then click Delete Group.
Creating a New Group
Each Group must have at least one member. Therefore, to create a new group, you must first select a user's name in the drop-down menu directly below the Group Administration title. Then, highlight all the text in the Group field to the right, and type in the name of the new group. Click Add User To Group.
The image below demonstrates a user named Fred
being added to a new group called NewCoolGroup
:
A list showing User names and Group names is presented in the lower portion of the panel.
This list can be filtered by entering an applicable term in the Filter field above the list. Regular expressions can be used in the filter after selecting the Regex check box. Default group mappings can be shown by selecting the Show Default Group Mappings check box.
Deleting a User from a Group
To delete a user from a specific group, find the row in the table that shows the appropriate user's name and the Group name for which he/she should be removed. Right-click anywhere in the row and select Delete User To Group Mappings from the context menu, as shown below.
After Delete User to Group Mappings is selected, a dialog window will prompt you to confirm the deletion. Click Yes to delete the user from the group. Click No to cancel the deletion process.
Special Groups
The following groups are used to provide specific access in Deephaven:
Group Name |
Access |
---|---|
|
Members of this group may open interactive consoles and create workers. In our default installation, all users are assigned to the |
|
Members of this group are not able to open a console, but will be allowed access through the controller if they have the required privileges (i.e., they can start and stop workers, create queries, and so on). |
|
Members of this group can view queries, but are not allowed to create or edit them. If a user is not assigned to a privileged group, they are |
iris-acleditors |
Members of this group can use the ACL Editor panel. |
iris-superusers |
Members of this group can view, edit, start, stop, and delete any persistent queries and all tables within a persistent query. |
iris-querymanagers |
Members of this group can stop and start all of the queries, but are not allowed to edit them or see the tables (unless otherwise permissioned). |
iris-schemamanagers |
Members of this group can use the Schema Editor panel. |
Group Supervisors
Another level of authorization is available for group supervisors. Group supervisors automatically have owner/admin rights for persistent queries owned by anyone in the group. This is accomplished by adding the supervisor to a new group named with the following syntax: <group name>-supervisors
.
For example, for a group named quantpros
, a supervisor of that group can be granted owner/admin authorization for that group by adding him/her to a new group quantpros-supervisors
. Multiple individuals can have the supervisor authorization for a group.
Accounts
The Accounts tab is only visible if configured by the Deephaven system administrator using the DbAclEditor.showAccountTab
property.
The Accounts tab only applies to tables filtered with AccountFilterGenerator()
and StrategyFilterGenerator()
, and provides two levels of mappings from groups to accounts.
- Groups are associated with a "Strategy" (e.g., "TradeGroup1", "TradeGroup2" or "TradeGroup3").
- "Strategies" are associated with Accounts (e.g., "TradeGroup1" is associated with "ABC_ACCOUNT", "XYZ_ACCOUNT", and "MNO_ACCOUNT").
This extra level of indirection makes it simpler to add a user to a set of accounts.
Table ACLs
The Table ACLs panel enables the authorization of group access to namespaces and tables.
Before returning a table to a user, Deephaven applies all of the ACLs for that user. ACLs determine the rows that a user can see in the table; they cannot change the columns that a user can see in a table. ACLs are implemented with where operations that are automatically applied to the table.
Each ACL consists of four components:
- Group: The name of the group to which this ACL is associated.
- Namespace: The namespace associated with this ACL, to apply to all tables. This may be the wild card "
*
", which means all namespaces are included. Note: If the namespace is "*
", the table must also be "*
". - Table: The table with which this ACL is associated. The wild card, "
*
", applies this entry to all tables within the namespace. - Table Filter: A string that represents Java code to create a filter for this table.
Table Filters
Using Java code to generate the filters provides additional flexibility. For example, a filter generator could be
new AccountFilterGenerator()
, which would filter the Account column based on the accounts for which the current user is authorized.
However, writing Java code to generate the filters can be a bit tedious, so there are two shorthand notations available:
*
means that all rows in the table should be presented to the user, and- if a filter generator is of the form
whereClause(A, B)
,whereClause(C, D)
, then the rows that match(A && B) || (C && D)
are available to the user.
To compute the ACLs that should be used for a given user, the following steps are taken:
- All of the user's groups are collected into a list.
- For each group, get the ACL generator for the table, namespace, or default (in that order).
- If no ACL generator was found, then deny permission.
- Run all of the ACL generators (unless one returns the empty set of filters, which means permit everything).
- If all generators returned null, deny permission (Note: If a generator returns null, that means deny; if it returns an empty list, that means permit everything).
- Apply a .
whereOneOf()
operation to the table with all the returned filters.
When computing the list of ACLs for a table, the most specific ACL for a particular group is used. For example, if "UserXYZ" belongs to the groups "groupABC", "groupXYZ", and "allusers", and if the following ACLs exist:
Group |
Namespace |
Table |
Filter |
---|---|---|---|
allusers |
* |
* |
new OwnNamespaceGenerator() |
groupABC |
SystemEQ |
PositionCache |
new AccountFilterGenerator() |
groupABC |
SystemEQ |
* |
* |
groupXYZ |
SystemEQ |
* |
whereClause(`false`) |
Then, the ACL generators that would be used for the SystemEQ.PositionCache table are:
- new
OwnNamespaceGenerator()
for allusers, because no more specific ACL exists for that group. - new
AccountFilterGenerator()
for groupABC, becauseSystemEQ.PositionCache
is more specific thanSystemEQ.*
(the "*" filter would be unused in this case) whereClause(`false`)
for groupXYZ
The OwnNamespaceGenerator
would return null because the SystemEQ
namespace is not equal to the username UserXYZ
, thus contributing no filters. The AccountFilterGenerator
would return a match filter for the account column. Finally, the whereClause(`false`)
produces a match filter with no results. This has the effect of allowing the user to see an empty table, but without denying permission. When taken together, groupABC
could see rows in SystemEQ.PositionCache
that have the appropriate accounts configured.
If any other table from the SystemEQ
namespace were requested, then the SystemEQ.* ACL
would be the most specific ACL for group ABC, resulting in an ACL of "*
", which would short-circuit further evaluation; and all rows would be visible.
Note: Adding a user to a group can only increase the permissions enabled for that user. Users cannot lose any existing permissions by being added to another group (e.g., if a group has the NullFilterGenerator() applied, any pre-existing user permissions would not be impacted.)
Filter Generators
The filter generator string in the ACL should create a FilterGenerator
object. Most of these strings will use one of the following built-in filter generators:
EmptyFilterGenerator() |
Provides full access to a table; it can be abbreviated as " |
---|---|
SimpleFilterGenerator() |
Passes through a simple where clause; it can be abbreviated by using a filter generator string beginning with |
AccountFilterGenerator() |
Creates a match filter for accounts for which this user is authorized; suitable for restricting position logs, trade logs, etc. to just the accounts a user should see. By default, this filters the Account column, but an optional column name can be passed into the generator. |
StrategyFilterGenerator() |
Creates a match filter for strategies for which this user is authorized. By default, this filters the Strategy column, but an optional column name can be passed in to the generator. |
OwnNamespaceFilterGenerator() |
Produces an empty filter (i.e., allow everything) when the namespace matches the effective user name; otherwise produces null (i.e., no filter). This allows users to have full access to their own user tables. |
UsernameFilterGenerator() |
Creates a match filter for this user's username. By default, this filters the Username column, but an optional column name can be passed in to the generator. |
UserCollectionFilterGenerator |
Creates a filter for this user's username within a collection. By default, this filters the Username column, but an optional column name can be passed in to the generator. This is useful, for example if a table column contains a list of authorized users for each row. |
GroupFilterGenerator() |
Creates a match filter for groups to which this user belongs. By default, this filters the Group column, but an optional column name can be passed in to the generator. |
WorkerNameFilterGenerator() |
Produces a filter that matches only this worker. By default, this filters the Note: the |
RequestIdFromWorkerNameFilterGenerator() |
Produces a dynamic where filter based on the Note: the |
NullFilterGenerator() |
Provides no access to a table; only useful to override a less-specific ACL for a group. |
ConjunctiveFilterGenerator(fg1, fg2, ...) |
Runs filter generators |
CopyFilterGenerator(Namespace, Table) |
Copies the ACLs from another table to this table. |
Permission Analyzer
The Permission Analyzer can be used to review the table permissions associated with any particular user. To access this tool, click the Permission Analyzer button on the Table ACLs panel. Then select the appropriate User, Namespace and TableName in the drop-down menus to review the permissions granted. The example below shows the permissions for user123
in regard to the DXFeed
namespace and the TradeStock
table. The bottom part of the panel shows that full read permission is allowed for that user (as noted by the *).
Selecting the Show groups without ACLs check box adds the names of the groups associated with that user and each group's respective permission levels, as shown below.
Input Tables
Setting the authorization for individual/group access for reading data in tables is accomplished through the Table ACLs tab. However, setting the authorization of individuals or groups to edit tables is accomplished in the Input Tables tab.
Note: When a user or group is authorized to edit a table, the entire table may be edited. Setting authorization for editing only a portion of the table is not supported.
Persistent Query ACLs
Just as Access Control Lists can be applied to tables, they can also be applied to persistent queries. The owner of a query, as well as designated administrator groups, have full access to the query. They can see every table and are able to edit the query, restart it, stop it, etc. The owner and administrator can also select groups that can view the query. Viewer groups are not able to view the query source code, stop, start, or edit the query.
However, permissions do not carryover to the plots generated by those same persistent queries. To set access control for viewing these plots, you must use the setValidGroups
method in the persistent query that generates the plot. See below for more about Setting Permissions for Viewing Plots.
Tables
As part of the Groovy code, filters can be added to tables. These filters do not take effect for the owner, admin, or members of the iris-superusers group; only for viewers. If no filters are defined on any table, then viewers can see all of the rows in all of the tables produced by the query. If there is a filter defined for at least one table, then viewers cannot see any tables without filters. This has the effect of making it convenient to let people see the full results of a query. Assuming care is taken to restrict part of the query, the parts that have not been addressed from a security perspective are hidden.
Filters are applied to tables as follows:
TableFilterProvider.FACTORY.create(db, table).addFilter("group", "filter1", "filter2", ...)
Where db
is the database object, group
is the group to which access is provided, and filter1
, filter2
, etc. are filter generator expressions to add (disjunctively). The format of the filter expressions is the same as for Table ACLs defined in the DB ACL Editor.
Filters can be chained, for example:
TableFilterProvider.FACTORY.create(db, table).addFilter("group1", "*").addFilter("group2", "whereClause(\"A=`B`\"").addFilter("group2", "whereClause(\"A=`C`\", \"D=`E`\")")
In this example, group1
may access the entire table; but group2
can only view rows where A
is equal to B
, or rows where A
is equal to C
, and D
is equal to E
.
Setting Permissions for Viewing Plots
The ability to see and edit persistent queries and the tables they generate is determined by the settings used by the query author in the Access Control tab of the Persistent Query Configuration panel. However, those permissions do not carryover to the plots generated by those same persistent queries.
To set access control for viewing these plots, you must use the setValidGroups
method in the persistent query that generates the plot.
Syntax
setValidGroups(String... validGroups)
setValidGroups(Collection<String> validGroups)
To limit viewing access to a particular plot, first write the query to create and show the plot. Then, assign the setValidGroups
method to that plot. Note: in a Python query, the .setValidGroups
argument must be on a separate line. Arguments to setValidGroups
method include the names of the User(s) and Group(s) you want to be allowed to see the plot.
For example, the following query creates an XY Series chart to show the price of a single security (PFE
) over the course of one day. No viewing restrictions are currently in place.
t1 = db.t("LearnIris","StockTrades").where("Date=`2017-08-24`","USym=`PFE`")
PlotPFE = plot("PFE", t1, "Timestamp", "Last")
.xBusinessTime()
.show()
To set the viewing permissions for this plot, add the following line to the query.
PlotPFE.setValidGroups("User1", "User2", "Group1")
When this query is executed in Deephaven, only User1
, User2
and individuals included in Group1
would be allowed to open and view the plot using the Show Widget button in the Deephaven console.
For example, if User3
was not included in Group1
, User3
would not be able to view PlotPFE
even if User3
was authorized to view the persistent query and/or the tables generated by the persistent query.
Note: The setValidGroups
method will have the same effect as the addFilter
method (described above in the Tables section) in that, if used, any table without restrictions will also be hidden.
Keep in mind that the setValidGroups
method does not differentiate the data shown to each user. The widget can make use of the IrisWidgetSupport getIrisUserContext
method to restrict information based on the user.
The LiveWidgetVisibilityProvider
interface can be implemented by a widget to restrict the set of users that can load the widget. However, it does not differentiate the data shown to each user. The widget can make use of the IrisWidgetSupport getIrisUserContext
method to restrict information based on the user.
Authentication Server Third-Party ACL Integration
System administrators are able to create and implement Deephaven Authentication Server plug-ins that will execute Java code upon certain Authentication Server actions, such as user login or token verification.
This document describes a specific use case in which an "Auth Hook" (plug-in) can be created to request and parse data from an external server and then import that data into the Deephaven system. The imported data may then be utilized in the ACL Editor by a corresponding, custom filter generator.
The following graphic demonstrates the general process:
Setup
There are four steps required to implementing the above system:
- Create the authentication server plug-in by creating a class that implements the
AuthHookModule
interface. - Specify the plug-in through the
authentication.server.hooks.class
property. - Set up a tailer to import logged data real-time.
- Create a custom filter generator that utilizes the imported data within an ACL.
AuthHookModule Interface
To create your authentication hook, you must create a class that implements the com.fishlib.auth.AuthHookModule
interface and overrides its methods.
The AuthHookModule
interface follows:
package com.fishlib.auth;
/**
* This interface allows you to run actions after useful authentication server operations; for example you may use
* an AuthHookModule to perform post-login refresh of ACL entries.
*
* Implementations must implement a Constructor which takes a com.fishlib.io.logger.Logger.
*/
public interface AuthHookModule {
/**
* Called after a client successfully logs in to the authentication server.
*
* userContext is the context of the user logging in
*
void onLogin(UserContext userContext)
/**
* Called after a client logs out from the authentication server (i.e. disconnects).
*
* userContext is the context of the user logging out
*/
void onLogout(UserContext userContext);
/**
* Called after an authentication token is created.
*
* authenticatedContext is the context of the user creating the token
* service is the service the user is creating a token for
*/
void onTokenCreate(UserContext authenticatedContext, String service);
/**
* Called after an authentication token is verified
*
* authenticatedContext is the context of the verified token
* service is the service for which the token is valid
*/
void onTokenVerify(UserContext authenticatedContext, String service);
/**
* Called after an authentication token fails verification
*
* authenticatedContext is the context of the verified token
* service is the service for which the token is valid
*/
void onTokenVerifyFailure(UserContext authenticatedContext, String service);
/**
* Called after the authentication server configuration is reloaded.
*/
void onReload();
class Null implements AuthHookModule {
@Override
public void onLogin(UserContext userContext) {
}
@Override
public void onLogout(UserContext userContext) {
}
@Override
public void onTokenCreate(UserContext authenticatedContext, String service) {
}
@Override
public void onTokenVerify(UserContext authenticatedContext, String service) {
}
@Override
public void onTokenVerifyFailure(UserContext authenticatedContext, String service) {
}
@Override
public void onReload() {
}
}
}
The nested com.fishlib.auth.AuthHookModule.Null
class provides an implementation with empty methods, which you may use as your base class. By using the Null
implementation as your base, you only need to implement methods required for your use case, and your extension will continue to compile if additional methods are added to the AuthHookModule
interface.
Authentication Server Hooks Property
To utilize the AuthHookModule
implementation, you must specify the fully qualified class name of the hook in the authentication.server.hooks.class
property:
authentication.server.hooks.class=<fully qualified class name>
Data Import
Authentication hooks may utilize a logger like a client logger application would. If this is the case, you will need to set up a tailer to import the logged data real-time. Please refer to Importing Data > Binary Log Tailer for an example of tailer installation and configuration.
Custom Filter Generator
If you'd like to utilize the imported data in the ACL Editor, you must create a class that implements the FilterGenerator interface, and then apply it as an ACL. Refer to the Deephaven Javadocs and the ACL Editor documentation to learn more.
Last Updated: 23 September 2019 12:17 -04:00 UTC Deephaven v.1.20181212 (See other versions)
Deephaven Documentation Copyright 2016-2019 Deephaven Data Labs, LLC All Rights Reserved