[[modules-scripting-security]]
=== Scripting and security

While Elasticsearch contributors make every effort to prevent scripts from
running amok, security is something best done in
https://en.wikipedia.org/wiki/Defense_in_depth_(computing)[layers] because
all software has bugs and it is important to minimize the risk of failure in
any security layer. Find below rules of thumb for how to keep Elasticsearch
from being a vulnerability.

[float]
=== Do not run as root
First and foremost, never run Elasticsearch as the `root` user as this would
allow any successful effort to circumvent the other security layers to do
*anything* on your server. Elasticsearch will refuse to start if it detects
that it is running as `root` but this is so important that it is worth double
and triple checking.

[float]
=== Do not expose Elasticsearch directly to users
Do not expose Elasticsearch directly to users, instead have an application
make requests on behalf of users. If this is not possible, have an application
to sanitize requests from users. If *that* is not possible then have some
mechanism to track which users did what. Understand that it is quite possible
to write a <<search, `_search`>> that overwhelms Elasticsearch and brings down
the cluster. All such searches should be considered bugs and the Elasticsearch
contributors make an effort to prevent this but they are still possible.

[float]
=== Do not expose Elasticsearch directly to the Internet
Do not expose Elasticsearch to the Internet, instead have an application
make requests on behalf of the Internet. Do not entertain the thought of having
an application "sanitize" requests to Elasticsearch. Understand that it is
possible for a sufficiently determined malicious user to write searches that
overwhelm the Elasticsearch cluster and bring it down. For example:

Good:
* Users type text into a search box and the text is sent directly to a
<<query-dsl-match-query>>, <<query-dsl-match-query-phrase>>,
<<query-dsl-simple-query-string-query>>, or any of the <<search-suggesters>>.
* Running a script with any of the above queries that was written as part of
the application development process.
* Running a script with `params` provided by users.
* User actions makes documents with a fixed structure.

Bad:
* Users can write arbitrary scripts, queries, `_search` requests.
* User actions make documents with structure defined by users.

[float]
[[modules-scripting-security-do-no-weaken]]
=== Do not weaken script security settings
By default Elasticsearch will run inline, stored, and filesystem scripts for
the builtin languages, namely the scripting language Painless, the template
language Mustache, and the expression language Expressions. These *ought* to be
safe to expose to trusted users and to your application servers because they
have strong security sandboxes. The Elasticsearch committers do not support any
non-sandboxed scripting languages and using any would be a poor choice because:
1. This drops a layer of security, leaving only Elasticsearch's builtin
<<modules-scripting-other-layers, security layers>>.
2. Non-sandboxed scripts have unchecked access to Elasticsearch's internals and
can cause all kinds of trouble if misused.


[float]
[[modules-scripting-other-layers]]
=== Other security layers
In addition to user privileges and script sandboxing Elasticsearch uses the
http://www.oracle.com/technetwork/java/seccodeguide-139067.html[Java Security Manager]
and native security tools as additional layers of security.

As part of its startup sequence Elasticsearch enables the Java Security Manager
which limits the actions that can be taken by portions of the code. Painless
uses this to limit the actions that generated Painless scripts can take,
preventing them from being able to do things like write files and listen to
sockets.

Elasticsearch uses
https://en.wikipedia.org/wiki/Seccomp[seccomp] in Linux,
https://www.chromium.org/developers/design-documents/sandbox/osx-sandboxing-design[Seatbelt]
in macOS, and
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684147[ActiveProcessLimit]
on Windows to prevent Elasticsearch from forking or executing other processes.

Below this we describe the security settings for scripts and how you can
change from the defaults described above. You should be very, very careful
when allowing more than the defaults. Any extra permissions weakens the total
security of the Elasticsearch deployment.

[[security-script-source]]
[float]
=== Script source settings

Which scripts Elasticsearch will execute where is controlled by settings
starting with `scripts.`. The simplest settings allow scripts to be enabled
or disabled based on where they are stored. For example:

[source,yaml]
-----------------------------------
script.inline: false  <1>
script.stored: false  <2>
script.file:   true   <3>
-----------------------------------
<1> Refuse to run scripts provided inline in the API.
<2> Refuse to run scripts stored using the API.
<3> Run scripts found on the filesystem in `/etc/elasticsearch/scripts`
(rpm or deb) or `config/scripts` (zip or tar).

NOTE: These settings override the defaults mentioned
<<modules-scripting-security-do-no-weaken, above>>. Recreating the defaults
requires more fine grained settings described <<security-script-fine, below>>.

[[security-script-context]]
[float]
=== Script context settings

Scripting may also be enabled or disabled in different contexts in the
Elasticsearch API. The supported contexts are:

[horizontal]
`aggs`::    Aggregations
`search`::  Search api, Percolator API and Suggester API
`update`::  Update api
`plugin`::  Any plugin that makes use of scripts under the generic `plugin` category

Plugins can also define custom operations that they use scripts for instead
of using the generic `plugin` category. Those operations can be referred to
in the following form: `${pluginName}_${operation}`.

The following example disables scripting for `update` and `plugin` operations,
regardless of the script source or language. Scripts can still be executed
as part of `aggregations`, `search` and plugins execution though, as the above
defaults still get applied.

[source,yaml]
-----------------------------------
script.update: false
script.plugin: false
-----------------------------------

[[security-script-fine]]
[float]
=== Fine-grained script settings

First, the high-level script settings described above are applied in order
(context settings have precedence over source settings). Then fine-grained
settings which include the script language take precedence over any high-level
settings. They have two forms:

[source,yaml]
------------------------
script.engine.{lang}.{inline|file|stored}.{context}: true|false
------------------------

And

[source,yaml]
------------------------
script.engine.{lang}.{inline|file|stored}: true|false
------------------------

For example:

[source,yaml]
-----------------------------------
script.inline: false <1>
script.stored: false <1>
script.file:   false <1>

script.engine.painless.inline:          true <2>
script.engine.painless.stored.search:   true <3>
script.engine.painless.stored.aggs:     true <3>

script.engine.mustache.stored.search:   true <4>
-----------------------------------
<1> Disable all scripting from any source.
<2> Allow inline Painless scripts for all operations.
<3> Allow stored Painless scripts to be used for search and aggregations.
<4> Allow stored Mustache templates to be used for search.
