Merge remote-tracking branch 'elastic/master' into feature/sql_2

Original commit: elastic/x-pack-elasticsearch@7029b1f881
This commit is contained in:
Igor Motov 2018-01-03 15:16:21 -05:00
commit db1693ea20
9 changed files with 370 additions and 70 deletions

View File

@ -81,16 +81,6 @@ case $key in
"-Dtests.jvm.argline=-Dbuild.snapshot=false"
)
;;
jdk9)
GRADLE_CLI_ARGS=(
"-Pxpack.kibana.build=false"
"--info"
"check"
"-Dtests.network=true"
"-Dtests.badapples=true"
-Dtests.jvm.argline="--add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.nio.file=ALL-UNNAMED --add-opens=java.base/java.security.cert=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/javax.net.ssl=ALL-UNNAMED"
)
;;
*)
echo "Unsupported cli argument $1. Allowed arguments are packagingTest or check. No argument defaults to check."
exit 1;;

View File

@ -2,6 +2,8 @@
[[certgen]]
== certgen
deprecated[6.1,Replaced by <<certutil,`certutil`>>. ]
The `certgen` command simplifies the creation of certificate authorities (CA),
certificate signing requests (CSR), and signed certificates for use with the
Elastic Stack.
@ -56,7 +58,7 @@ signed certificates must be in PEM format to work with {security}.
using an existing CA certificate, which is provided in the `<cert_file>` argument.
This parameter cannot be used with the `-csr` parameter.
`--csr`:: Specifies to operation in certificate signing request mode.
`--csr`:: Specifies to operate in certificate signing request mode.
`--days <n>`::
Specifies an integer value that represents the number of days the generated keys

View File

@ -0,0 +1,279 @@
[role="xpack"]
[[certutil]]
== certutil
The `certutil` command simplifies the creation of certificates for use with
Transport Layer Security (TLS) in the Elastic Stack.
[float]
=== Synopsis
[source,shell]
--------------------------------------------------
bin/x-pack/certutil
(
(ca [--ca-dn <name>] [--days <n>] [--pem])
| (cert ([--ca <file_path>] | [--ca-cert <file_path> --ca-key <file_path>])
[--ca-dn <name>] [--ca-pass <password>] [--days <n>]
[--dns <domain_name>] [--in <input_file>] [--ip <ip_addresses>]
[--keep-ca-key] [--multiple] [--name <file_name>] [--pem])
| (csr [--dns <domain_name>] [--in <input_file>] [--ip <ip_addresses>]
[--name <file_name>])
[-E <KeyValuePair>] [--keysize <bits>] [--out <file_path>]
[--pass <password>]
)
[-h, --help] ([-s, --silent] | [-v, --verbose])
--------------------------------------------------
[float]
=== Description
You can specify one of the following modes: `ca`, `cert`, `csr`. The `certutil`
command also supports a silent mode of operation to enable easier batch
operations.
[float]
[[certutil-ca]]
==== CA mode
The `ca` mode generates a new certificate authority (CA). By default, it
produces a single PKCS#12 output file, which holds the CA certificate and the
private key for the CA. If you specify the `--pem` parameter, the command
generates a zip file, which contains the certificate and private key in PEM
format.
You can subsequently use these files as input for the `cert` mode of the command.
[float]
[[certutil-cert]]
==== CERT mode
The `cert` mode generates X.509 certificates and private keys. By default, it
produces a single certificate and key for use on a single instance.
To generate certificates and keys for multiple instances, specify the
`--multiple` parameter, which prompts you for details about each instance.
Alternatively, you can use the `--in` parameter to specify a YAML file that
contains details about the instances.
An instance is any piece of the Elastic Stack that requires a TLS or SSL
certificate. Depending on your configuration, {es}, Logstash, {kib}, and Beats
might all require a certificate and private key. The minimum required
information for an instance is its name, which is used as the common name for
the certificate. The instance name can be a hostname value or a full
distinguished name. If the instance name would result in an invalid file or
directory name, you must also specify a file name in the `--name` command
parameter or in the `filename` field in an input YAML file.
You can optionally provide IP addresses or DNS names for each instance. If
neither IP addresses nor DNS names are specified, the Elastic stack products
cannot perform hostname verification and you might need to configure the
`verfication_mode` security setting to `certificate` only. For more information
about this setting, see <<security-settings>>.
All certificates that are generated by this command are signed by a CA. You can
provide your own CA with the `--ca` or `--ca-cert` parameters. Otherwise, the
command automatically generates a new CA for you. For more information about
generating a CA, see the <<certutil-ca,CA mode of this command>>.
By default, the `cert` mode produces a single PKCS#12 output file which holds
the instance certificate, the instance private key, and the CA certificate. If
you specify the `--pem` parameter, the command generates PEM formatted
certificates and keys and packages them into a zip file. Likewise if you chose
to generate output for multiple instances, the command produces a zip file.
[float]
[[certutil-csr]]
==== CSR mode
The `csr` mode generates certificate signing requests (CSRs) that you can send
to a trusted certificate authority to obtain signed certificates. The signed
certificates must be in PEM or PKCS#12 format to work with {security}.
By default, the command produces a single CSR for a single instance.
To generate CSRs for multiple instances, specify the `--multiple` parameter,
which prompts you for details about each instance. Alternatively, you can use
the `--in` parameter to specify a YAML file that contains details about the
instances.
The `cert` mode produces a single zip file which contains the CSRs and the
private keys for each instance. Each CSR is provided as a standard PEM
encoding of a PKCS#10 CSR. Each key is provided as a PEM encoding of an RSA
private key.
[float]
=== Parameters
`ca`:: Specifies to generate a new local certificate authority (CA). This
parameter cannot be used with the `csr` or `cert` parameters.
`cert`:: Specifies to generate new X.509 certificates and keys.
This parameter cannot be used with the `csr` or `ca` parameters.
`csr`:: Specifies to generate certificate signing requests. This parameter
cannot be used with the `ca` or `cert` parameters.
`--ca <file_path>`:: Specifies the path to an existing CA key pair
(in PKCS#12 format). This parameter cannot be used with the `ca` or `csr` parameters.
`--ca-cert <file_path>`:: Specifies the path to an existing CA certificate (in
PEM format). You must also specify the `--ca-key` parameter. The `--ca-cert`
parameter cannot be used with the `ca` or `csr` parameters.
`--ca-dn <name>`:: Defines the _Distinguished Name_ (DN) that is used for the
generated CA certificate. The default value is
`CN=Elastic Certificate Tool Autogenerated CA`. This parameter cannot be used
with the `csr` parameter.
`--ca-key <file_path>`:: Specifies the path to an existing CA private key (in
PEM format). You must also specify the `--ca-cert` parameter. The `--ca-key`
parameter cannot be used with the `ca` or `csr` parameters.
`--ca-pass <password>`:: Specifies the password for an existing CA private key
or the generated CA private key. This parameter cannot be used with the `ca` or
`csr` parameters.
`--days <n>`:: Specifies an integer value that represents the number of days the
generated certificates are valid. The default value is `1095`. This parameter
cannot be used with the `csr` parameter.
`--dns <domain_name>`:: Specifies a comma-separated list of DNS names. This
parameter cannot be used with the `ca` parameter.
`-E <KeyValuePair>`:: Configures a setting.
`-h, --help`:: Returns all of the command parameters.
`--in <input_file>`:: Specifies the file that is used to run in silent mode. The
input file must be a YAML file. This parameter cannot be used with the `ca`
parameter.
`--ip <IP_addresses>`:: Specifies a comma-separated list of IP addresses. This
parameter cannot be used with the `ca` parameter.
`--keep-ca-key`:: When running in `cert` mode with an automatically-generated
CA, specifies to retain the CA private key for future use.
`--keysize <bits>`::
Defines the number of bits that are used in generated RSA keys. The default
value is `2048`.
`--multiple`::
Specifies to generate files for multiple instances. This parameter cannot be
used with the `ca` parameter.
`--name <file_name>`::
Specifies the name of the generated certificate. This parameter cannot be used
with the `ca` parameter.
`--out <file_path>`:: Specifies a path for the output files.
`--pass <password>`:: Specifies the password for the generated private keys.
`--pem`:: Generates certificates and keys in PEM format instead of PKCS#12. This
parameter cannot be used with the `csr` parameter.
`-s, --silent`:: Shows minimal output.
`-v, --verbose`:: Shows verbose output.
[float]
=== Examples
The following command generates a CA certificate and private key in PKCS#12
format:
[source, sh]
--------------------------------------------------
bin/x-pack/certutil ca
--------------------------------------------------
You are prompted for an output filename and a password. Alternatively, you can
specify the `--out` and `--pass` parameters.
You can then generate X.509 certificates and private keys by using the new
CA. For example:
[source, sh]
--------------------------------------------------
bin/x-pack/certutil cert --ca elastic-stack-ca.p12
--------------------------------------------------
You are prompted for the CA password and for an output filename and password.
Alternatively, you can specify the `--ca-pass`, `--out`, and `--pass` parameters.
By default, this command generates a file called `elastic-certificates.p12`,
which you can copy to the relevant configuration directory for each Elastic
product that you want to configure. For more information, see
{xpack-ref}/ssl-tls.html[Setting Up TLS on a Cluster].
[float]
[[certutil-silent]]
==== Using `certutil` in Silent Mode
To use the silent mode of operation, you must create a YAML file that contains
information about the instances. It must match the following format:
[source, yaml]
--------------------------------------------------
instances:
- name: "node1" <1>
ip: <2>
- "192.0.2.1"
dns: <3>
- "node1.mydomain.com"
- name: "node2"
ip:
- "192.0.2.2"
- "198.51.100.1"
- name: "node3"
- name: "node4"
dns:
- "node4.mydomain.com"
- "node4.internal"
- name: "CN=node5,OU=IT,DC=mydomain,DC=com"
filename: "node5" <4>
--------------------------------------------------
<1> The name of the instance. This can be a simple string value or can be a
Distinguished Name (DN). This is the only required field.
<2> An optional array of strings that represent IP Addresses for this instance.
Both IPv4 and IPv6 values are allowed. The values are added as Subject
Alternative Names.
<3> An optional array of strings that represent DNS names for this instance.
The values are added as Subject Alternative Names.
<4> The filename to use for this instance. This name is used as the name of the
directory that contains the instance's files in the output. It is also used in
the names of the files within the directory. This filename should not have an
extension. Note: If the `name` provided for the instance does not represent a
valid filename, then the `filename` field must be present.
When your YAML file is ready, you can use the `certutil` command to generate
certificates or certificate signing requests. Simply use the `--in` parameter to
specify the location of the file. For example:
[source, sh]
--------------------------------------------------
bin/x-pack/certutil cert --silent --in instances.yml --out test1.zip --pass testpassword
--------------------------------------------------
This command generates a compressed `test1.zip` file. After you decompress the
output file, there is a directory for each instance that was listed in the
`instances.yml` file. Each instance directory contains a single PKCS#12 (`.p12`)
file, which contains the instance certificate, instance private key, and CA
certificate.
You an also use the YAML file to generate certificate signing requests. For
example:
[source, sh]
--------------------------------------------------
bin/x-pack/certutil csr --silent --in instances.yml --out test2.zip --pass testpassword
--------------------------------------------------
This command generates a compressed file, which contains a directory for each
instance. Each instance directory contains a certificate signing request
(`*.csr` file) and private key (`*.key` file).

View File

@ -8,6 +8,7 @@
{xpack} includes commands that help you configure security:
* <<certgen>>
* <<certutil>>
* <<migrate-tool>>
* <<setup-passwords>>
* <<syskeygen>>
@ -16,6 +17,7 @@
--
include::certgen.asciidoc[]
include::certutil.asciidoc[]
include::migrate-tool.asciidoc[]
include::setup-passwords.asciidoc[]
include::syskeygen.asciidoc[]

View File

@ -96,7 +96,7 @@ values occur.
This function supports the following properties:
* `by_field_name` (required)
* `over_field_name` (optional)
* `over_field_name` (required)
* `partition_field_name` (optional)
For more information about those properties, see

View File

@ -1,2 +1,2 @@
org.gradle.daemon=false
org.gradle.jvmargs=-Xmx1536m
org.gradle.jvmargs=-Xmx2048m

View File

@ -5,6 +5,12 @@
*/
package org.elasticsearch.xpack.security.authc.esnative;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.util.Supplier;
import org.elasticsearch.Version;
@ -32,12 +38,6 @@ import org.elasticsearch.xpack.security.user.KibanaUser;
import org.elasticsearch.xpack.security.user.LogstashSystemUser;
import org.elasticsearch.xpack.security.user.User;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* A realm for predefined users. These users can only be modified in terms of changing their passwords; no other modifications are allowed.
* This realm is <em>always</em> enabled.
@ -97,6 +97,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
}
} finally {
assert userInfo.passwordHash != DISABLED_DEFAULT_USER_INFO.passwordHash : "default user info must be cloned";
assert userInfo.passwordHash != ENABLED_DEFAULT_USER_INFO.passwordHash : "default user info must be cloned";
assert userInfo.passwordHash != bootstrapUserInfo.passwordHash : "bootstrap user info must be cloned";
Arrays.fill(userInfo.passwordHash, (char) 0);
}
@ -184,15 +185,11 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
logger.debug("Marking user [{}] as disabled because the security mapping is not at the required version", username);
listener.onResponse(DISABLED_DEFAULT_USER_INFO.deepClone());
} else if (securityLifecycleService.isSecurityIndexExisting() == false) {
listener.onResponse(bootstrapUserInfo.deepClone());
listener.onResponse(getDefaultUserInfo(username));
} else {
nativeUsersStore.getReservedUserInfo(username, ActionListener.wrap((userInfo) -> {
if (userInfo == null) {
if (ElasticUser.NAME.equals(username)) {
listener.onResponse(bootstrapUserInfo.deepClone());
} else {
listener.onResponse(ENABLED_DEFAULT_USER_INFO.deepClone());
}
listener.onResponse(getDefaultUserInfo(username));
} else {
listener.onResponse(userInfo);
}
@ -204,6 +201,14 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
}
}
private ReservedUserInfo getDefaultUserInfo(String username) {
if (ElasticUser.NAME.equals(username)) {
return bootstrapUserInfo.deepClone();
} else {
return ENABLED_DEFAULT_USER_INFO.deepClone();
}
}
private boolean userIsDefinedForCurrentSecurityMapping(String username) {
final Version requiredVersion = getDefinedVersion(username);
return securityLifecycleService.checkSecurityMappingVersion(requiredVersion::onOrBefore);

View File

@ -5,6 +5,13 @@
*/
package org.elasticsearch.xpack.security.authc.esnative;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener;
@ -26,16 +33,10 @@ import org.elasticsearch.xpack.security.user.ElasticUser;
import org.elasticsearch.xpack.security.user.KibanaUser;
import org.elasticsearch.xpack.security.user.LogstashSystemUser;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.UsernamesField;
import org.junit.Before;
import org.mockito.ArgumentCaptor;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
@ -58,7 +59,6 @@ import static org.mockito.Mockito.when;
public class ReservedRealmTests extends ESTestCase {
private static final SecureString EMPTY_PASSWORD = new SecureString("".toCharArray());
public static final String ACCEPT_DEFAULT_PASSWORDS = ReservedRealm.ACCEPT_DEFAULT_PASSWORD_SETTING.getKey();
private NativeUsersStore usersStore;
private SecurityLifecycleService securityLifecycleService;
@ -71,33 +71,16 @@ public class ReservedRealmTests extends ESTestCase {
mockGetAllReservedUserInfo(usersStore, Collections.emptyMap());
}
public void testDisableDefaultPasswordAuthentication() throws Throwable {
final User expected = randomFrom(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true));
public void testReservedUserEmptyPasswordAuthenticationFails() throws Throwable {
final String principal = randomFrom(UsernamesField.ELASTIC_NAME, UsernamesField.KIBANA_NAME, UsernamesField.LOGSTASH_NAME);
final Environment environment = mock(Environment.class);
final AnonymousUser anonymousUser = new AnonymousUser(Settings.EMPTY);
final Settings settings = Settings.builder().put(ACCEPT_DEFAULT_PASSWORDS, false).build();
final ReservedRealm reservedRealm = new ReservedRealm(environment, settings, usersStore, anonymousUser,
securityLifecycleService, new ThreadContext(Settings.EMPTY));
PlainActionFuture<AuthenticationResult> listener = new PlainActionFuture<>();
reservedRealm.doAuthenticate(new UsernamePasswordToken(expected.principal(), EMPTY_PASSWORD), listener);
assertFailedAuthentication(listener, expected.principal());
}
public void testElasticEmptyPasswordAuthenticationFails() throws Throwable {
final User expected = new ElasticUser(true);
final String principal = expected.principal();
Settings settings = Settings.builder().put(ACCEPT_DEFAULT_PASSWORDS, true).build();
final ReservedRealm reservedRealm =
new ReservedRealm(mock(Environment.class), settings, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
PlainActionFuture<AuthenticationResult> listener = new PlainActionFuture<>();
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener);
assertFailedAuthentication(listener, expected.principal());
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener);
assertFailedAuthentication(listener, principal);
}
public void testAuthenticationDisabled() throws Throwable {
@ -107,8 +90,8 @@ public class ReservedRealmTests extends ESTestCase {
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
}
final ReservedRealm reservedRealm =
new ReservedRealm(mock(Environment.class), settings, usersStore,
new AnonymousUser(settings), securityLifecycleService, new ThreadContext(Settings.EMPTY));
new ReservedRealm(mock(Environment.class), settings, usersStore,
new AnonymousUser(settings), securityLifecycleService, new ThreadContext(Settings.EMPTY));
final User expected = randomFrom(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true));
final String principal = expected.principal();
@ -129,9 +112,8 @@ public class ReservedRealmTests extends ESTestCase {
}
private void verifySuccessfulAuthentication(boolean enabled) throws Exception {
final Settings settings = Settings.builder().put(ACCEPT_DEFAULT_PASSWORDS, randomBoolean()).build();
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore,
new AnonymousUser(settings), securityLifecycleService, new ThreadContext(Settings.EMPTY));
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
final User expectedUser = randomFrom(new ElasticUser(enabled), new KibanaUser(enabled), new LogstashSystemUser(enabled));
final String principal = expectedUser.principal();
final SecureString newPassword = new SecureString("foobar".toCharArray());
@ -171,8 +153,8 @@ public class ReservedRealmTests extends ESTestCase {
public void testLookup() throws Exception {
final ReservedRealm reservedRealm =
new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
final User expectedUser = randomFrom(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true));
final String principal = expectedUser.principal();
@ -196,8 +178,8 @@ public class ReservedRealmTests extends ESTestCase {
public void testLookupDisabled() throws Exception {
Settings settings = Settings.builder().put(XPackSettings.RESERVED_REALM_ENABLED_SETTING.getKey(), false).build();
final ReservedRealm reservedRealm =
new ReservedRealm(mock(Environment.class), settings, usersStore, new AnonymousUser(settings),
securityLifecycleService, new ThreadContext(Settings.EMPTY));
new ReservedRealm(mock(Environment.class), settings, usersStore, new AnonymousUser(settings),
securityLifecycleService, new ThreadContext(Settings.EMPTY));
final User expectedUser = randomFrom(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true));
final String principal = expectedUser.principal();
@ -210,8 +192,8 @@ public class ReservedRealmTests extends ESTestCase {
public void testLookupThrows() throws Exception {
final ReservedRealm reservedRealm =
new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
final User expectedUser = randomFrom(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true));
final String principal = expectedUser.principal();
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
@ -258,7 +240,7 @@ public class ReservedRealmTests extends ESTestCase {
public void testGetUsers() {
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
PlainActionFuture<Collection<User>> userFuture = new PlainActionFuture<>();
reservedRealm.users(userFuture);
assertThat(userFuture.actionGet(), containsInAnyOrder(new ElasticUser(true), new KibanaUser(true),
@ -273,7 +255,7 @@ public class ReservedRealmTests extends ESTestCase {
.build();
final AnonymousUser anonymousUser = new AnonymousUser(settings);
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore, anonymousUser,
securityLifecycleService, new ThreadContext(Settings.EMPTY));
securityLifecycleService, new ThreadContext(Settings.EMPTY));
PlainActionFuture<Collection<User>> userFuture = new PlainActionFuture<>();
reservedRealm.users(userFuture);
if (anonymousEnabled) {
@ -290,7 +272,7 @@ public class ReservedRealmTests extends ESTestCase {
ReservedUserInfo userInfo = new ReservedUserInfo(hash, true, false);
mockGetAllReservedUserInfo(usersStore, Collections.singletonMap("elastic", userInfo));
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
if (randomBoolean()) {
PlainActionFuture<AuthenticationResult> future = new PlainActionFuture<>();
@ -379,6 +361,44 @@ public class ReservedRealmTests extends ESTestCase {
assertThat(result.getStatus(), is(AuthenticationResult.Status.SUCCESS));
}
public void testNonElasticUsersCannotUseBootstrapPasswordWhenSecurityIndexExists() throws Exception {
final MockSecureSettings mockSecureSettings = new MockSecureSettings();
final String password = randomAlphaOfLengthBetween(8, 24);
mockSecureSettings.setString("bootstrap.password", password);
Settings settings = Settings.builder().setSecureSettings(mockSecureSettings).build();
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
PlainActionFuture<AuthenticationResult> listener = new PlainActionFuture<>();
final String principal = randomFrom(KibanaUser.NAME, LogstashSystemUser.NAME);
doAnswer((i) -> {
ActionListener callback = (ActionListener) i.getArguments()[1];
callback.onResponse(null);
return null;
}).when(usersStore).getReservedUserInfo(eq(principal), any(ActionListener.class));
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, mockSecureSettings.getString("bootstrap.password")), listener);
final AuthenticationResult result = listener.get();
assertThat(result.getStatus(), is(AuthenticationResult.Status.TERMINATE));
}
public void testNonElasticUsersCannotUseBootstrapPasswordWhenSecurityIndexDoesNotExists() throws Exception {
final MockSecureSettings mockSecureSettings = new MockSecureSettings();
final String password = randomAlphaOfLengthBetween(8, 24);
mockSecureSettings.setString("bootstrap.password", password);
Settings settings = Settings.builder().setSecureSettings(mockSecureSettings).build();
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(false);
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore,
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
PlainActionFuture<AuthenticationResult> listener = new PlainActionFuture<>();
final String principal = randomFrom(KibanaUser.NAME, LogstashSystemUser.NAME);
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, mockSecureSettings.getString("bootstrap.password")), listener);
final AuthenticationResult result = listener.get();
assertThat(result.getStatus(), is(AuthenticationResult.Status.TERMINATE));
}
/*
* NativeUserStore#getAllReservedUserInfo is pkg private we can't mock it otherwise

View File

@ -9,6 +9,7 @@ import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.elasticsearch.client.Response;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.yaml.ObjectPath;
import org.elasticsearch.xpack.watcher.actions.ActionBuilders;
@ -25,6 +26,7 @@ import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput;
import static org.elasticsearch.xpack.watcher.trigger.schedule.IntervalSchedule.Interval.Unit.MINUTES;
import static org.hamcrest.Matchers.is;
@TestLogging("org.elasticsearch.client:TRACE")
public class MonitoringWithWatcherRestIT extends ESRestTestCase {
@After