The following table shows the versions of elasticsearch and jetty that Jetty Plugin was built with.
| Jetty Plugin | Elasticsearch | Jetty |
|---|---|---|
| 1.0.0 | 1.0.0 | 8.1.14.v20131031 |
| 0.90.10.* | 0.90.10 | 8.1.14.v20131031 |
| 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://s3.amazonaws.com/www.emergi.net/elasticsearch/plugins/elasticsearch-jetty-1.0.0.zip -install elasticsearch-jetty-1.0.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.14.v20131031) 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.14.v20131031)
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 isESServerby default. If such server doesn’t exists, elasticsearch picks the Jetty Server that was created first. - All elasticsearch requests have to be handled by
JettyHttpServerTransportHandlerthat 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_hostis not specified, ElasticSearch will try to use values specified inhttp.bind_hostandhttp.hostsettings.jetty.port– Http port, if the settingsonian.elasticsearch.http.jetty.portis 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.foocan be referred to in Jetty configuration as .
It also exposes two elasticsearch objects using the following ids:
ESServerTransport– TheJettyHttpServerTransportobject that is needed to configureJettyHttpServerTransportHandlerproperly.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.