Skip to content

Commit

Permalink
Auto configure TLS for new nodes of new clusters (#77231)
Browse files Browse the repository at this point in the history
This commit introduces TLS auto-configuration for elasticsearch nodes, during
the first startup. A number of heuristics are performed in order to determine if
the node should get TLS auto-configuration which can also be explicitly
disallowed with the use of xpack.security.autoconfiguration.enabled setting.

This affects archive installations and docker. Packaged installations are
handled in #75144 and #75704 .

Co-authored-by: Ioannis Kakavas <[email protected]>
  • Loading branch information
albertzaharovits and jkakavas authored Oct 14, 2021
1 parent 62d2df4 commit b257da1
Show file tree
Hide file tree
Showing 31 changed files with 1,394 additions and 592 deletions.
23 changes: 23 additions & 0 deletions distribution/src/bin/elasticsearch
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
source "`dirname "$0"`"/elasticsearch-env

CHECK_KEYSTORE=true
ATTEMPT_SECURITY_AUTO_CONFIG=true
DAEMONIZE=false
for option in "$@"; do
case "$option" in
-h|--help|-V|--version)
CHECK_KEYSTORE=false
ATTEMPT_SECURITY_AUTO_CONFIG=false
;;
-d|--daemonize)
DAEMONIZE=true
Expand All @@ -45,6 +47,27 @@ then
fi
fi

if [[ $ATTEMPT_SECURITY_AUTO_CONFIG = true ]]; then
# It is possible that an auto-conf failure prevents the node from starting, but this is only the exceptional case (exit code 1).
# Most likely an auto-conf failure will leave the configuration untouched (exit codes 73, 78 and 80), optionally printing a message
# if the error is uncommon or unexpected, but it should otherwise let the node to start as usual.
# It is passed in all the command line options in order to read the node settings ones (-E), while the other parameters are ignored
# (a small caveat is that it also inspects the -v option in order to provide more information on how auto config went)
if ES_MAIN_CLASS=org.elasticsearch.xpack.security.cli.ConfigInitialNode \
ES_ADDITIONAL_SOURCES="x-pack-env;x-pack-security-env" \
ES_ADDITIONAL_CLASSPATH_DIRECTORIES=lib/tools/security-cli \
"`dirname "$0"`"/elasticsearch-cli "$@" <<<"$KEYSTORE_PASSWORD"; then
:
else
retval=$?
# these exit codes cover the cases where auto-conf cannot run but the node should NOT be prevented from starting as usual
# eg the node is restarted, is already configured in an incompatible way, or the file system permissions do not allow it
if [[ $retval -ne 80 ]] && [[ $retval -ne 73 ]] && [[ $retval -ne 78 ]]; then
exit $retval
fi
fi
fi

# The JVM options parser produces the final JVM options to start Elasticsearch.
# It does this by incorporating JVM options in the following way:
# - first, system JVM options are applied (these are hardcoded options in the
Expand Down
13 changes: 13 additions & 0 deletions distribution/src/bin/elasticsearch-env
Original file line number Diff line number Diff line change
Expand Up @@ -119,22 +119,35 @@ if [[ "$ES_DISTRIBUTION_TYPE" == "docker" ]]; then

declare -a es_arg_array

containsElement () {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}

# Elasticsearch settings need to either:
# a. have at least two dot separated lower case words, e.g. `cluster.name`, or
while IFS='=' read -r envvar_key envvar_value; do
es_opt=""
if [[ -n "$envvar_value" ]]; then
es_opt="-E${envvar_key}=${envvar_value}"
fi
if [[ ! -z "${es_opt}" ]] && ! containsElement "${es_opt}" "$@" ; then
es_arg_array+=("${es_opt}")
fi
done <<< "$(env | grep -E '^[-a-z0-9_]+(\.[-a-z0-9_]+)+=')"

# b. be upper cased with underscore separators and prefixed with `ES_SETTING_`, e.g. `ES_SETTING_CLUSTER_NAME`.
# Underscores in setting names are escaped by writing them as a double-underscore e.g. "__"
while IFS='=' read -r envvar_key envvar_value; do
es_opt=""
if [[ -n "$envvar_value" ]]; then
# The long-hand sed `y` command works in any sed variant.
envvar_key="$(echo "$envvar_key" | sed -e 's/^ES_SETTING_//; s/_/./g ; s/\.\./_/g; y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' )"
es_opt="-E${envvar_key}=${envvar_value}"
fi
if [[ ! -z "${es_opt}" ]] && ! containsElement "${es_opt}" "$@" ; then
es_arg_array+=("${es_opt}")
fi
done <<< "$(env | grep -E '^ES_SETTING(_{1,2}[A-Z]+)+=')"
Expand Down
22 changes: 22 additions & 0 deletions distribution/src/bin/elasticsearch.bat
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ setlocal enableextensions

SET params='%*'
SET checkpassword=Y
SET attemptautoconfig=Y

:loop
FOR /F "usebackq tokens=1* delims= " %%A IN (!params!) DO (
Expand All @@ -21,16 +22,20 @@ FOR /F "usebackq tokens=1* delims= " %%A IN (!params!) DO (

IF "!current!" == "-h" (
SET checkpassword=N
SET attemptautoconfig=N
)
IF "!current!" == "--help" (
SET checkpassword=N
SET attemptautoconfig=N
)

IF "!current!" == "-V" (
SET checkpassword=N
SET attemptautoconfig=N
)
IF "!current!" == "--version" (
SET checkpassword=N
SET attemptautoconfig=N
)

IF "!silent!" == "Y" (
Expand Down Expand Up @@ -68,6 +73,23 @@ IF "%checkpassword%"=="Y" (
)
)

IF "%attemptautoconfig%"=="Y" (
ECHO.!KEYSTORE_PASSWORD!| %JAVA% %ES_JAVA_OPTS% ^
-Des.path.home="%ES_HOME%" ^
-Des.path.conf="%ES_PATH_CONF%" ^
-Des.distribution.flavor="%ES_DISTRIBUTION_FLAVOR%" ^
-Des.distribution.type="%ES_DISTRIBUTION_TYPE%" ^
-cp "!ES_CLASSPATH!;!ES_HOME!/lib/tools/security-cli/*;!ES_HOME!/modules/x-pack-core/*;!ES_HOME!/modules/x-pack-security/*" "org.elasticsearch.xpack.security.cli.ConfigInitialNode" !newparams!
SET SHOULDEXIT=Y
IF !ERRORLEVEL! EQU 0 SET SHOULDEXIT=N
IF !ERRORLEVEL! EQU 73 SET SHOULDEXIT=N
IF !ERRORLEVEL! EQU 78 SET SHOULDEXIT=N
IF !ERRORLEVEL! EQU 80 SET SHOULDEXIT=N
IF "!SHOULDEXIT!"=="Y" (
exit /b !ERRORLEVEL!
)
)

if not defined ES_TMPDIR (
for /f "tokens=* usebackq" %%a in (`CALL %JAVA% -cp "!ES_CLASSPATH!" "org.elasticsearch.tools.launchers.TempDirectory"`) do set ES_TMPDIR=%%a
)
Expand Down
7 changes: 7 additions & 0 deletions docs/changelog/77231.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pr: 77231
summary: Auto configure TLS for new nodes of new clusters
area: Security
type: feature
issues:
- 75144
- 75704
4 changes: 3 additions & 1 deletion libs/cli/src/main/java/org/elasticsearch/cli/ExitCodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
* POSIX exit codes.
*/
public class ExitCodes {
// please be extra careful when changing these as the values might be used in scripts,
// usages of which are not tracked by the IDE
public static final int OK = 0;
public static final int NOOP = 63; // nothing to do
public static final int USAGE = 64; // command line usage error
public static final int DATA_ERROR = 65; // data format error
public static final int NO_INPUT = 66; // cannot open input
Expand All @@ -27,6 +28,7 @@ public class ExitCodes {
public static final int PROTOCOL = 76; // remote error in protocol
public static final int NOPERM = 77; // permission denied
public static final int CONFIG = 78; // configuration error
public static final int NOOP = 80; // nothing to do

private ExitCodes() { /* no instance, just constants */ }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

package org.elasticsearch.packaging.test;

import org.apache.http.client.fluent.Request;
import org.elasticsearch.packaging.util.Distribution;
import org.elasticsearch.packaging.util.FileUtils;
import org.elasticsearch.packaging.util.ServerUtils;
Expand Down Expand Up @@ -45,15 +44,10 @@ public static void filterDistros() {
}

public void test10Install() throws Exception {
// security config tool would run as administrator and change the owner of the config file, which is elasticsearch
// We can re-enable this when #77231 is merged, but the rest of the tests in class are also currently muted on windows
assumeTrue("Don't run on windows", distribution.platform != Distribution.Platform.WINDOWS);
installation = installArchive(sh, distribution());
// Enable security for these tests only where it is necessary, until we can enable it for all
// TODO: Remove this when https://github.com/elastic/elasticsearch/pull/77231 is merged
ServerUtils.enableSecurityFeatures(installation);
verifyArchiveInstallation(installation, distribution());
installation.executables().securityConfigTool.run("");
}

public void test20NoAutoGenerationWhenAutoConfigurationDisabled() throws Exception {
Expand Down Expand Up @@ -88,12 +82,7 @@ public void test40VerifyAutogeneratedCredentials() throws Exception {
assertThat(parseElasticPassword(result.stdout), notNullValue());
assertThat(parseKibanaToken(result.stdout), notNullValue());
assertThat(parseFingerprint(result.stdout), notNullValue());
String response = ServerUtils.makeRequest(
Request.Get("https://localhost:9200"),
"elastic",
parseElasticPassword(result.stdout),
ServerUtils.getCaCert(installation.config)
);
String response = makeRequestAsElastic("https://localhost:9200", parseElasticPassword(result.stdout));
assertThat(response, containsString("You Know, for Search"));
}

Expand Down
Loading

0 comments on commit b257da1

Please sign in to comment.