Skip to content

Security: cuebook/turnilo

Security

docs/security.md

This document has not been updated yet, enter at your own risk.

Security in Turnilo

User management

Turnilo does not currently have a concept of a user. Everyone who has access to a given Turnilo server has equal access to that server. Turnilo can act as a 'gatekeeper' for Druid or any supported datasource via the config.

Data cubes level access

It is possible to restrict which data cubes users have access to by explicitly defining in the config all the data cubes that you want the users to see and disabling source discovery. This will prevent any data cube not explicitly defined from being queried through Turnilo.

Alternatively you can set up auth proxy (eg. nginx) which will be adding header x-turnilo-allow-datacubes. It have to contains names of datacubes which have to be accessible for user, delimited by comma. Wildcard(*) means all datacubes. Examples of x-turnilo-allow-datacubes:

  • "*"
  • "some-name"
  • "name1,name2"
  • "name1,name2,*"

Additionally, enable guard by adding in config in cluster section:

clusters:
  - name: druid
[...]	
    guardDataCubes: true
[...]

Column level access

It is possible restrict which columns users have access to by explicitly defining all the dimensions and measures that you want the users to see and disabling introspection. Any query asking for a column that was not explicitly defined in the dimensions or measures will fail.

Row level access

A Turnilo dataSource can define a subsetFormula that is a boolean Plywood filter clause that will be silently applied to all queries made to that data cube. For example if you wanted your users to only see the data for "United States" you could add subsetFormula: $country == "United States" to the data cube definition.

Authentication

Turnilo can authenticate to a Druid server via request decoration. You can utilize it as follows:

In the config add a key of druidRequestDecorator that point to a relative js file.

druidRequestDecorator: './druid-request-decorator.js'

Then the contract is that your module should export a function druidRequestDecorator that has to return a decorator.

A decorator is a function that gets called on every request and receives a Druid query and may return an object with the key headers where you can set whatever headers you want.

Here is an example decorator:

exports.version = 1;

// logger - is just a collection of functions that you should use instead of console to have your logs included with the Turnilo logs
// options - is an object with the following keys:
//   * cluster: Cluster - the cluster object
exports.druidRequestDecoratorFactory = function (logger, params) {
  var options = params.options;
  var myUsername = options.myUsername; // pretend we store the username and password
  var myPassword = options.myPassword; // in the config

  if (!myUsername) throw new Error('must have username');
  if (!myPassword) throw new Error('must have password');

  logger.log("Decorator init for username: " + myUsername);

  var auth = "Basic " + Buffer(myUsername + ":" + myPassword).toString('base64');

  // decoratorRequest: DecoratorRequest - is an object that has the following keys:
  //   * method: string - the method that is used (POST or GET)
  //   * url: string -
  //   * query: Druid.Query -
  return function (decoratorRequest) {

    var decoration = {
      headers: {
        "Authorization": auth,
        "X-I-Like": "Koalas"
      }
    };

    // This can also be async if instead of a value of a promise is returned.
    return decoration;
  };
};

You can find this example, with an example config, in the ./example folder.

This would result in all Druid requests being tagged as:

decoration example

There aren’t any published security advisories