Help for plugin authorsedit

The Elasticsearch repository contains examples of:

  • a Java plugin which contains a plugin with custom settings.
  • a Java plugin which contains a plugin that registers a Rest handler.
  • a Java plugin which contains a rescore plugin.
  • a Java plugin which contains a script plugin.

These examples provide the bare bones needed to get started. For more information about how to write a plugin, we recommend looking at the plugins listed in this documentation for inspiration.

Plugin descriptor fileedit

All plugins must contain a file called plugin-descriptor.properties. The format for this file is described in detail in this example:

# Elasticsearch plugin descriptor file
# This file must exist as 'plugin-descriptor.properties' inside a plugin.
#
### example plugin for "foo"
#
# foo.zip <-- zip file for the plugin, with this structure:
# |____   <arbitrary name1>.jar <-- classes, resources, dependencies
# |____   <arbitrary nameN>.jar <-- any number of jars
# |____   plugin-descriptor.properties <-- example contents below:
#
# classname=foo.bar.BazPlugin
# description=My cool plugin
# version=6.0
# elasticsearch.version=6.0
# java.version=1.8
#
### mandatory elements for all plugins:
#
# 'type': the type of this plugin. 'isolated' indicated a typical sandboxed plugin,
# whereas 'bootstrap' indicates a plugin whose jars are added to the JVM's boot
# classpath.
type=${type}
#
# 'description': simple summary of the plugin
description=${description}
#
# 'version': plugin's version
version=${version}
#
# 'name': the plugin name
name=${name}
<% if (type != "bootstrap") { %>
#
# 'classname': the name of the class to load, fully-qualified. Only applies to
# "isolated" plugins
classname=${classname}
<% } %>
#
# 'java.version': version of java the code is built against
# use the system property java.specification.version
# version string must be a sequence of nonnegative decimal integers
# separated by "."'s and may have leading zeros
java.version=${javaVersion}
#
# 'elasticsearch.version': version of elasticsearch compiled against
elasticsearch.version=${elasticsearchVersion}
### optional elements for plugins:
#
#  'extended.plugins': other plugins this plugin extends through SPI
extended.plugins=${extendedPlugins}
#
# 'has.native.controller': whether or not the plugin has a native controller
has.native.controller=${hasNativeController}
<% if (type == "bootstrap") { %>
#
# 'java.opts': any additional command line parameters to pass to the JVM when
# Elasticsearch starts. Only applies to "bootstrap" plugins.
java.opts=${javaOpts}
<% } %>
<% if (licensed) { %>
# This plugin requires that a license agreement be accepted before installation
licensed=${licensed}
<% } %>

Either fill in this template yourself or, if you are using Elasticsearch’s Gradle build system, you can fill in the necessary values in the build.gradle file for your plugin.

Mandatory elements for pluginsedit

Element Type Description

description

String

simple summary of the plugin

version

String

plugin’s version

name

String

the plugin name

classname

String

the name of the class to load, fully-qualified.

java.version

String

version of java the code is built against. Use the system property java.specification.version. Version string must be a sequence of nonnegative decimal integers separated by "."'s and may have leading zeros.

elasticsearch.version

String

version of Elasticsearch compiled against.

Note that only jar files at the root of the plugin are added to the classpath for the plugin! If you need other resources, package them into a resources jar.

Plugin release lifecycle

You will have to release a new version of the plugin for each new Elasticsearch release. This version is checked when the plugin is loaded so Elasticsearch will refuse to start in the presence of plugins with the incorrect elasticsearch.version.

Testing your pluginedit

When testing a Java plugin, it will only be auto-loaded if it is in the plugins/ directory. Use bin/elasticsearch-plugin install file:///path/to/your/plugin to install your plugin for testing.

You may also load your plugin within the test framework for integration tests. Read more in Changing Node Configuration.

Java Security permissionsedit

Some plugins may need additional security permissions. A plugin can include the optional plugin-security.policy file containing grant statements for additional permissions. Any additional permissions will be displayed to the user with a large warning, and they will have to confirm them when installing the plugin interactively. So if possible, it is best to avoid requesting any spurious permissions!

If you are using the Elasticsearch Gradle build system, place this file in src/main/plugin-metadata and it will be applied during unit tests as well.

Keep in mind that the Java security model is stack-based, and the additional permissions will only be granted to the jars in your plugin, so you will have write proper security code around operations requiring elevated privileges. It is recommended to add a check to prevent unprivileged code (such as scripts) from gaining escalated permissions. For example:

// ES permission you should check before doPrivileged() blocks
import org.elasticsearch.SpecialPermission;

SecurityManager sm = System.getSecurityManager();
if (sm != null) {
  // unprivileged code such as scripts do not have SpecialPermission
  sm.checkPermission(new SpecialPermission());
}
AccessController.doPrivileged(
  // sensitive operation
);

See Secure Coding Guidelines for Java SE for more information.