The following table shows the versions of elasticsearch and jetty that Jetty Plugin was built with.
Jetty Plugin | Elasticsearch | Jetty |
---|---|---|
0.90.0 | 0.90.0 | 8.1.4.v20120524 |
0.20.1 | 0.20.2 | 8.1.4.v20120524 |
0.19.9-master | 0.19.9 | 8.1.4.v20120524 |
0.19.6-0.19.8 | 0.19.8 | 8.1.4.v20120524 |
0.19.0-0.19.5 | 0.19.2 | 7.4.5.v20110725 |
0.18.1-0.18.6 | 0.18.5 | 7.4.5.v20110725 |
0.18.0 | 0.18.4 | 7.4.5.v20110725 |
The elasticsearch-jetty plugin brings full power of Jetty and adds several new features to elasticsearch. With this plugin elasticsearch can now handle SSL connections, support basic authentication, and log all or some incoming requests in plain text or json formats.
The elasticsearch-jetty plugin can be installed as any other ES plugin using bin/plugin utility:
(specifying the URL is required since github downloads are going away)
$ bin/plugin -url https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-0.90.0.zip -install elasticsearch-jetty-0.90.0
The core of the plugin is JettyHttpServerTransport module that works as a replacement for NettyHttpServerTransport. To enable the elasticsearch-jetty plugin, the default netty http transport should be replaced with jetty http transport by adding the following line to elasticsearch.yml
.
http.type: com.sonian.elasticsearch.http.jetty.JettyHttpServerTransportModule
The elasticsearch-jetty plugin adds Server: Jetty(8.1.4.v20120524)
header to all responses. So, it’s possible to verify that jetty plugin is running by checking the response headers using the following curl command:
$ curl -I "http://localhost:9200/" HTTP/1.1 200 OK Content-Type: text/plain;charset=UTF-8 Access-Control-Allow-Origin: * Content-Length: 0 Server: Jetty(8.1.4.v20120524)
The embedded jetty is configured using standard jetty-*.xml
files. The list of config files can be specified using the sonian.elasticsearch.http.jetty.config
setting. This setting should contain a comma-separated list of jetty configuration files. The files are loaded one by one in the order specified in the setting and used to configure the Jetty server. Elasticsearch tries to find each file by checking the following locations:
- absolute path
- elasticsearch config directory
- elasticsearch classpath
- config directory in elasticsearch classpath
If the sonian.elasticsearch.http.jetty.config
setting is not set, the elasticsearch-jetty plugin tries to locate and load a single file called jetty.xml
.
The elasticsearch-jetty plugin comes with several generic jetty-*.xml
configuration files that can be used to simplify the plugin setup. These files can be found in the plugins/jetty/config
directory.
- jetty.xml – basic elasticsearch configuration file that should be always the first file in the list of config files.
- jetty-hash-auth.xml – adds login service for basic file-based authentication.
- jetty-restrict-all.xml and jetty-restrict-writes.xml – set of security constraint that requires password for all or write access to elasticsearch. Only one of these files should be used at a time.
- jetty-ssl.xml and jetty-strong-ssl.xml – both files add an SSL connector, the second file limits ciphers that SSL connector can use to only known strong ciphers. Only one of these files should be used at a time.
- jetty-gzip.xml – enables GZip support. If used, this file should be the last file in the list.
First step in enabling SSL support is generation of keys and certificates. The process is described on the How to Configure SSL page. For the test purposes, the keystore file from the elasticsearch-jetty plugin can be also used. The generated or downloaded keystore file should be places in the config
directory of elasticsearch. The SSL connector can be enabled by adding the following settings in the elasticsearch.yml
file:
http.type: com.sonian.elasticsearch.http.jetty.JettyHttpServerTransportModule sonian.elasticsearch.http.jetty: config: jetty.xml,jetty-ssl.xml ssl_port: 9443 keystore_password: "OBF:1nc01vuz1w8f1w1c1rbu1rac1w261w9b1vub1ndq"
The keystore_password
should contain the password used for keystore generation. The password "OBF:1nc01vuz1w8f1w1c1rbu1rac1w261w9b1vub1ndq"
can be used with the test keystore downloaded from the elasticsearch-jetty plugin page. The jetty-strong-ssl.xml
config file can be used instead of jetty-ssl.xml
if it’s required to disable known weak ciphers and protocols. The password can be obfuscated using Jetty Password Utility.
Setting up authentication for elasticsearch starts with configuring login service. The elasticsearch-jetty plugin comes with sample script jetty-hash-auth.xml that shows how to setup HashLoginService. This service obtains usersnames, passwords and roles from the file realm.properties
in the config
directory of elasticsearch. The file should contain a list of users, one line per user in the following format:
username: password[,rolename ...]
For example:
config/realm.properties
superuser: Adm1n,admin,readwrite user: Passw0rd,readwrite
The passwords can be obfuscated or MD5 hashed using Jetty Password Utility
After the login service is configured, the next step is to set security constraints. The elasticsearch-jetty plugin comes with two sample constraints configuration files: jetty-restrict-all.xml and jetty-restrict-writes.xml that demonstrate two different approaches to controlling access to elasticsearch. The first file requires password for any access to elasticsearch, and the second one uses more granular restrictions depending on the type of the access.
The following settings in elasticsearch.yml
will enable granular restrictions:
http.type: com.sonian.elasticsearch.http.jetty.JettyHttpServerTransportModule sonian.elasticsearch.http.jetty: config: jetty.xml,jetty-hash-auth.xml,jetty-restrict-writes.xml
Authentication can be used with SSL connector. The following settings will restrict access to all pages and enable SSL connector:
http.type: com.sonian.elasticsearch.http.jetty.JettyHttpServerTransportModule sonian.elasticsearch.http.jetty: config: jetty.xml,jetty-ssl.xml,jetty-hash-auth.xml,jetty-restrict-all.xml ssl_port: 9443 keystore_password: "OBF:1nc01vuz1w8f1w1c1rbu1rac1w261w9b1vub1ndq"
Security constraints in the elasticsearch-jetty plugin is very similar to security constraints in Jetty. The only difference is the custom security handler com.sonian.elasticsearch.http.jetty.security.RestConstraintSecurityHandler
, which is a modified version of standard Jetty security handler org.eclipse.jetty.security.ConstraintSecurityHandler
. The standard Jetty security handler is using servlet spec for path mapping, which makes it very difficult to express elasticsearch paths. The RestConstraintSecurityHandler
behaves identically to ConstraintSecurityHandler
but it treats path wildcards in a slightly different way. RestConstraintSecurityHandler
supports both named {name}
and anonymous *
wildcards. Both types of wildcards match exactly one element of the path and can appear at any position in the path. For example: /{index}/_search
will match /myindex/_search
but will not match /_search
or /myindex/mytype/_search
.
The elasticsearch-jetty plugin contains two versions of the HTTP Server Transport: JettyHttpServerTransport
and FilterHttpTransportModule
. While JettyHttpServerTransport
uses Jetty to handle all incoming requests, FilterHttpTransportModule
simply wraps another HTTP Server Transport (JettyHttpServerTransport
by default) to filter requests and responses. FilterHttpTransportModule
can be configured to pass all incoming requests through a chain of filters. The elasticsearch-jetty plugin contains one such filter that can be used for request logging.
In order to setup request logging, elasticsearch should be switched to use FilterHttpTransportModule
. It can be done by the following setting:
http.type: com.sonian.elasticsearch.http.filter.FilterHttpServerTransportModule
Then FilterHttpTransportModule
has to be configured with an appropriate filter:
sonian.elasticsearch.http.filter: http_filter_chain: ["logging"] http_filter: # Request logging filter logging: type: com.sonian.elasticsearch.http.filter.logging.LoggingFilterHttpServerAdapter logger: request format: text level: INFO log_body: false
This configuration will create one logger with the name request
that will log all incoming requests in plain text format on the INFO level and request bodies will not be logged. By default, this new logger will log all messages into the same log file as a standard elasticsearch logger. It’s possible to redirect requests logging into a separate log file. The following logging.yml
configuration specifies that logger request
logs on the INFO
level and above using appender request_log_file
, which is the same dailyRollingFile
appender that is used by elasticsearch, but it logs into logs/elasticsearch-request.log
instead of logs/elasticsearch.log
file. Dots “………” in the example below indicate existing lines in the logger
and appender
sections, that should be left intact.
logger: ........ request: INFO, request_log_file additivity: request: false appender: ......... request_log_file: type: dailyRollingFile file: ${path.logs}/${cluster.name}_requests.log datePattern: "'.'yyyy-MM-dd" layout: type: pattern conversionPattern: "[%d{ABSOLUTE}] %m%n"
Not all requests are equally important. For example, /_cluster/health
requests can be ignored, and body of a /_search
request is an important part of the request. So, the LoggingFilterHttpServerAdapter
can be configured to treat different request in different ways. The following elasticsearch.yml
fragment will cause cluster health, state, info and stats requests to be logged on the TRACE
level, while all _search
and _count
requests will be logged with request bodies.
sonian.elasticsearch.http.filter: http_filter_chain: ["logging"] http_filter: # Request logging filter logging: logger: request format: text type: com.sonian.elasticsearch.http.filter.logging.LoggingFilterHttpServerAdapter level: INFO log_body: false loggers: stats: path: ["/_cluster/health", "/_cluster/nodes", "/_cluster/state", "/_cluster/nodes/{node}/stats"] method: GET level: TRACE searches: path: ["/_search", "/_search/scroll", "/_search/scroll/{scroll_id}", "/{index}/_search", "/{index}/{type}/_search", "/{index}/{type}/{id}/_mlt"] method: GET, POST log_body: true count: path: ["/_count", "/{index}/_count", "/{index}/{type}/_count"] method: GET, POST log_body: true
The LoggingFilterHttpServerAdapter
can also support json
format, which is more difficult to read, but much easier to parse and index. FilterHttpTransportModule
supports chaining of multiple filters, see elasticsearch.xml for an example.
Compression of responses can be enabled by adding jetty-gzip.xml
to the end of the configuration file list:
sonian.elasticsearch.http.jetty: port: 9200 ssl_port: 9443 keystore_password: "OBF:1nc01vuz1w8f1w1c1rbu1rac1w261w9b1vub1ndq" config: jetty.xml,jetty-strong-ssl.xml,jetty-hash-auth.xml,jetty-restrict-writes.xml,jetty-gzip.xml
The following settings under sonian.elasticsearch.http.jetty
can be used to configure elasticsearch-jetty plugin
Setting | Description | Default | Used by |
---|---|---|---|
config |
List of jetty config files | jetty.xml |
plugin |
server_id |
The id of the Jetty Server that will handle elasticsearch requests | ESServer |
plugin |
port |
The port Jetty should listen on | http.port or 9200-9300 |
jetty.xml |
bind_host |
The port Jetty should listen on | http.bind_host or http.host |
jetty.xml |
publish_host |
The port Jetty should listen on | http.publish_host or http.host |
jetty.xml |
ssl_port |
The port SSL connector should listen on | jetty-ssl.xml and jetty-strong-ssl.xml |
|
ssl_bind_host |
The bind host SSL connector should use | jetty-ssl.xml and jetty-strong-ssl.xml |
|
keystore_password |
The keystore password for SSL connector. Plain text of obfuscated passwords can be used. Hashed passwords are not supported. | jetty-ssl.xml and jetty-strong-ssl.xml |
The elasticsearch-jetty plugin comes with several sample jetty*.xml
files, but it can be used with entirely custom configuration. For the plugin to function correctly the custom configuration has to only satisfy the following two requirements:
- The custom configuration has to create at least one Jetty server.
- The first connector of the created Jetty server has to be Internet Socket Connector. If the custom configuration creates more than one Jetty Server, the plugin tries to find server with ID specified in the
sonian.elasticsearch.http.jetty.server_id
, which isESServer
by default. If such server doesn’t exists, elasticsearch picks the Jetty Server that was created first. - All elasticsearch requests have to be handled by
JettyHttpServerTransportHandler
that has to be configured the following way:
<New class="com.sonian.elasticsearch.http.jetty.handler.JettyHttpServerTransportHandler" id="HttpServerAdapterHandler"> <Set name="transport"><Ref id="ESServerTransport"/></Set> </New>
To simplify custom configuration, the elasticsearch-jetty plugin exposes several ES settings as Jetty properties that can be used in Jetty configuration files using <Property name="property.name"/>
es.home
– ElasticSearch home directoryes.config
– ElasticSearch configuration directoryes.data
– ElasticSearch data directoryes.cluster.data
– ElasticSearch data directory for the clusteres.cluster
– Cluster namejetty.bind_host
– Http bind host, if the settingsonian.elasticsearch.http.jetty.bind_host
is not specified, ElasticSearch will try to use values specified inhttp.bind_host
andhttp.host
settings.jetty.port
– Http port, if the settingsonian.elasticsearch.http.jetty.port
is not specified, ElasticSearch will try to use http.port or default to 9200-9300. If port is specified in form of the range, ElasticSearch will try to start Jetty with each individual port number iterating through the range.jetty.*
– all other settings specified insonian.elasticsearch.http.jetty.
are exposed as Jetty properties. For example, the settingsonian.elasticsearch.http.jetty.foo
can be referred to in Jetty configuration as .
It also exposes two elasticsearch objects using the following ids:
ESServerTransport
– TheJettyHttpServerTransport
object that is needed to configureJettyHttpServerTransportHandler
properly.ESClient
– elasticsearch client that can be used by custom component to communicate to local instance of elasticsearch.
Join elasticsearch-jetty group for questions and discussions related to this plugin.