ADOPTERS.md- list of project adopters, other companies who may use this package.CODE_OF_CONDUCT.md- code of conductCONTRIBUTING.md- contributing guideLICENSE- our standard Apache 2.0 license
_____ _ ____ __
/ ___/(_)___ ___ ____ ____ / __ \____ _/ /_____ _
\__ \/ / __ `__ \/ __ \/ __ \ / / / / __ `/ __/ __ `/
___/ / / / / / / / /_/ / / / / / /_/ / /_/ / /_/ /_/ /
/____/_/_/ /_/ /_/\____/_/ /_/ /_____/\__,_/\__/\__,_/
This project serves as a blueprint for writing Scala plugins for the Trino Service Provider Interface (SPI). When Simon Data first got started with Presto, there wasn't a solid option for auth. These days, Apache Ranger will work for most, but there is still a benefit to be had in real-time notifications triggered by the EventListener plugin.
- Joel Edwards: @joeledwards
The initial version of this project was aimed only at implementing custom auth via SystemAccessControl. For this reason, the auth store is much more full featured than any other part of this project. The SystemAccessControl interface specifies the methods that Trino uses to determine which resources (catalog/schema/table) and actions (functions, etc.) are accessible for a given role when they submit a query.
Implement com.simondata.trino.auth.AuthRules to define your own custom auth rules. You can also adapt one of the
built-in example implementations.
The EventListener interface specifies methods that will be called for query lifecycle events (create/split/complete).
The SystemAccessControl interface is subject to major change between versions of Trino. The SystemAccessControl
interface bundled with Starburst's release is proprietary, expanding on the method definitions in the
open source trino-spi. We address this by defining SystemAccessControlStarburst which extends
io.trino.spi.security.SystemAcessControl and declares the additional funcions defined by Starburst.
Our implementations of SystemAccessControl extend SystemAccessControlStarburst instead, which ensures we are not
missing any of the Starburst additions, while still remaining backward compatible with the open source version of Trino.
We have a related issue with the SystemAccessControlFactory, where Starburst adds a LicenseManager parameter to
its create() method. We handle this by providing two overriden create() methods, permitting the right version to be
selected based on the version of Trino which loads our plugin.
In the event that a newer version of Starburst expands on the custom set of added methods, our XRay utility can
dump out a class' structure as JSON so we can keep SystemAccessControlStarburst in sync the proprietary version.
This will require inspecting the logs for messages containing "XRAY" in order to discover changes to the
interface structure. The classes which XRay inspects are specified in AuthMetrics.init().
Make sure you have the jdk installed for java 8 or greater.
Mac (x64):
brew cask install java
Mac (M1): Download the Zulu JDK dmg
Ubuntu:
sudo apt install default-jdk
While this project does target Java 11, any version of the JDK >= 11 can be used to build the project targeting version 11.
Make sure you have the latest version of sbt installed
Once this is installed, you should be able to build the project.
This is defined in build.sbt, and will pull the version of the dependency defined by trinoVersion.
The version of the SPI dependency needs to match the version of the Trino cluster to which we are adding the plugin.
Build a basic jar containing only our local classes:
$ sbt package
Build the full, fat jar containing all dependencies, with debug output:
$ sbt assembly
Build the full, fat jar, outputting the artifact name and instructions on where where the artifact should be placed on S3.
$ ./assemble.sh
The jar file will be written to target/scala-2.13/trino-plugins-<trino-version>-<git-hash>[-dirty].jar
(marked -dirty if we do not have a clean working tree in git)
Once the assemble.sh script has been used to generate the artifact (fat jar), a local Trino cluster can be
started within Docker according to the included docker-compose.yml file.
- docker
- docker-compose
You can start via the simple wrapper script (listening on localhost:8080):
$ ./start-trino.sh
You can optionally change the port exposed for the coordinator (listening on localhost:8888):
$ TRINO_PORT=8888 ./start-trino.sh
Configuration is applied via environment variables or the /etc/trino/cluster-info.properties file.
Each of the configuration descriptors below has a header of the following form: <description> (<type> = <default-value>)
When a configuration involves logging, it is applies to the logger and all of its targets. When disabled, it will neither log to disk nor to Slack (or any other custom auxiliary targets).
TRINO_PLUGINS_LOG_QUERY_CREATEDevents.log.query_created
TRINO_PLUGINS_LOG_QUERY_SUCCESSevents.log.query_success
TRINO_PLUGINS_LOG_QUERY_FAILUREevents.log.query_failure
TRINO_PLUGINS_LOG_SPLIT_COMPLETEevents.log.split_complete
TRINO_PLUGINS_SLACK_QUERY_CREATEDevents.slack.query_created
TRINO_PLUGINS_SLACK_QUERY_SUCCESSevents.slack.query_success
TRINO_PLUGINS_SLACK_QUERY_FAILUREevents.slack.query_failure
TRINO_PLUGINS_SLACK_SPLIT_COMPLETEevents.slack.split_complete
TRINO_PLUGINS_ENFORCE_AUTHauth.enforce
TRINO_PLUGINS_ENVIRONMENTenvironment
TRINO_PLUGINS_SLACK_WEBHOOK_URLnotifications.slack.webhook
TRINO_PLUGINS_CLUSTERtrino.cluster.name
TRINO_PLUGINS_NODE_TYPEtrino.node.type
There are a variety of requirements which must be met in order for a plugin to be correctly built and installed.
- The plugin is loaded by creating an instances of the declared plugin class (implements
io.trino.spi.Plugin), fetching an instance of a factory (e.g., implementsio.trino.spi.security.SystemAccessControlFactory) which must be an instance of an inner class that implementsPlugin. Since Scala does not support no-arg constructors, the plugin entry point must be a Java source file (seecom.simondata.trino.TrinoPlugins.java). This Java file may reference any Scala type, including traits. However, due to Scala's lack of no-arg constructors, a Scala class can not be the entry point (guice cannot instantiate a Scala class in order to inject it). - Include a file named
io.trino.spi.Pluginmust reside inMETA-INF/services/containing the fully-qualified classname. In our case,com.simondata.trino.TrinoPlugins. - The generated jar must be deployed into the plugin directory on trino in a directory with the same name as the plugin.
In our case, the directory is named
trino-plugins/. - The file
access-control.propertiesmust be defined in the trinoetc/directory. The file must begin with the lineaccess-control.name=<plugin-name>. In our case the first config line isaccess-control.name=trino-auth. - The file
event-listener.propertiesmust be defined in the trinoetc/directory. The file must begin with the lineaccess-control.name=<plugin-name>. In our case the first config line isaccess-control.name=trino-events. - Plugins must be loaded by all coordinators and workers.
- The default location for plugins is
/usr/lib/trino/lib/plugin/. This can be changed, but would then require that all plugins be relocated to the new plugin directory.
The assemble.sh scripts takes cares of the top two issues.