Remove default passwords from reserved users (elastic/x-pack-elasticsearch#1665)
This is related to elastic/x-pack-elasticsearch#1217. This PR removes the default password of "changeme" from the reserved users. This PR adds special behavior for authenticating the reserved users. No ReservedRealm user can be authenticated until its password is set. The one exception to this is the elastic user. The elastic user can be authenticated with an empty password if the action is a rest request originating from localhost. In this scenario where an elastic user is authenticated with a default password, it will have metadata indicating that it is in setup mode. An elastic user in setup mode is only authorized to execute a change password request. Original commit: elastic/x-pack-elasticsearch@e1e101a237
This commit is contained in:
parent
075eda4fc1
commit
f2cbe20ea0
|
@ -113,7 +113,7 @@ Closure waitWithAuth = { NodeInfo node, AntBuilder ant ->
|
|||
try {
|
||||
httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_cluster/health").openConnection();
|
||||
httpURLConnection.setRequestProperty("Authorization", "Basic " +
|
||||
Base64.getEncoder().encodeToString("test_admin:changeme".getBytes(StandardCharsets.UTF_8)));
|
||||
Base64.getEncoder().encodeToString("test_admin:x-pack-test-password".getBytes(StandardCharsets.UTF_8)));
|
||||
httpURLConnection.setRequestMethod("GET");
|
||||
httpURLConnection.setConnectTimeout(1000);
|
||||
httpURLConnection.setReadTimeout(30000);
|
||||
|
@ -145,7 +145,7 @@ Closure waitWithAuth = { NodeInfo node, AntBuilder ant ->
|
|||
integTestCluster {
|
||||
plugin ':x-pack-elasticsearch:plugin'
|
||||
setupCommand 'setupTestAdmin',
|
||||
'bin/x-pack/users', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'superuser'
|
||||
'bin/x-pack/users', 'useradd', 'test_admin', '-p', 'x-pack-test-password', '-r', 'superuser'
|
||||
waitCondition = waitWithAuth
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@ make it easier to control which users have authority to view and manage the jobs
|
|||
{dfeeds}, and results.
|
||||
|
||||
By default, you can perform all of the steps in this tutorial by using the
|
||||
built-in `elastic` super user. The default password for the `elastic` user is
|
||||
`changeme`. For information about how to change that password, see
|
||||
built-in `elastic` super user. However, the password must be set before the user
|
||||
can do anything. For information about how to set that password, see
|
||||
<<security-getting-started>>.
|
||||
|
||||
If you are performing these steps in a production environment, take extra care
|
||||
|
@ -191,7 +191,7 @@ mapping for the data set:
|
|||
[source,shell]
|
||||
----------------------------------
|
||||
|
||||
curl -u elastic:changeme -X PUT -H 'Content-Type: application/json'
|
||||
curl -u elastic:x-pack-test-password -X PUT -H 'Content-Type: application/json'
|
||||
http://localhost:9200/server-metrics -d '{
|
||||
"settings":{
|
||||
"number_of_shards":1,
|
||||
|
@ -227,7 +227,7 @@ http://localhost:9200/server-metrics -d '{
|
|||
}'
|
||||
----------------------------------
|
||||
|
||||
NOTE: If you run this command, you must replace `changeme` with your
|
||||
NOTE: If you run this command, you must replace `x-pack-test-password` with your
|
||||
actual password.
|
||||
|
||||
////
|
||||
|
@ -247,16 +247,16 @@ example, which loads the four JSON files:
|
|||
[source,shell]
|
||||
----------------------------------
|
||||
|
||||
curl -u elastic:changeme -X POST -H "Content-Type: application/json"
|
||||
curl -u elastic:x-pack-test-password -X POST -H "Content-Type: application/json"
|
||||
http://localhost:9200/server-metrics/_bulk --data-binary "@server-metrics_1.json"
|
||||
|
||||
curl -u elastic:changeme -X POST -H "Content-Type: application/json"
|
||||
curl -u elastic:x-pack-test-password -X POST -H "Content-Type: application/json"
|
||||
http://localhost:9200/server-metrics/_bulk --data-binary "@server-metrics_2.json"
|
||||
|
||||
curl -u elastic:changeme -X POST -H "Content-Type: application/json"
|
||||
curl -u elastic:x-pack-test-password -X POST -H "Content-Type: application/json"
|
||||
http://localhost:9200/server-metrics/_bulk --data-binary "@server-metrics_3.json"
|
||||
|
||||
curl -u elastic:changeme -X POST -H "Content-Type: application/json"
|
||||
curl -u elastic:x-pack-test-password -X POST -H "Content-Type: application/json"
|
||||
http://localhost:9200/server-metrics/_bulk --data-binary "@server-metrics_4.json"
|
||||
----------------------------------
|
||||
|
||||
|
@ -271,7 +271,7 @@ You can verify that the data was loaded successfully with the following command:
|
|||
[source,shell]
|
||||
----------------------------------
|
||||
|
||||
curl 'http://localhost:9200/_cat/indices?v' -u elastic:changeme
|
||||
curl 'http://localhost:9200/_cat/indices?v' -u elastic:x-pack-test-password
|
||||
----------------------------------
|
||||
|
||||
You should see output similar to the following:
|
||||
|
|
|
@ -13,7 +13,7 @@ To change the password of the logged in user, submit a POST request to the
|
|||
--------------------------------------------------
|
||||
POST _xpack/security/user/elastic/_password
|
||||
{
|
||||
"password": "changeme"
|
||||
"password": "x-pack-test-password"
|
||||
}
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
|
|
|
@ -16,8 +16,8 @@ endpoint.
|
|||
POST /_xpack/security/oauth2/token
|
||||
{
|
||||
"grant_type" : "password",
|
||||
"username" : "elastic",
|
||||
"password" : "changeme"
|
||||
"username" : "test_admin",
|
||||
"password" : "x-pack-test-password"
|
||||
}
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
|
|
|
@ -15,9 +15,11 @@ see <<managing-native-users, Managing Native Users>>.
|
|||
=== Built-in Users
|
||||
|
||||
{security} provides built-in user credentials to help you get up and running.
|
||||
These users have a fixed set of privileges and the default password `changeme`.
|
||||
Please read <<reset-built-in-user-passwords,Reset Built-in User Passwords>> and
|
||||
<<disabling-default-password, Disable Default Password Functionality>> below.
|
||||
These users have a fixed set of privileges and cannot be authenticated until their
|
||||
passwords have been set. The exception is the `elastic` user which can be authenticated
|
||||
from a localhost rest request with an empty password. Until a password is set, the elastic
|
||||
user is only authorized to perform change password requests.
|
||||
Please read <<reset-built-in-user-passwords,Reset Built-in User Passwords>> below.
|
||||
|
||||
.{security} Built-in Users
|
||||
|========
|
||||
|
@ -48,8 +50,7 @@ be disabled individually, using the
|
|||
==== Reset Built-in User Passwords
|
||||
[IMPORTANT]
|
||||
=============================================================================
|
||||
You must reset the default passwords for all built-in users, and then
|
||||
<<disabling-default-password, disable default password support>>.
|
||||
You must set the passwords for all built-in users.
|
||||
You can update passwords from the *Management > Users* UI in Kibana or with the
|
||||
{ref}/security-api-users.html#security-api-reset-user-password[Reset Password API]:
|
||||
|
||||
|
@ -112,22 +113,6 @@ PUT _xpack/security/user/logstash_system/_enable
|
|||
// CONSOLE
|
||||
=============================================================================
|
||||
|
||||
[float]
|
||||
[[disabling-default-password]]
|
||||
==== Disable Default Password Functionality
|
||||
[IMPORTANT]
|
||||
=============================================================================
|
||||
The default password of `changeme` is provided as a convenience that allows you to quickly
|
||||
setup your Elasticsearch stack. It should not be used when running in production.
|
||||
|
||||
Once you have changed the password for the built-in users, you must disable default password support
|
||||
by setting `xpack.security.authc.accept_default_password` to `false`.
|
||||
|
||||
A {ref}/bootstrap-checks.html[bootstrap check] will prevent your cluster from operating in production
|
||||
mode until you make this configuration change.
|
||||
|
||||
=============================================================================
|
||||
|
||||
[float]
|
||||
[[internal-users]]
|
||||
=== Internal Users
|
||||
|
|
|
@ -61,7 +61,7 @@ xpack:
|
|||
order: 0
|
||||
url: "ldaps://ldap.example.com:636"
|
||||
bind_dn: "cn=ldapuser, ou=users, o=services, dc=example, dc=com"
|
||||
bind_password: changeme
|
||||
bind_password: x-pack-test-password
|
||||
user_search:
|
||||
base_dn: "dc=example,dc=com"
|
||||
attribute: cn
|
||||
|
|
|
@ -21,7 +21,7 @@ Run the migrate tool after you install the X-Pack plugin. For example:
|
|||
|
||||
[source, sh]
|
||||
----------------------------------------------------------------------
|
||||
$ bin/x-pack/migrate native -U http://localhost:9200 -u elastic -p changeme
|
||||
$ bin/x-pack/migrate native -U http://localhost:9200 -u elastic -p x-pack-test-password
|
||||
-n lee,foo -r role1,role2,role3,role4,foo
|
||||
starting migration of users and roles...
|
||||
importing users from [/home/es/config/shield/users]...
|
||||
|
@ -69,5 +69,5 @@ to specify a different configuration directory, the command would look like:
|
|||
|
||||
[source, sh]
|
||||
----------------------------------------------------------------------
|
||||
$ bin/x-pack/migrate native -U http://localhost:9200 -u elastic -p changeme --path.conf /etc/elasticsearch
|
||||
$ bin/x-pack/migrate native -U http://localhost:9200 -u elastic -p x-pack-test-password --path.conf /etc/elasticsearch
|
||||
----------------------------------------------------------------------
|
||||
|
|
|
@ -80,7 +80,7 @@ xpack:
|
|||
type: pki
|
||||
truststore:
|
||||
path: "/path/to/pki_truststore.jks"
|
||||
password: "changeme"
|
||||
password: "x-pack-test-password"
|
||||
------------------------------------------------------------
|
||||
|
||||
. Restart Elasticsearch.
|
||||
|
|
|
@ -36,7 +36,8 @@ curl -XPUT -u elastic 'localhost:9200/_xpack/security/user/logstash_system/_pass
|
|||
----------------------------------------------------------
|
||||
// NOTCONSOLE
|
||||
|
||||
NOTE: The default password for the `elastic` user is `changeme`.
|
||||
NOTE: By default, the `elastic` user does not have a password set. Until its password is set, the `elastic` user will only be
|
||||
allowed to submit change password rest requests from localhost.
|
||||
|
||||
--
|
||||
|
||||
|
|
|
@ -58,11 +58,11 @@ for the client traffic by adding the following to `elasticsearch.yml`:
|
|||
--------------------------------------------------
|
||||
transport.profiles.client.xpack.security.ssl.truststore:
|
||||
path: /path/to/another/truststore
|
||||
password: changeme
|
||||
password: x-pack-test-password
|
||||
|
||||
transport.profiles.client.xpack.security.ssl.keystore:
|
||||
path: /path/to/another/keystore
|
||||
password: changeme
|
||||
password: x-pack-test-password
|
||||
--------------------------------------------------
|
||||
|
||||
To change the default behavior that requires certificates for transport clients,
|
||||
|
|
|
@ -57,7 +57,7 @@ users from the **Management / Users** UI in Kibana or through the
|
|||
---------------------------------------------------------------
|
||||
POST /_xpack/security/user/packetbeat_internal
|
||||
{
|
||||
"password" : "changeme",
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "packetbeat_writer"],
|
||||
"full_name" : "Internal Packetbeat User"
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ output.elasticsearch:
|
|||
hosts: ["localhost:9200"]
|
||||
index: "packetbeat"
|
||||
username: "packetbeat_internal"
|
||||
password: "changeme"
|
||||
password: "x-pack-test-password"
|
||||
--------------------------------------------------
|
||||
|
||||
.. To use PKI authentication, configure the `certificate` and
|
||||
|
@ -144,7 +144,7 @@ the `packetbeat_reader` role:
|
|||
---------------------------------------------------------------
|
||||
POST /_xpack/security/user/packetbeat_user
|
||||
{
|
||||
"password" : "changeme",
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "packetbeat_reader"],
|
||||
"full_name" : "Packetbeat User"
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
|
|||
|
||||
TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
|
||||
.put("cluster.name", "myClusterName")
|
||||
.put("xpack.security.user", "transport_client_user:changeme")
|
||||
.put("xpack.security.user", "transport_client_user:x-pack-test-password")
|
||||
...
|
||||
.build())
|
||||
.addTransportAddress(new InetSocketTransportAddress("localhost", 9300))
|
||||
|
@ -169,14 +169,14 @@ import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordTok
|
|||
|
||||
TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
|
||||
.put("cluster.name", "myClusterName")
|
||||
.put("xpack.security.user", "transport_client_user:changeme")
|
||||
.put("xpack.security.user", "transport_client_user:x-pack-test-password")
|
||||
...
|
||||
.build())
|
||||
.build()
|
||||
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300))
|
||||
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9301))
|
||||
|
||||
String token = basicAuthHeaderValue("test_user", new SecureString("changeme".toCharArray()));
|
||||
String token = basicAuthHeaderValue("test_user", new SecureString("x-pack-test-password".toCharArray()));
|
||||
|
||||
client.filterWithHeader(Collections.singletonMap("Authorization", token))
|
||||
.prepareSearch().get();
|
||||
|
@ -198,7 +198,7 @@ import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
|
|||
|
||||
TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
|
||||
.put("cluster.name", "myClusterName")
|
||||
.put("xpack.security.user", "transport_client_user:changeme")
|
||||
.put("xpack.security.user", "transport_client_user:x-pack-test-password")
|
||||
.put("xpack.ssl.key", "/path/to/client.key")
|
||||
.put("xpack.ssl.certificate", "/path/to/client.crt")
|
||||
.put("xpack.ssl.certificate_authorities", "/path/to/ca.crt")
|
||||
|
@ -217,7 +217,7 @@ import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
|
|||
|
||||
TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
|
||||
.put("cluster.name", "myClusterName")
|
||||
.put("xpack.security.user", "transport_client_user:changeme")
|
||||
.put("xpack.security.user", "transport_client_user:x-pack-test-password")
|
||||
.put("xpack.ssl.key", "/path/to/client.key")
|
||||
.put("xpack.ssl.certificate", "/path/to/client.crt")
|
||||
.put("xpack.ssl.certificate_authorities", "/path/to/ca.crt")
|
||||
|
@ -246,7 +246,7 @@ import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
|
|||
|
||||
TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
|
||||
.put("cluster.name", "myClusterName")
|
||||
.put("xpack.security.user", "test_user:changeme")
|
||||
.put("xpack.security.user", "test_user:x-pack-test-password")
|
||||
.put("xpack.ssl.certificate_authorities", "/path/to/ca.crt")
|
||||
.put("xpack.security.transport.ssl.enabled", "true")
|
||||
...
|
||||
|
|
|
@ -27,8 +27,8 @@ To use Kibana with {security}:
|
|||
requests as this user to access the cluster monitoring APIs and the `.kibana` index.
|
||||
The server does _not_ need access to user indices.
|
||||
+
|
||||
By default, the `kibana` user password is set to `changeme`. Change this password
|
||||
through the reset password API:
|
||||
By default, the `kibana` does not have a password. The user will not be enabled until
|
||||
a password is set. Set the password through the reset password API:
|
||||
+
|
||||
[source,shell]
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
|
@ -61,7 +61,7 @@ the `user` API:
|
|||
---------------------------------------------------------------
|
||||
POST _xpack/security/user/logstash_internal
|
||||
{
|
||||
"password" : "changeme",
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "logstash_writer"],
|
||||
"full_name" : "Internal Logstash User"
|
||||
}
|
||||
|
@ -76,18 +76,18 @@ plugins in your Logstash `.conf` file. For example:
|
|||
input {
|
||||
...
|
||||
user => logstash_internal
|
||||
password => changeme
|
||||
password => x-pack-test-password
|
||||
}
|
||||
filter {
|
||||
...
|
||||
user => logstash_internal
|
||||
password => changeme
|
||||
password => x-pack-test-password
|
||||
}
|
||||
output {
|
||||
elasticsearch {
|
||||
...
|
||||
user => logstash_internal
|
||||
password => changeme
|
||||
password => x-pack-test-password
|
||||
}
|
||||
--------------------------------------------------
|
||||
|
||||
|
@ -126,7 +126,7 @@ the `user` API:
|
|||
---------------------------------------------------------------
|
||||
POST _xpack/security/user/logstash_user
|
||||
{
|
||||
"password" : "changeme",
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "logstash_reader"],
|
||||
"full_name" : "Kibana User"
|
||||
}
|
||||
|
@ -187,8 +187,8 @@ This user has the minimum permissions necessary for the monitoring function, and
|
|||
_should not_ be used for any other purpose - it is specifically _not intended_ for
|
||||
use within a Logstash pipeline.
|
||||
|
||||
By default, the `logstash_system` user password is set to `changeme`.
|
||||
Change this password through the reset password API:
|
||||
By default, the `logstash_system` does not have a password. The user will not be enabled until
|
||||
a password is set. Set the password through the reset password API:
|
||||
|
||||
[source,js]
|
||||
---------------------------------------------------------------------
|
||||
|
|
|
@ -152,7 +152,7 @@ for the agent user:
|
|||
--------------------------------------------------
|
||||
xpack.monitoring.elasticsearch.url: ["http://es-mon-1:9200", "http://es-mon2:9200"]
|
||||
xpack.monitoring.elasticsearch.username: "remote_monitor"
|
||||
xpack.monitoring.elasticsearch.password: "changeme"
|
||||
xpack.monitoring.elasticsearch.password: "x-pack-test-password"
|
||||
--------------------------------------------------
|
||||
|
||||
.. If SSL/TLS is enabled on the monitoring cluster:
|
||||
|
@ -176,6 +176,6 @@ Alternatively, you can configure trusted certificates using a truststore
|
|||
[source,yaml]
|
||||
--------------------------------------------------
|
||||
xpack.monitoring.elasticsearch.ssl.truststore.path: /path/to/file
|
||||
xpack.monitoring.elasticsearch.ssl.truststore.password: changeme
|
||||
xpack.monitoring.elasticsearch.ssl.truststore.password: x-pack-test-password
|
||||
--------------------------------------------------
|
||||
--
|
|
@ -24,7 +24,7 @@ the following request creates a `reporter` user that has the
|
|||
---------------------------------------------------------------
|
||||
POST /_xpack/security/user/reporter
|
||||
{
|
||||
"password" : "changeme",
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : ["kibana_user", "reporting_user"],
|
||||
"full_name" : "Reporting User"
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ PUT _xpack/watcher/watch/cluster_health_watch
|
|||
"auth": {
|
||||
"basic": {
|
||||
"username": "elastic",
|
||||
"password": "changeme"
|
||||
"password": "x-pack-test-password"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ output { <2>
|
|||
elasticsearch {
|
||||
hosts => "http://localhost:9200"
|
||||
user => "elastic"
|
||||
password => "changeme"
|
||||
password => "x-pack-test-password"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import static java.util.Collections.singletonMap;
|
|||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
||||
public class XDocsClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
private static final String USER_TOKEN = basicAuthHeaderValue("test_admin", new SecureString("changeme".toCharArray()));
|
||||
private static final String USER_TOKEN = basicAuthHeaderValue("test_admin", new SecureString("x-pack-test-password".toCharArray()));
|
||||
|
||||
public XDocsClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
|
|
|
@ -206,13 +206,50 @@ integTestCluster {
|
|||
|
||||
waitCondition = { NodeInfo node, AntBuilder ant ->
|
||||
File tmpFile = new File(node.cwd, 'wait.success')
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
HttpURLConnection httpURLConnection = null;
|
||||
try {
|
||||
httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_xpack/security/user/elastic/_password")
|
||||
.openConnection();
|
||||
httpURLConnection.setRequestProperty("Authorization", "Basic " +
|
||||
Base64.getEncoder().encodeToString("elastic:".getBytes(StandardCharsets.UTF_8)));
|
||||
httpURLConnection.setRequestMethod("PUT");
|
||||
httpURLConnection.setDoOutput(true);
|
||||
httpURLConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||
|
||||
httpURLConnection.connect();
|
||||
OutputStream out = httpURLConnection.getOutputStream();
|
||||
out.write("{\"password\": \"x-pack-test-password\"}".getBytes(StandardCharsets.UTF_8));
|
||||
out.close()
|
||||
|
||||
if (httpURLConnection.getResponseCode() == 200) {
|
||||
break
|
||||
}
|
||||
} catch (Exception e) {
|
||||
httpURLConnection.disconnect()
|
||||
if (i == 9) {
|
||||
logger.error("final attempt to set elastic password", e)
|
||||
} else {
|
||||
logger.debug("failed to set elastic password", e)
|
||||
}
|
||||
} finally {
|
||||
if (httpURLConnection != null) {
|
||||
httpURLConnection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
// did not start, so wait a bit before trying again
|
||||
Thread.sleep(500L);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
// we use custom wait logic here as the elastic user is not available immediately and ant.get will fail when a 401 is returned
|
||||
HttpURLConnection httpURLConnection = null;
|
||||
try {
|
||||
httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_cluster/health?wait_for_nodes=${numNodes}&wait_for_status=yellow").openConnection();
|
||||
httpURLConnection.setRequestProperty("Authorization", "Basic " +
|
||||
Base64.getEncoder().encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8)));
|
||||
Base64.getEncoder().encodeToString("elastic:x-pack-test-password".getBytes(StandardCharsets.UTF_8)));
|
||||
httpURLConnection.setRequestMethod("GET");
|
||||
httpURLConnection.connect();
|
||||
if (httpURLConnection.getResponseCode() == 200) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.common.settings.SecureString;
|
|||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Setting.Property;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
|
@ -29,6 +30,7 @@ import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
|||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
@ -132,8 +134,8 @@ public class AuthenticationService extends AbstractComponent {
|
|||
|
||||
private final AuditableRequest request;
|
||||
private final User fallbackUser;
|
||||
private final ActionListener<Authentication> listener;
|
||||
|
||||
private final ActionListener<Authentication> listener;
|
||||
private RealmRef authenticatedBy = null;
|
||||
private RealmRef lookedupBy = null;
|
||||
private AuthenticationToken authenticationToken = null;
|
||||
|
@ -279,7 +281,7 @@ public class AuthenticationService extends AbstractComponent {
|
|||
authenticationToken.principal(), realm.name(), ex);
|
||||
logger.debug("Authentication failed due to exception", ex);
|
||||
userListener.onFailure(ex);
|
||||
}));
|
||||
}), request);
|
||||
} else {
|
||||
userListener.onResponse(null);
|
||||
}
|
||||
|
@ -436,16 +438,21 @@ public class AuthenticationService extends AbstractComponent {
|
|||
}
|
||||
}
|
||||
|
||||
abstract static class AuditableRequest {
|
||||
abstract static class AuditableRequest implements IncomingRequest {
|
||||
|
||||
final AuditTrail auditTrail;
|
||||
final AuthenticationFailureHandler failureHandler;
|
||||
final ThreadContext threadContext;
|
||||
private final InetSocketAddress remoteAddress;
|
||||
private final RequestType requestType;
|
||||
|
||||
AuditableRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext) {
|
||||
AuditableRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext,
|
||||
RequestType requestType, InetSocketAddress remoteAddress) {
|
||||
this.auditTrail = auditTrail;
|
||||
this.failureHandler = failureHandler;
|
||||
this.threadContext = threadContext;
|
||||
this.remoteAddress = remoteAddress;
|
||||
this.requestType = requestType;
|
||||
}
|
||||
|
||||
abstract void realmAuthenticationFailed(AuthenticationToken token, String realm);
|
||||
|
@ -461,6 +468,14 @@ public class AuthenticationService extends AbstractComponent {
|
|||
abstract ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token);
|
||||
|
||||
abstract void authenticationSuccess(String realm, User user);
|
||||
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
return remoteAddress;
|
||||
}
|
||||
|
||||
public RequestType getType() {
|
||||
return requestType;
|
||||
}
|
||||
}
|
||||
|
||||
static class AuditableTransportRequest extends AuditableRequest {
|
||||
|
@ -470,7 +485,7 @@ public class AuthenticationService extends AbstractComponent {
|
|||
|
||||
AuditableTransportRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext,
|
||||
String action, TransportMessage message) {
|
||||
super(auditTrail, failureHandler, threadContext);
|
||||
super(auditTrail, failureHandler, threadContext, getType(message), getRemoteAddress(message));
|
||||
this.action = action;
|
||||
this.message = message;
|
||||
}
|
||||
|
@ -523,15 +538,25 @@ public class AuthenticationService extends AbstractComponent {
|
|||
public String toString() {
|
||||
return "transport request action [" + action + "]";
|
||||
}
|
||||
|
||||
private static RequestType getType(TransportMessage message) {
|
||||
return message.remoteAddress() == null ? RequestType.LOCAL_NODE : RequestType.REMOTE_NODE;
|
||||
}
|
||||
|
||||
private static InetSocketAddress getRemoteAddress(TransportMessage message) {
|
||||
TransportAddress transportAddress = message.remoteAddress();
|
||||
return transportAddress == null ? null : transportAddress.address();
|
||||
}
|
||||
}
|
||||
|
||||
static class AuditableRestRequest extends AuditableRequest {
|
||||
|
||||
private final RestRequest request;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
AuditableRestRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext,
|
||||
RestRequest request) {
|
||||
super(auditTrail, failureHandler, threadContext);
|
||||
super(auditTrail, failureHandler, threadContext, RequestType.REST, (InetSocketAddress) request.getRemoteAddress());
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.security.authc;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* This represents an incoming request that needs to be authenticated
|
||||
*/
|
||||
public interface IncomingRequest {
|
||||
|
||||
/**
|
||||
* This method returns the remote address for the request. It will be null if the request is a
|
||||
* local transport request.
|
||||
*
|
||||
* @return the remote socket address
|
||||
*/
|
||||
InetSocketAddress getRemoteAddress();
|
||||
|
||||
/**
|
||||
* This returns the type of request that is incoming. It can be a rest request, a remote
|
||||
* transport request, or a local transport request.
|
||||
*
|
||||
* @return the request type
|
||||
*/
|
||||
RequestType getType();
|
||||
|
||||
enum RequestType {
|
||||
REST,
|
||||
REMOTE_NODE,
|
||||
LOCAL_NODE
|
||||
}
|
||||
}
|
|
@ -81,10 +81,12 @@ public abstract class Realm implements Comparable<Realm> {
|
|||
* {@link ActionListener#onResponse} with the User associated with the given token. An unsuccessful authentication calls
|
||||
* with {@code null} on the argument.
|
||||
*
|
||||
* The remote address should be null if the request initiated from the local node.
|
||||
* @param token The authentication token
|
||||
* @param listener The listener to pass the authentication result to
|
||||
* @param incomingRequest the request that is being authenticated
|
||||
*/
|
||||
public abstract void authenticate(AuthenticationToken token, ActionListener<User> listener);
|
||||
public abstract void authenticate(AuthenticationToken token, ActionListener<User> listener, IncomingRequest incomingRequest);
|
||||
|
||||
/**
|
||||
* Looks up the user identified the String identifier. A successful lookup will call the {@link ActionListener#onResponse}
|
||||
|
|
|
@ -7,12 +7,12 @@ package org.elasticsearch.xpack.security.authc.esnative;
|
|||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +35,7 @@ public class NativeRealm extends CachingUsernamePasswordRealm {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
userStore.verifyPassword(token.principal(), token.credentials(), listener);
|
||||
}
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ public class NativeRealmMigrator implements IndexLifecycleManager.IndexDataMigra
|
|||
}
|
||||
|
||||
try (SecureString secureString = new SecureString(passwordHash.toCharArray())) {
|
||||
return Hasher.BCRYPT.verify(ReservedRealm.DEFAULT_PASSWORD_TEXT, secureString.getChars());
|
||||
return Hasher.BCRYPT.verify(ReservedRealm.EMPTY_PASSWORD_TEXT, secureString.getChars());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -548,7 +548,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
} else if (password.isEmpty() && containerSettings.inContainer() && username.equals(ElasticUser.NAME)) {
|
||||
listener.onResponse(new ReservedUserInfo(containerSettings.getPasswordHash(), enabled, false));
|
||||
} else if (password.isEmpty()) {
|
||||
listener.onResponse(new ReservedUserInfo(ReservedRealm.DEFAULT_PASSWORD_HASH, enabled, true));
|
||||
listener.onResponse(new ReservedUserInfo(ReservedRealm.EMPTY_PASSWORD_HASH, enabled, true));
|
||||
} else {
|
||||
listener.onResponse(new ReservedUserInfo(password.toCharArray(), enabled, false));
|
||||
}
|
||||
|
@ -607,7 +607,7 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
char[] passwordHash = containerSettings.getPasswordHash();
|
||||
userInfos.put(searchHit.getId(), new ReservedUserInfo(passwordHash, enabled, false));
|
||||
} else if (password.isEmpty()) {
|
||||
userInfos.put(username, new ReservedUserInfo(ReservedRealm.DEFAULT_PASSWORD_HASH, enabled, true));
|
||||
userInfos.put(username, new ReservedUserInfo(ReservedRealm.EMPTY_PASSWORD_HASH, enabled, true));
|
||||
} else {
|
||||
userInfos.put(username, new ReservedUserInfo(password.toCharArray(), enabled, false));
|
||||
}
|
||||
|
@ -694,12 +694,12 @@ public class NativeUsersStore extends AbstractComponent {
|
|||
|
||||
public final char[] passwordHash;
|
||||
public final boolean enabled;
|
||||
public final boolean hasDefaultPassword;
|
||||
public final boolean hasEmptyPassword;
|
||||
|
||||
ReservedUserInfo(char[] passwordHash, boolean enabled, boolean hasDefaultPassword) {
|
||||
ReservedUserInfo(char[] passwordHash, boolean enabled, boolean hasEmptyPassword) {
|
||||
this.passwordHash = passwordHash;
|
||||
this.enabled = enabled;
|
||||
this.hasDefaultPassword = hasDefaultPassword;
|
||||
this.hasEmptyPassword = hasEmptyPassword;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.env.Environment;
|
|||
import org.elasticsearch.xpack.XPackSettings;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore.ReservedUserInfo;
|
||||
import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
|
||||
|
@ -30,6 +31,7 @@ import org.elasticsearch.xpack.security.user.KibanaUser;
|
|||
import org.elasticsearch.xpack.security.user.LogstashSystemUser;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -44,20 +46,20 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
|
||||
public static final String TYPE = "reserved";
|
||||
|
||||
public static final SecureString DEFAULT_PASSWORD_TEXT = new SecureString("changeme".toCharArray());
|
||||
static final char[] DEFAULT_PASSWORD_HASH = Hasher.BCRYPT.hash(DEFAULT_PASSWORD_TEXT);
|
||||
public static final SecureString EMPTY_PASSWORD_TEXT = new SecureString("".toCharArray());
|
||||
static final char[] EMPTY_PASSWORD_HASH = Hasher.BCRYPT.hash(EMPTY_PASSWORD_TEXT);
|
||||
|
||||
private static final ReservedUserInfo DEFAULT_USER_INFO = new ReservedUserInfo(DEFAULT_PASSWORD_HASH, true, true);
|
||||
private static final ReservedUserInfo DISABLED_USER_INFO = new ReservedUserInfo(DEFAULT_PASSWORD_HASH, false, true);
|
||||
private static final ReservedUserInfo DEFAULT_USER_INFO = new ReservedUserInfo(EMPTY_PASSWORD_HASH, true, true);
|
||||
private static final ReservedUserInfo DISABLED_USER_INFO = new ReservedUserInfo(EMPTY_PASSWORD_HASH, false, true);
|
||||
|
||||
public static final Setting<Boolean> ACCEPT_DEFAULT_PASSWORD_SETTING = Setting.boolSetting(
|
||||
Security.setting("authc.accept_default_password"), true, Setting.Property.NodeScope, Setting.Property.Filtered);
|
||||
Security.setting("authc.accept_default_password"), true, Setting.Property.NodeScope, Setting.Property.Filtered,
|
||||
Setting.Property.Deprecated);
|
||||
|
||||
private final NativeUsersStore nativeUsersStore;
|
||||
private final AnonymousUser anonymousUser;
|
||||
private final boolean realmEnabled;
|
||||
private final boolean anonymousEnabled;
|
||||
private final boolean defaultPasswordEnabled;
|
||||
private final SecurityLifecycleService securityLifecycleService;
|
||||
|
||||
public ReservedRealm(Environment env, Settings settings, NativeUsersStore nativeUsersStore, AnonymousUser anonymousUser,
|
||||
|
@ -67,12 +69,20 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
this.realmEnabled = XPackSettings.RESERVED_REALM_ENABLED_SETTING.get(settings);
|
||||
this.anonymousUser = anonymousUser;
|
||||
this.anonymousEnabled = AnonymousUser.isAnonymousEnabled(settings);
|
||||
this.defaultPasswordEnabled = ACCEPT_DEFAULT_PASSWORD_SETTING.get(settings);
|
||||
this.securityLifecycleService = securityLifecycleService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
if (incomingRequest.getType() != IncomingRequest.RequestType.REST) {
|
||||
doAuthenticate(token, listener, false);
|
||||
} else {
|
||||
InetAddress address = incomingRequest.getRemoteAddress().getAddress();
|
||||
doAuthenticate(token, listener, address.isAnyLocalAddress() || address.isLoopbackAddress());
|
||||
}
|
||||
}
|
||||
|
||||
private void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, boolean acceptEmptyPassword) {
|
||||
if (realmEnabled == false) {
|
||||
listener.onResponse(null);
|
||||
} else if (isReserved(token.principal(), config.globalSettings()) == false) {
|
||||
|
@ -82,7 +92,10 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
Runnable action;
|
||||
if (userInfo != null) {
|
||||
try {
|
||||
if (verifyPassword(userInfo, token)) {
|
||||
if (userInfo.hasEmptyPassword && isSetupMode(token.principal(), acceptEmptyPassword) == false) {
|
||||
action = () -> listener.onFailure(Exceptions.authenticationError("failed to authenticate user [{}]",
|
||||
token.principal()));
|
||||
} else if (verifyPassword(userInfo, token)) {
|
||||
final User user = getUser(token.principal(), userInfo);
|
||||
action = () -> listener.onResponse(user);
|
||||
} else {
|
||||
|
@ -90,7 +103,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
token.principal()));
|
||||
}
|
||||
} finally {
|
||||
if (userInfo.passwordHash != DEFAULT_PASSWORD_HASH) {
|
||||
if (userInfo.passwordHash != EMPTY_PASSWORD_HASH) {
|
||||
Arrays.fill(userInfo.passwordHash, (char) 0);
|
||||
}
|
||||
}
|
||||
|
@ -104,11 +117,12 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isSetupMode(String userName, boolean acceptEmptyPassword) {
|
||||
return ElasticUser.NAME.equals(userName) && acceptEmptyPassword;
|
||||
}
|
||||
|
||||
private boolean verifyPassword(ReservedUserInfo userInfo, UsernamePasswordToken token) {
|
||||
if (Hasher.BCRYPT.verify(token.credentials(), userInfo.passwordHash)) {
|
||||
if (userInfo.hasDefaultPassword && this.defaultPasswordEnabled == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -154,7 +168,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
assert username != null;
|
||||
switch (username) {
|
||||
case ElasticUser.NAME:
|
||||
return new ElasticUser(userInfo.enabled);
|
||||
return new ElasticUser(userInfo.enabled, userInfo.hasEmptyPassword);
|
||||
case KibanaUser.NAME:
|
||||
return new KibanaUser(userInfo.enabled);
|
||||
case LogstashSystemUser.NAME:
|
||||
|
@ -178,7 +192,8 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
List<User> users = new ArrayList<>(4);
|
||||
|
||||
ReservedUserInfo userInfo = reservedUserInfos.get(ElasticUser.NAME);
|
||||
users.add(new ElasticUser(userInfo == null || userInfo.enabled));
|
||||
users.add(new ElasticUser(userInfo == null || userInfo.enabled,
|
||||
userInfo == null || userInfo.hasEmptyPassword));
|
||||
|
||||
userInfo = reservedUserInfos.get(KibanaUser.NAME);
|
||||
users.add(new KibanaUser(userInfo == null || userInfo.enabled));
|
||||
|
|
|
@ -157,7 +157,7 @@ public class SetupPasswordTool extends MultiCommand {
|
|||
private OptionSpec<String> noPromptOption;
|
||||
|
||||
private String elasticUser = ElasticUser.NAME;
|
||||
private SecureString elasticUserPassword = ReservedRealm.DEFAULT_PASSWORD_TEXT;
|
||||
private SecureString elasticUserPassword = ReservedRealm.EMPTY_PASSWORD_TEXT;
|
||||
private String url;
|
||||
|
||||
SetupCommand(String description) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Set;
|
|||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
|
@ -37,7 +38,7 @@ public class FileRealm extends CachingUsernamePasswordRealm {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
if (userPasswdStore.verifyPassword(token.principal(), token.credentials())) {
|
||||
String[] roles = userRolesStore.roles(token.principal());
|
||||
listener.onResponse(new User(token.principal(), roles));
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.apache.lucene.util.IOUtils;
|
|||
import org.elasticsearch.ElasticsearchTimeoutException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.ContextPreservingActionListener;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Setting.Property;
|
||||
|
@ -29,6 +28,7 @@ import org.elasticsearch.common.util.concurrent.ThreadContext;
|
|||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPool.Names;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.RealmSettings;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapLoadBalancing;
|
||||
|
@ -142,7 +142,7 @@ public final class LdapRealm extends CachingUsernamePasswordRealm {
|
|||
* This user will then be passed to the listener
|
||||
*/
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
// we submit to the threadpool because authentication using LDAP will execute blocking I/O for a bind request and we don't want
|
||||
// network threads stuck waiting for a socket to connect. After the bind, then all interaction with LDAP should be async
|
||||
final CancellableLdapRunnable cancellableLdapRunnable = new CancellableLdapRunnable(listener,
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
|
||||
import org.elasticsearch.xpack.security.authc.support.mapper.CompositeRoleMapper;
|
||||
import org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore;
|
||||
|
@ -40,9 +41,6 @@ import java.util.Set;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.elasticsearch.xpack.XPackSettings.HTTP_SSL_ENABLED;
|
||||
import static org.elasticsearch.xpack.security.Security.setting;
|
||||
|
||||
public class PkiRealm extends Realm {
|
||||
|
||||
public static final String PKI_CERT_HEADER_NAME = "__SECURITY_CLIENT_CERTIFICATE";
|
||||
|
@ -84,7 +82,7 @@ public class PkiRealm extends Realm {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void authenticate(AuthenticationToken authToken, ActionListener<User> listener) {
|
||||
public void authenticate(AuthenticationToken authToken, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
X509AuthenticationToken token = (X509AuthenticationToken)authToken;
|
||||
if (isCertificateChainTrusted(trustManager, token, logger) == false) {
|
||||
listener.onResponse(null);
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.SecureString;
|
|||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
|
||||
|
@ -67,17 +68,18 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
|
|||
* If the user exists in the cache (keyed by the principle name), then the password is validated
|
||||
* against a hash also stored in the cache. Otherwise the subclass authenticates the user via
|
||||
* doAuthenticate
|
||||
*
|
||||
* @param authToken The authentication token
|
||||
* @param listener to be called at completion
|
||||
* @param incomingRequest the request that is being authenticated
|
||||
*/
|
||||
@Override
|
||||
public final void authenticate(AuthenticationToken authToken, ActionListener<User> listener) {
|
||||
UsernamePasswordToken token = (UsernamePasswordToken)authToken;
|
||||
public final void authenticate(AuthenticationToken authToken, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
UsernamePasswordToken token = (UsernamePasswordToken) authToken;
|
||||
try {
|
||||
if (cache == null) {
|
||||
doAuthenticate(token, listener);
|
||||
doAuthenticate(token, listener, incomingRequest);
|
||||
} else {
|
||||
authenticateWithCache(token, listener);
|
||||
authenticateWithCache(token, listener, incomingRequest);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// each realm should handle exceptions, if we get one here it should be considered fatal
|
||||
|
@ -85,7 +87,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
|
|||
}
|
||||
}
|
||||
|
||||
private void authenticateWithCache(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
private void authenticateWithCache(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
UserWithHash userWithHash = cache.get(token.principal());
|
||||
if (userWithHash == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
@ -97,7 +99,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
|
|||
logger.debug("realm [{}] authenticated user [{}], with roles [{}]", name(), token.principal(), user.roles());
|
||||
}
|
||||
listener.onResponse(user);
|
||||
}, listener::onFailure));
|
||||
}, listener::onFailure), incomingRequest);
|
||||
} else if (userWithHash.hasHash()) {
|
||||
if (userWithHash.verify(token.credentials())) {
|
||||
if (userWithHash.user.enabled()) {
|
||||
|
@ -114,7 +116,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
|
|||
user.enabled(), user.roles());
|
||||
}
|
||||
listener.onResponse(user);
|
||||
}, listener::onFailure));
|
||||
}, listener::onFailure), incomingRequest);
|
||||
}
|
||||
} else {
|
||||
cache.invalidate(token.principal());
|
||||
|
@ -124,7 +126,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
|
|||
name(), token.principal(), user.roles());
|
||||
}
|
||||
listener.onResponse(user);
|
||||
}, listener::onFailure));
|
||||
}, listener::onFailure), incomingRequest);
|
||||
}
|
||||
} else {
|
||||
cache.invalidate(token.principal());
|
||||
|
@ -134,12 +136,12 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
|
|||
"realm [{}] authenticated user [{}] with roles [{}]", name(), token.principal(), user.roles());
|
||||
}
|
||||
listener.onResponse(user);
|
||||
}, listener::onFailure));
|
||||
}, listener::onFailure), incomingRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private void doAuthenticateAndCache(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
doAuthenticate(token, ActionListener.wrap((user) -> {
|
||||
private void doAuthenticateAndCache(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
ActionListener<User> wrapped = ActionListener.wrap((user) -> {
|
||||
if (user == null) {
|
||||
listener.onResponse(null);
|
||||
} else {
|
||||
|
@ -148,7 +150,9 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
|
|||
cache.put(token.principal(), userWithHash);
|
||||
listener.onResponse(user);
|
||||
}
|
||||
}, listener::onFailure));
|
||||
}, listener::onFailure);
|
||||
|
||||
doAuthenticate(token, wrapped, incomingRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -158,7 +162,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
|
|||
return stats;
|
||||
}
|
||||
|
||||
protected abstract void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener);
|
||||
protected abstract void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest);
|
||||
|
||||
@Override
|
||||
public final void lookupUser(String username, ActionListener<User> listener) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.ElasticsearchSecurityException;
|
|||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.CompositeIndicesRequest;
|
||||
import org.elasticsearch.action.IndicesRequest;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthAction;
|
||||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||
|
@ -61,6 +62,7 @@ import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
|
|||
import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
|
||||
import org.elasticsearch.xpack.security.support.Automatons;
|
||||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||
import org.elasticsearch.xpack.security.user.ElasticUser;
|
||||
import org.elasticsearch.xpack.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
import org.elasticsearch.xpack.security.user.XPackUser;
|
||||
|
@ -147,6 +149,12 @@ public class AuthorizationService extends AbstractComponent {
|
|||
throw denial(authentication, action, request);
|
||||
}
|
||||
|
||||
// If the user is the elastic user in setup mode, then only change password requests can be authorized
|
||||
if (ElasticUser.isElasticUserInSetupMode(authentication.getUser())
|
||||
&& ChangePasswordAction.NAME.equals(action) == false) {
|
||||
throw denial(authentication, action, request);
|
||||
}
|
||||
|
||||
// get the roles of the authenticated user, which may be different than the effective
|
||||
Role permission = userRole;
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@ package org.elasticsearch.xpack.security.user;
|
|||
|
||||
import org.elasticsearch.xpack.security.support.MetadataUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The reserved {@code elastic} superuser. Has full permission/access to the cluster/indices and can
|
||||
* run as any other user.
|
||||
|
@ -15,8 +18,27 @@ public class ElasticUser extends User {
|
|||
|
||||
public static final String NAME = "elastic";
|
||||
private static final String ROLE_NAME = "superuser";
|
||||
private static final String SETUP_MODE = "_setup_mode";
|
||||
|
||||
public ElasticUser(boolean enabled) {
|
||||
super(NAME, new String[] { ROLE_NAME }, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA, enabled);
|
||||
this(enabled, false);
|
||||
}
|
||||
|
||||
public ElasticUser(boolean enabled, boolean setupMode) {
|
||||
super(NAME, new String[] { ROLE_NAME }, null, null, metadata(setupMode), enabled);
|
||||
}
|
||||
|
||||
public static boolean isElasticUserInSetupMode(User user) {
|
||||
return NAME.equals(user.principal()) && Boolean.TRUE.equals(user.metadata().get(SETUP_MODE));
|
||||
}
|
||||
|
||||
private static Map<String, Object> metadata(boolean setupMode) {
|
||||
if (setupMode == false) {
|
||||
return MetadataUtils.DEFAULT_RESERVED_METADATA;
|
||||
} else {
|
||||
HashMap<String, Object> metadata = new HashMap<>(MetadataUtils.DEFAULT_RESERVED_METADATA);
|
||||
metadata.put(SETUP_MODE, true);
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,8 +74,8 @@ public class BulkUpdateTests extends SecurityIntegTestCase {
|
|||
public void testThatBulkUpdateDoesNotLoseFieldsHttp() throws IOException {
|
||||
final String path = "/index1/type/1";
|
||||
final Header basicAuthHeader = new BasicHeader("Authorization",
|
||||
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.DEFAULT_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray())));
|
||||
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray())));
|
||||
|
||||
StringEntity body = new StringEntity("{\"test\":\"test\"}", ContentType.APPLICATION_JSON);
|
||||
Response response = getRestClient().performRequest("PUT", path, Collections.emptyMap(), body, basicAuthHeader);
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.elasticsearch.test.SecurityIntegTestCase;
|
|||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheRequest;
|
||||
import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheResponse;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
import org.elasticsearch.xpack.security.authc.Realms;
|
||||
import org.elasticsearch.xpack.security.authc.support.Hasher;
|
||||
|
@ -40,6 +41,7 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class ClearRealmsCacheTests extends SecurityIntegTestCase {
|
||||
private static final String USERS_PASSWD_HASHED = new String(Hasher.BCRYPT.hash(new SecureString("passwd".toCharArray())));
|
||||
|
@ -164,8 +166,8 @@ public class ClearRealmsCacheTests extends SecurityIntegTestCase {
|
|||
static void executeHttpRequest(String path, Map<String, String> params) throws Exception {
|
||||
Response response = getRestClient().performRequest("POST", path, params,
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.DEFAULT_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()))));
|
||||
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray()))));
|
||||
assertNotNull(response.getEntity());
|
||||
assertTrue(EntityUtils.toString(response.getEntity()).contains("cluster_name"));
|
||||
}
|
||||
|
@ -233,7 +235,7 @@ public class ClearRealmsCacheTests extends SecurityIntegTestCase {
|
|||
for (Realm realm : realms) {
|
||||
for (String username : usernames) {
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(tokens.get(username), future);
|
||||
realm.authenticate(tokens.get(username), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, notNullValue());
|
||||
Map<Realm, User> realmToUser = users.get(username);
|
||||
|
@ -250,7 +252,7 @@ public class ClearRealmsCacheTests extends SecurityIntegTestCase {
|
|||
for (String username : usernames) {
|
||||
for (Realm realm : realms) {
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(tokens.get(username), future);
|
||||
realm.authenticate(tokens.get(username), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, sameInstance(users.get(username).get(realm)));
|
||||
}
|
||||
|
@ -263,7 +265,7 @@ public class ClearRealmsCacheTests extends SecurityIntegTestCase {
|
|||
for (String username : usernames) {
|
||||
for (Realm realm : realms) {
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(tokens.get(username), future);
|
||||
realm.authenticate(tokens.get(username), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, notNullValue());
|
||||
scenario.assertEviction(users.get(username).get(realm), user);
|
||||
|
|
|
@ -33,7 +33,7 @@ public class MultipleIndicesPermissionsTests extends SecurityIntegTestCase {
|
|||
|
||||
@Override
|
||||
protected String configRoles() {
|
||||
return SecuritySettingsSource.DEFAULT_ROLE + ":\n" +
|
||||
return SecuritySettingsSource.TEST_ROLE + ":\n" +
|
||||
" cluster: [ all ]\n" +
|
||||
" indices:\n" +
|
||||
" - names: '*'\n" +
|
||||
|
|
|
@ -7,7 +7,6 @@ package org.elasticsearch.integration;
|
|||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.indices.TermsLookup;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
|
@ -26,7 +25,7 @@ public class SecurityCachePermissionTests extends SecurityIntegTestCase {
|
|||
@Override
|
||||
public String configUsers() {
|
||||
return super.configUsers()
|
||||
+ READ_ONE_IDX_USER + ":" + SecuritySettingsSource.DEFAULT_PASSWORD_HASHED + "\n";
|
||||
+ READ_ONE_IDX_USER + ":" + SecuritySettingsSource.TEST_PASSWORD_HASHED + "\n";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,7 +60,7 @@ public class SecurityCachePermissionTests extends SecurityIntegTestCase {
|
|||
// Repeat with unauthorized user!!!!
|
||||
try {
|
||||
response = client().filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(READ_ONE_IDX_USER,
|
||||
new SecureString("changeme".toCharArray()))))
|
||||
SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING)))
|
||||
.prepareSearch("data").setTypes("a").setQuery(QueryBuilders.constantScoreQuery(
|
||||
QueryBuilders.termsLookupQuery("token", new TermsLookup("tokens", "tokens", "1", "tokens"))))
|
||||
.execute().actionGet();
|
||||
|
|
|
@ -78,7 +78,7 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
@TestLogging("org.elasticsearch.cluster.service:TRACE,org.elasticsearch.discovery.zen:TRACE")
|
||||
public class LicensingTests extends SecurityIntegTestCase {
|
||||
public static final String ROLES =
|
||||
SecuritySettingsSource.DEFAULT_ROLE + ":\n" +
|
||||
SecuritySettingsSource.TEST_ROLE + ":\n" +
|
||||
" cluster: [ all ]\n" +
|
||||
" indices:\n" +
|
||||
" - names: '*'\n" +
|
||||
|
@ -204,8 +204,8 @@ public class LicensingTests extends SecurityIntegTestCase {
|
|||
e = expectThrows(ResponseException.class, () -> getRestClient().performRequest("GET", "/_xpack/security/_authenticate"));
|
||||
assertThat(e.getResponse().getStatusLine().getStatusCode(), is(401));
|
||||
|
||||
final String basicAuthValue = UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.DEFAULT_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()));
|
||||
final String basicAuthValue = UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray()));
|
||||
response = getRestClient().performRequest("GET", "/", new BasicHeader("Authorization", basicAuthValue));
|
||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||
response = getRestClient()
|
||||
|
|
|
@ -5,10 +5,28 @@
|
|||
*/
|
||||
package org.elasticsearch.test;
|
||||
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.nio.entity.NStringEntity;
|
||||
import org.elasticsearch.client.Response;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.xpack.security.client.SecurityClient;
|
||||
import org.elasticsearch.xpack.security.user.BeatsSystemUser;
|
||||
import org.elasticsearch.xpack.security.user.ElasticUser;
|
||||
import org.elasticsearch.xpack.security.user.KibanaUser;
|
||||
import org.elasticsearch.xpack.security.user.LogstashSystemUser;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Test case with method to handle the starting and stopping the stores for native users and roles
|
||||
*/
|
||||
|
@ -17,6 +35,7 @@ public abstract class NativeRealmIntegTestCase extends SecurityIntegTestCase {
|
|||
@Before
|
||||
public void ensureNativeStoresStarted() throws Exception {
|
||||
assertSecurityIndexActive();
|
||||
setupReservedPasswords();
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -29,4 +48,41 @@ public abstract class NativeRealmIntegTestCase extends SecurityIntegTestCase {
|
|||
client.prepareClearRealmCache().get();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
||||
.build();
|
||||
}
|
||||
|
||||
private SecureString reservedPassword = SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING;
|
||||
|
||||
protected SecureString getReservedPassword() {
|
||||
return reservedPassword;
|
||||
}
|
||||
|
||||
protected boolean shouldSetReservedUserPasswords() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setupReservedPasswords() throws IOException {
|
||||
if (shouldSetReservedUserPasswords() == false) {
|
||||
return;
|
||||
}
|
||||
logger.info("setting up reserved passwords for test");
|
||||
SecureString defaultPassword = new SecureString("".toCharArray());
|
||||
|
||||
for (String username : Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, BeatsSystemUser.NAME, LogstashSystemUser.NAME)) {
|
||||
SecureString authPassword = username.equals(ElasticUser.NAME) ? defaultPassword : reservedPassword;
|
||||
String payload = "{\"password\": \"" + new String(reservedPassword.getChars()) + "\"}";
|
||||
HttpEntity entity = new NStringEntity(payload, ContentType.APPLICATION_JSON);
|
||||
BasicHeader authHeader = new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, authPassword));
|
||||
String route = "/_xpack/security/user/" + username + "/_password";
|
||||
Response response = getRestClient().performRequest("PUT", route, Collections.emptyMap(), entity, authHeader);
|
||||
}
|
||||
logger.info("setting up reserved passwords finished");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,8 +244,8 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase {
|
|||
@Override
|
||||
protected Settings externalClusterClientSettings() {
|
||||
return Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), SecuritySettingsSource.DEFAULT_USER_NAME + ":"
|
||||
+ SecuritySettingsSource.DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), SecuritySettingsSource.TEST_USER_NAME + ":"
|
||||
+ SecuritySettingsSource.TEST_PASSWORD)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -52,25 +52,25 @@ public class SecuritySettingsSource extends ClusterDiscoveryConfiguration.Unicas
|
|||
|
||||
public static final Settings DEFAULT_SETTINGS = Settings.EMPTY;
|
||||
|
||||
public static final String DEFAULT_USER_NAME = "test_user";
|
||||
public static final String DEFAULT_PASSWORD = "changeme";
|
||||
public static final SecureString DEFAULT_PASSWORD_SECURE_STRING = new SecureString("changeme".toCharArray());
|
||||
public static final String DEFAULT_PASSWORD_HASHED = new String(Hasher.BCRYPT.hash(new SecureString(DEFAULT_PASSWORD.toCharArray())));
|
||||
public static final String DEFAULT_ROLE = "user";
|
||||
public static final String TEST_USER_NAME = "test_user";
|
||||
public static final String TEST_PASSWORD = "x-pack-test-password";
|
||||
public static final SecureString TEST_PASSWORD_SECURE_STRING = new SecureString("x-pack-test-password".toCharArray());
|
||||
public static final String TEST_PASSWORD_HASHED = new String(Hasher.BCRYPT.hash(new SecureString(TEST_PASSWORD.toCharArray())));
|
||||
public static final String TEST_ROLE = "user";
|
||||
|
||||
public static final String DEFAULT_TRANSPORT_CLIENT_ROLE = "transport_client";
|
||||
public static final String DEFAULT_TRANSPORT_CLIENT_USER_NAME = "test_trans_client_user";
|
||||
|
||||
public static final String CONFIG_STANDARD_USER =
|
||||
DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD_HASHED + "\n" +
|
||||
DEFAULT_TRANSPORT_CLIENT_USER_NAME + ":" + DEFAULT_PASSWORD_HASHED + "\n";
|
||||
TEST_USER_NAME + ":" + TEST_PASSWORD_HASHED + "\n" +
|
||||
DEFAULT_TRANSPORT_CLIENT_USER_NAME + ":" + TEST_PASSWORD_HASHED + "\n";
|
||||
|
||||
public static final String CONFIG_STANDARD_USER_ROLES =
|
||||
DEFAULT_ROLE + ":" + DEFAULT_USER_NAME + "," + DEFAULT_TRANSPORT_CLIENT_USER_NAME + "\n" +
|
||||
TEST_ROLE + ":" + TEST_USER_NAME + "," + DEFAULT_TRANSPORT_CLIENT_USER_NAME + "\n" +
|
||||
DEFAULT_TRANSPORT_CLIENT_ROLE + ":" + DEFAULT_TRANSPORT_CLIENT_USER_NAME+ "\n";
|
||||
|
||||
public static final String CONFIG_ROLE_ALLOW_ALL =
|
||||
DEFAULT_ROLE + ":\n" +
|
||||
TEST_ROLE + ":\n" +
|
||||
" cluster: [ ALL ]\n" +
|
||||
" indices:\n" +
|
||||
" - names: '*'\n" +
|
||||
|
@ -174,11 +174,11 @@ public class SecuritySettingsSource extends ClusterDiscoveryConfiguration.Unicas
|
|||
}
|
||||
|
||||
protected String nodeClientUsername() {
|
||||
return DEFAULT_USER_NAME;
|
||||
return TEST_USER_NAME;
|
||||
}
|
||||
|
||||
protected SecureString nodeClientPassword() {
|
||||
return new SecureString(DEFAULT_PASSWORD.toCharArray());
|
||||
return new SecureString(TEST_PASSWORD.toCharArray());
|
||||
}
|
||||
|
||||
protected String transportClientUsername() {
|
||||
|
@ -186,7 +186,7 @@ public class SecuritySettingsSource extends ClusterDiscoveryConfiguration.Unicas
|
|||
}
|
||||
|
||||
protected SecureString transportClientPassword() {
|
||||
return new SecureString(DEFAULT_PASSWORD.toCharArray());
|
||||
return new SecureString(TEST_PASSWORD.toCharArray());
|
||||
}
|
||||
|
||||
protected Class<? extends XPackPlugin> xpackPluginClass() {
|
||||
|
|
|
@ -55,7 +55,7 @@ public class SecurityTestsUtils {
|
|||
|
||||
public static void assertAuthorizationExceptionDefaultUsers(Throwable throwable, String action) {
|
||||
assertAuthorizationException(throwable, either(containsString("[" + action + "] is unauthorized for user ["
|
||||
+ SecuritySettingsSource.DEFAULT_USER_NAME + "]")).or(containsString("[" + action + "] is unauthorized for user ["
|
||||
+ SecuritySettingsSource.TEST_USER_NAME + "]")).or(containsString("[" + action + "] is unauthorized for user ["
|
||||
+ SecuritySettingsSource.DEFAULT_TRANSPORT_CLIENT_USER_NAME + "]")));
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ import org.apache.http.message.BasicHeader;
|
|||
import org.elasticsearch.client.Response;
|
||||
import org.elasticsearch.client.ResponseException;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.xpack.ml.MachineLearning;
|
||||
import org.junit.After;
|
||||
|
@ -33,9 +33,9 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
public class DatafeedJobsRestIT extends ESRestTestCase {
|
||||
|
||||
private static final String BASIC_AUTH_VALUE_ELASTIC =
|
||||
basicAuthHeaderValue("elastic", new SecureString("changeme".toCharArray()));
|
||||
basicAuthHeaderValue("elastic", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
private static final String BASIC_AUTH_VALUE_ML_ADMIN =
|
||||
basicAuthHeaderValue("ml_admin", new SecureString("changeme".toCharArray()));
|
||||
basicAuthHeaderValue("ml_admin", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
|
||||
@Override
|
||||
protected Settings restClientSettings() {
|
||||
|
@ -50,11 +50,16 @@ public class DatafeedJobsRestIT extends ESRestTestCase {
|
|||
|
||||
@Before
|
||||
public void setUpData() throws Exception {
|
||||
String password = new String(SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING.getChars());
|
||||
String elasticUserPayload = "{\"password\" : \"" + password + "\"}";
|
||||
|
||||
client().performRequest("put", "_xpack/security/user/elastic/_password", Collections.emptyMap(),
|
||||
new StringEntity(elasticUserPayload, ContentType.APPLICATION_JSON));
|
||||
|
||||
// This user has admin rights on machine learning, but (importantly for the tests) no
|
||||
// rights on any of the data indexes
|
||||
String user = "{"
|
||||
+ " \"password\" : \"changeme\","
|
||||
+ " \"password\" : \"" + password + "\","
|
||||
+ " \"roles\" : [ \"machine_learning_admin\" ]"
|
||||
+ "}";
|
||||
|
||||
|
|
|
@ -9,11 +9,11 @@ import org.apache.http.entity.ContentType;
|
|||
import org.apache.http.entity.StringEntity;
|
||||
import org.elasticsearch.client.Response;
|
||||
import org.elasticsearch.client.ResponseException;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
|
||||
import org.elasticsearch.common.util.concurrent.ConcurrentMapLong;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.xpack.ml.MachineLearning;
|
||||
import org.elasticsearch.xpack.ml.job.persistence.AnomalyDetectorsIndex;
|
||||
|
@ -36,7 +36,7 @@ import static org.hamcrest.Matchers.not;
|
|||
|
||||
public class MlJobIT extends ESRestTestCase {
|
||||
|
||||
private static final String BASIC_AUTH_VALUE = basicAuthHeaderValue("elastic", new SecureString("changeme".toCharArray()));
|
||||
private static final String BASIC_AUTH_VALUE = basicAuthHeaderValue("elastic", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
|
||||
@Override
|
||||
protected Settings restClientSettings() {
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
|
|||
import org.elasticsearch.search.SearchModule;
|
||||
import org.elasticsearch.tasks.Task;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.XPackSettings;
|
||||
import org.elasticsearch.xpack.ml.MlMetadata;
|
||||
import org.elasticsearch.xpack.ml.action.CloseJobAction;
|
||||
|
@ -80,7 +81,7 @@ abstract class MlNativeAutodetectIntegTestCase extends SecurityIntegTestCase {
|
|||
protected Settings externalClusterClientSettings() {
|
||||
Settings.Builder builder = Settings.builder();
|
||||
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4);
|
||||
builder.put(Security.USER_SETTING.getKey(), "elastic:changeme");
|
||||
builder.put(Security.USER_SETTING.getKey(), "elastic:" + SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
builder.put(XPackSettings.MACHINE_LEARNING_ENABLED.getKey(), true);
|
||||
return builder.build();
|
||||
}
|
||||
|
|
|
@ -84,8 +84,8 @@ public class OldMonitoringIndicesBackwardsCompatibilityTests extends AbstractOld
|
|||
httpExporter.put("type", "http");
|
||||
httpExporter.put("enabled", port == null ? "false" : "true");
|
||||
httpExporter.put("host", "http://localhost:" + (port == null ? "does_not_matter" : port));
|
||||
httpExporter.put("auth.username", SecuritySettingsSource.DEFAULT_USER_NAME);
|
||||
httpExporter.put("auth.password", SecuritySettingsSource.DEFAULT_PASSWORD);
|
||||
httpExporter.put("auth.username", SecuritySettingsSource.TEST_USER_NAME);
|
||||
httpExporter.put("auth.password", SecuritySettingsSource.TEST_PASSWORD);
|
||||
|
||||
settings.putProperties(httpExporter, k -> MonitoringSettings.EXPORTERS_SETTINGS.getKey() + "my_exporter." + k);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.elasticsearch.index.IndexNotFoundException;
|
|||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.test.TestCluster;
|
||||
import org.elasticsearch.test.store.MockFSIndexStore;
|
||||
import org.elasticsearch.test.transport.MockTransportService;
|
||||
|
@ -157,7 +158,7 @@ public abstract class MonitoringIntegTestCase extends ESIntegTestCase {
|
|||
return Settings.builder()
|
||||
.put(super.transportClientSettings())
|
||||
.put("client.transport.sniff", false)
|
||||
.put(Security.USER_SETTING.getKey(), "test:changeme")
|
||||
.put(Security.USER_SETTING.getKey(), "test:" + SecuritySettings.TEST_PASSWORD)
|
||||
.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4)
|
||||
.put(NetworkModule.HTTP_TYPE_KEY, Security.NAME4)
|
||||
.put(XPackSettings.WATCHER_ENABLED.getKey(), watcherEnabled)
|
||||
|
@ -467,7 +468,7 @@ public abstract class MonitoringIntegTestCase extends ESIntegTestCase {
|
|||
public static class SecuritySettings {
|
||||
|
||||
public static final String TEST_USERNAME = "test";
|
||||
public static final String TEST_PASSWORD = "changeme";
|
||||
public static final String TEST_PASSWORD = SecuritySettingsSource.TEST_PASSWORD;
|
||||
private static final String TEST_PASSWORD_HASHED = new String(Hasher.BCRYPT.hash(new SecureString(TEST_PASSWORD.toCharArray())));
|
||||
|
||||
static boolean auditLogsEnabled = SystemPropertyUtil.getBoolean("tests.audit_logs", true);
|
||||
|
|
|
@ -43,8 +43,8 @@ public class SecurityPluginTests extends SecurityIntegTestCase {
|
|||
logger.info("executing authorized request to /_xpack infos");
|
||||
Response response = getRestClient().performRequest("GET", "/_xpack",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
basicAuthHeaderValue(SecuritySettingsSource.DEFAULT_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()))));
|
||||
basicAuthHeaderValue(SecuritySettingsSource.TEST_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray()))));
|
||||
assertThat(response.getStatusLine().getStatusCode(), is(OK.getStatus()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,22 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.nio.entity.NStringEntity;
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.elasticsearch.client.RestClientBuilder;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.ClusterStateObserver;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.UUIDs;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.SecureSettings;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
|
@ -33,11 +40,14 @@ import org.elasticsearch.xpack.security.action.role.PutRoleResponse;
|
|||
import org.elasticsearch.xpack.security.action.user.PutUserResponse;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.xpack.security.client.SecurityClient;
|
||||
import org.elasticsearch.xpack.security.user.ElasticUser;
|
||||
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -76,7 +86,16 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase {
|
|||
super.setUp();
|
||||
if (cluster2 == null) {
|
||||
SecuritySettingsSource cluster2SettingsSource =
|
||||
new SecuritySettingsSource(defaultMaxNumberOfNodes(), useGeneratedSSL, createTempDir(), Scope.SUITE);
|
||||
new SecuritySettingsSource(defaultMaxNumberOfNodes(), useGeneratedSSL, createTempDir(), Scope.SUITE) {
|
||||
@Override
|
||||
public Settings nodeSettings(int nodeOrdinal) {
|
||||
return Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
||||
.build();
|
||||
}
|
||||
};
|
||||
|
||||
cluster2 = new InternalTestCluster(randomLong(), createTempDir(), true, true, 1, 2,
|
||||
UUIDs.randomBase64UUID(random()), cluster2SettingsSource, 0, false, SECOND_CLUSTER_NODE_PREFIX, getMockPlugins(),
|
||||
getClientWrapper());
|
||||
|
@ -85,6 +104,11 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSetReservedUserPasswords() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useGeneratedSSLConfig() {
|
||||
return useGeneratedSSL;
|
||||
|
@ -138,8 +162,17 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase {
|
|||
|
||||
private void setupTribeNode(Settings settings) throws NodeValidationException, InterruptedException {
|
||||
SecuritySettingsSource cluster2SettingsSource =
|
||||
new SecuritySettingsSource(1, useGeneratedSSL, createTempDir(), Scope.TEST);
|
||||
Map<String,String> asMap = new HashMap<>(cluster2SettingsSource.nodeSettings(0).getAsMap());
|
||||
new SecuritySettingsSource(1, useGeneratedSSL, createTempDir(), Scope.TEST) {
|
||||
@Override
|
||||
public Settings nodeSettings(int nodeOrdinal) {
|
||||
return Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
|
||||
.build();
|
||||
}
|
||||
};
|
||||
|
||||
Map<String, String> asMap = new HashMap<>(cluster2SettingsSource.nodeSettings(0).getAsMap());
|
||||
asMap.remove(NodeEnvironment.MAX_LOCAL_STORAGE_NODES_SETTING.getKey());
|
||||
Settings.Builder tribe1Defaults = Settings.builder();
|
||||
Settings.Builder tribe2Defaults = Settings.builder();
|
||||
|
@ -216,9 +249,25 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase {
|
|||
}
|
||||
|
||||
public void testThatTribeCanAuthenticateElasticUser() throws Exception {
|
||||
InetSocketAddress[] inetSocketAddresses = cluster2.httpAddresses();
|
||||
List<HttpHost> hosts = new ArrayList<>();
|
||||
for (InetSocketAddress address : inetSocketAddresses) {
|
||||
hosts.add(new HttpHost(address.getAddress(), address.getPort()));
|
||||
}
|
||||
RestClientBuilder builder = RestClient.builder(hosts.toArray(new HttpHost[hosts.size()]));
|
||||
RestClient client = builder.build();
|
||||
|
||||
String payload = "{\"password\": \"" + SecuritySettingsSource.TEST_PASSWORD + "\"}";
|
||||
HttpEntity entity = new NStringEntity(payload, ContentType.APPLICATION_JSON);
|
||||
BasicHeader authHeader = new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, new SecureString("".toCharArray())));
|
||||
String route = "/_xpack/security/user/" + ElasticUser.NAME + "/_password";
|
||||
client.performRequest("PUT", route, Collections.emptyMap(), entity, authHeader);
|
||||
client.close();
|
||||
|
||||
setupTribeNode(Settings.EMPTY);
|
||||
ClusterHealthResponse response = tribeClient.filterWithHeader(Collections.singletonMap("Authorization",
|
||||
UsernamePasswordToken.basicAuthHeaderValue("elastic", new SecureString("changeme".toCharArray()))))
|
||||
UsernamePasswordToken.basicAuthHeaderValue("elastic", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING)))
|
||||
.admin().cluster().prepareHealth().get();
|
||||
assertNoTimeout(response);
|
||||
}
|
||||
|
@ -308,7 +357,7 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase {
|
|||
PutUserResponse response =
|
||||
securityClient(nonPreferredClient).preparePutUser(username, "password".toCharArray(), "superuser").get();
|
||||
assertTrue(response.created());
|
||||
shouldBeSuccessfulUsers.add(username);
|
||||
shouldBeSuccessfulUsers.add(username);
|
||||
}
|
||||
|
||||
assertTribeNodeHasAllIndices();
|
||||
|
|
|
@ -9,8 +9,8 @@ import org.elasticsearch.ElasticsearchSecurityException;
|
|||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.ActionFilters;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
||||
import org.elasticsearch.xpack.security.authc.support.Hasher;
|
||||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||
|
@ -54,7 +54,7 @@ public class TransportChangePasswordActionTests extends ESTestCase {
|
|||
|
||||
ChangePasswordRequest request = new ChangePasswordRequest();
|
||||
request.username(anonymousUser.principal());
|
||||
request.passwordHash(Hasher.BCRYPT.hash(new SecureString("changeme".toCharArray())));
|
||||
request.passwordHash(Hasher.BCRYPT.hash(SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING));
|
||||
|
||||
final AtomicReference<Throwable> throwableRef = new AtomicReference<>();
|
||||
final AtomicReference<ChangePasswordResponse> responseRef = new AtomicReference<>();
|
||||
|
@ -85,7 +85,7 @@ public class TransportChangePasswordActionTests extends ESTestCase {
|
|||
|
||||
ChangePasswordRequest request = new ChangePasswordRequest();
|
||||
request.username(randomFrom(SystemUser.INSTANCE.principal(), XPackUser.INSTANCE.principal()));
|
||||
request.passwordHash(Hasher.BCRYPT.hash(new SecureString("changeme".toCharArray())));
|
||||
request.passwordHash(Hasher.BCRYPT.hash(SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING));
|
||||
|
||||
final AtomicReference<Throwable> throwableRef = new AtomicReference<>();
|
||||
final AtomicReference<ChangePasswordResponse> responseRef = new AtomicReference<>();
|
||||
|
@ -112,15 +112,13 @@ public class TransportChangePasswordActionTests extends ESTestCase {
|
|||
NativeUsersStore usersStore = mock(NativeUsersStore.class);
|
||||
ChangePasswordRequest request = new ChangePasswordRequest();
|
||||
request.username(user.principal());
|
||||
request.passwordHash(Hasher.BCRYPT.hash(new SecureString("changeme".toCharArray())));
|
||||
doAnswer(new Answer() {
|
||||
public Void answer(InvocationOnMock invocation) {
|
||||
Object[] args = invocation.getArguments();
|
||||
assert args.length == 2;
|
||||
ActionListener<Void> listener = (ActionListener<Void>) args[1];
|
||||
listener.onResponse(null);
|
||||
return null;
|
||||
}
|
||||
request.passwordHash(Hasher.BCRYPT.hash(SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING));
|
||||
doAnswer(invocation -> {
|
||||
Object[] args = invocation.getArguments();
|
||||
assert args.length == 2;
|
||||
ActionListener<Void> listener = (ActionListener<Void>) args[1];
|
||||
listener.onResponse(null);
|
||||
return null;
|
||||
}).when(usersStore).changePassword(eq(request), any(ActionListener.class));
|
||||
TransportService transportService = new TransportService(Settings.EMPTY, null, null, TransportService.NOOP_TRANSPORT_INTERCEPTOR,
|
||||
x -> null, null);
|
||||
|
@ -152,7 +150,7 @@ public class TransportChangePasswordActionTests extends ESTestCase {
|
|||
NativeUsersStore usersStore = mock(NativeUsersStore.class);
|
||||
ChangePasswordRequest request = new ChangePasswordRequest();
|
||||
request.username(user.principal());
|
||||
request.passwordHash(Hasher.BCRYPT.hash(new SecureString("changeme".toCharArray())));
|
||||
request.passwordHash(Hasher.BCRYPT.hash(SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING));
|
||||
final Exception e = randomFrom(new ElasticsearchSecurityException(""), new IllegalStateException(), new RuntimeException());
|
||||
doAnswer(new Answer() {
|
||||
public Void answer(InvocationOnMock invocation) {
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
|||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealmTests;
|
||||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||
import org.elasticsearch.xpack.security.user.ElasticUser;
|
||||
import org.elasticsearch.xpack.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
@ -180,9 +181,11 @@ public class TransportGetUsersActionTests extends ESTestCase {
|
|||
}
|
||||
});
|
||||
|
||||
User[] users = responseRef.get().users();
|
||||
|
||||
assertThat(throwableRef.get(), is(nullValue()));
|
||||
assertThat(responseRef.get(), is(notNullValue()));
|
||||
assertThat(responseRef.get().users(), arrayContaining(reservedUsers.toArray(new User[reservedUsers.size()])));
|
||||
assertThat(users, arrayContaining(reservedUsers.toArray(new User[reservedUsers.size()])));
|
||||
}
|
||||
|
||||
public void testGetAllUsers() {
|
||||
|
|
|
@ -11,10 +11,10 @@ import org.elasticsearch.action.support.ActionFilters;
|
|||
import org.elasticsearch.action.support.PlainActionFuture;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.common.ValidationException;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
|
@ -163,7 +163,7 @@ public class TransportPutUserActionTests extends ESTestCase {
|
|||
final PutUserRequest request = new PutUserRequest();
|
||||
request.username(user.principal());
|
||||
if (isCreate) {
|
||||
request.passwordHash(Hasher.BCRYPT.hash(new SecureString("changeme".toCharArray())));
|
||||
request.passwordHash(Hasher.BCRYPT.hash(SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING));
|
||||
}
|
||||
final boolean created = isCreate ? randomBoolean() : false; // updates should always return false for create
|
||||
doAnswer(new Answer() {
|
||||
|
|
|
@ -15,8 +15,6 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
import org.apache.http.message.BasicHeader;
|
||||
import org.elasticsearch.action.ActionFuture;
|
||||
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
|
||||
import org.elasticsearch.action.admin.indices.recovery.RecoveryAction;
|
||||
import org.elasticsearch.action.admin.indices.recovery.RecoveryRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.support.PlainActionFuture;
|
||||
import org.elasticsearch.client.Client;
|
||||
|
@ -24,7 +22,6 @@ import org.elasticsearch.client.Requests;
|
|||
import org.elasticsearch.client.ResponseException;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
|
@ -37,7 +34,7 @@ import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
|||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import static org.elasticsearch.test.SecuritySettingsSource.DEFAULT_PASSWORD_SECURE_STRING;
|
||||
import static org.elasticsearch.test.SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
@ -70,7 +67,7 @@ public class AuditTrailTests extends SecurityIntegTestCase {
|
|||
@Override
|
||||
public String configUsers() {
|
||||
return super.configUsers()
|
||||
+ AUTHENTICATE_USER + ":" + SecuritySettingsSource.DEFAULT_PASSWORD_HASHED + "\n"
|
||||
+ AUTHENTICATE_USER + ":" + SecuritySettingsSource.TEST_PASSWORD_HASHED + "\n"
|
||||
+ EXECUTE_USER + ":xx_no_password_xx\n";
|
||||
}
|
||||
|
||||
|
@ -90,7 +87,7 @@ public class AuditTrailTests extends SecurityIntegTestCase {
|
|||
try {
|
||||
getRestClient().performRequest("GET", "/.security/_search",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(AUTHENTICATE_USER, DEFAULT_PASSWORD_SECURE_STRING)),
|
||||
UsernamePasswordToken.basicAuthHeaderValue(AUTHENTICATE_USER, TEST_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, EXECUTE_USER));
|
||||
fail("request should have failed");
|
||||
} catch (ResponseException e) {
|
||||
|
@ -112,7 +109,7 @@ public class AuditTrailTests extends SecurityIntegTestCase {
|
|||
try {
|
||||
getRestClient().performRequest("GET", "/.security/_search",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(AUTHENTICATE_USER, DEFAULT_PASSWORD_SECURE_STRING)),
|
||||
UsernamePasswordToken.basicAuthHeaderValue(AUTHENTICATE_USER, TEST_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, ""));
|
||||
fail("request should have failed");
|
||||
} catch (ResponseException e) {
|
||||
|
|
|
@ -183,8 +183,8 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
|||
Settings.Builder builder = Settings.builder()
|
||||
.put("xpack.security.audit.index.client." + XPackSettings.SECURITY_ENABLED.getKey(), useSecurity)
|
||||
.put(remoteSettings(NetworkAddress.format(inet.address().getAddress()), inet.address().getPort(), cluster2Name))
|
||||
.put("xpack.security.audit.index.client.xpack.security.user", SecuritySettingsSource.DEFAULT_USER_NAME + ":" +
|
||||
SecuritySettingsSource.DEFAULT_PASSWORD);
|
||||
.put("xpack.security.audit.index.client.xpack.security.user", SecuritySettingsSource.TEST_USER_NAME + ":" +
|
||||
SecuritySettingsSource.TEST_PASSWORD);
|
||||
|
||||
if (useGeneratedSSL == false) {
|
||||
cluster2SettingsSource.addClientSSLSettings(builder, "xpack.security.audit.index.client.");
|
||||
|
|
|
@ -101,7 +101,7 @@ public class RemoteIndexAuditTrailStartingTests extends SecurityIntegTestCase {
|
|||
.put("xpack.security.audit.outputs", randomFrom("index", "index,logfile"))
|
||||
.putArray("xpack.security.audit.index.client.hosts", addresses.toArray(new String[addresses.size()]))
|
||||
.put("xpack.security.audit.index.client.cluster.name", clusterName)
|
||||
.put("xpack.security.audit.index.client.xpack.security.user", DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD);
|
||||
.put("xpack.security.audit.index.client.xpack.security.user", TEST_USER_NAME + ":" + TEST_PASSWORD);
|
||||
|
||||
addClientSSLSettings(builder, "xpack.security.audit.index.client.");
|
||||
return builder.build();
|
||||
|
|
|
@ -5,16 +5,6 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Clock;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
|
@ -24,11 +14,14 @@ import org.elasticsearch.action.get.GetRequest;
|
|||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.action.support.PlainActionFuture;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.SuppressForbidden;
|
||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
|
@ -53,6 +46,18 @@ import org.elasticsearch.xpack.security.user.User;
|
|||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.time.Clock;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.elasticsearch.test.SecurityTestsUtils.assertAuthenticationException;
|
||||
import static org.elasticsearch.xpack.security.support.Exceptions.authenticationError;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
|
@ -93,12 +98,16 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
private TokenService tokenService;
|
||||
private SecurityLifecycleService lifecycleService;
|
||||
private Client client;
|
||||
private InetSocketAddress remoteAddress;
|
||||
|
||||
@Before
|
||||
@SuppressForbidden(reason = "Allow accessing localhost")
|
||||
public void init() throws Exception {
|
||||
token = mock(AuthenticationToken.class);
|
||||
message = new InternalMessage();
|
||||
restRequest = new FakeRestRequest();
|
||||
remoteAddress = new InetSocketAddress(InetAddress.getLocalHost(), 100);
|
||||
message.remoteAddress(new TransportAddress(remoteAddress));
|
||||
restRequest = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY).withRemoteAddress(remoteAddress).build();
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
|
||||
firstRealm = mock(Realm.class);
|
||||
|
@ -206,7 +215,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
}, this::logAndFail));
|
||||
verify(auditTrail).authenticationSuccess(secondRealm.name(), user, "_action", message);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(firstRealm, never()).authenticate(eq(token), any(ActionListener.class));
|
||||
verify(firstRealm, never()).authenticate(eq(token), any(ActionListener.class), any(IncomingRequest.class));
|
||||
assertTrue(completed.get());
|
||||
}
|
||||
|
||||
|
@ -562,7 +571,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
doThrow(authenticationError("realm doesn't like authenticate"))
|
||||
.when(secondRealm).authenticate(eq(token), any(ActionListener.class));
|
||||
.when(secondRealm).authenticate(eq(token), any(ActionListener.class), any(IncomingRequest.class));
|
||||
try {
|
||||
authenticateBlocking("_action", message, null);
|
||||
fail("exception should bubble out");
|
||||
|
@ -577,7 +586,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
doThrow(authenticationError("realm doesn't like authenticate"))
|
||||
.when(secondRealm).authenticate(eq(token), any(ActionListener.class));
|
||||
.when(secondRealm).authenticate(eq(token), any(ActionListener.class), any(IncomingRequest.class));
|
||||
try {
|
||||
authenticateBlocking(restRequest);
|
||||
fail("exception should bubble out");
|
||||
|
@ -869,7 +878,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
ActionListener listener = (ActionListener) i.getArguments()[1];
|
||||
listener.onResponse(user);
|
||||
return null;
|
||||
}).when(realm).authenticate(eq(token), any(ActionListener.class));
|
||||
}).when(realm).authenticate(eq(token), any(ActionListener.class), any(IncomingRequest.class));
|
||||
}
|
||||
|
||||
private Authentication authenticateBlocking(RestRequest restRequest) {
|
||||
|
|
|
@ -436,7 +436,7 @@ public class RealmsTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void authenticate(AuthenticationToken token, ActionListener<User> listener) {
|
||||
public void authenticate(AuthenticationToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
listener.onResponse(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.test.SecuritySettingsSource.DEFAULT_PASSWORD_SECURE_STRING;
|
||||
import static org.elasticsearch.test.SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
@ -40,7 +40,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
private static final String TRANSPORT_CLIENT_USER = "transport_user";
|
||||
private static final String ROLES =
|
||||
"run_as_role:\n" +
|
||||
" run_as: [ '" + SecuritySettingsSource.DEFAULT_USER_NAME + "', 'idontexist' ]\n";
|
||||
" run_as: [ '" + SecuritySettingsSource.TEST_USER_NAME + "', 'idontexist' ]\n";
|
||||
|
||||
// indicates whether the RUN_AS_USER that is being authenticated is also a superuser
|
||||
private static boolean runAsHasSuperUserRole;
|
||||
|
@ -66,8 +66,8 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
@Override
|
||||
public String configUsers() {
|
||||
return super.configUsers()
|
||||
+ RUN_AS_USER + ":" + SecuritySettingsSource.DEFAULT_PASSWORD_HASHED + "\n"
|
||||
+ TRANSPORT_CLIENT_USER + ":" + SecuritySettingsSource.DEFAULT_PASSWORD_HASHED + "\n";
|
||||
+ RUN_AS_USER + ":" + SecuritySettingsSource.TEST_PASSWORD_HASHED + "\n"
|
||||
+ TRANSPORT_CLIENT_USER + ":" + SecuritySettingsSource.TEST_PASSWORD_HASHED + "\n";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,7 +89,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
|
||||
public void testUserImpersonation() throws Exception {
|
||||
try (TransportClient client = getTransportClient(Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), TRANSPORT_CLIENT_USER + ":" + SecuritySettingsSource.DEFAULT_PASSWORD).build())) {
|
||||
.put(Security.USER_SETTING.getKey(), TRANSPORT_CLIENT_USER + ":" + SecuritySettingsSource.TEST_PASSWORD).build())) {
|
||||
//ensure the client can connect
|
||||
assertBusy(() -> assertThat(client.connectedNodes().size(), greaterThan(0)));
|
||||
|
||||
|
@ -104,7 +104,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
// let's run as without authorization
|
||||
try {
|
||||
Map<String, String> headers = Collections.singletonMap(AuthenticationService.RUN_AS_USER_HEADER,
|
||||
SecuritySettingsSource.DEFAULT_USER_NAME);
|
||||
SecuritySettingsSource.TEST_USER_NAME);
|
||||
client.filterWithHeader(headers)
|
||||
.admin().cluster().prepareHealth().get();
|
||||
fail("run as should be unauthorized for the transport client user");
|
||||
|
@ -115,8 +115,8 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER,
|
||||
new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray())));
|
||||
headers.put(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME);
|
||||
new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray())));
|
||||
headers.put(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.TEST_USER_NAME);
|
||||
// lets set the user
|
||||
ClusterHealthResponse response = client.filterWithHeader(headers).admin().cluster().prepareHealth().get();
|
||||
assertThat(response.isTimedOut(), is(false));
|
||||
|
@ -129,8 +129,8 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
getRestClient().performRequest("GET", "/_nodes",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(TRANSPORT_CLIENT_USER,
|
||||
DEFAULT_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME));
|
||||
TEST_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.TEST_USER_NAME));
|
||||
fail("request should have failed");
|
||||
} catch(ResponseException e) {
|
||||
assertThat(e.getResponse().getStatusLine().getStatusCode(), is(403));
|
||||
|
@ -142,7 +142,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
getRestClient().performRequest("GET", "/_nodes",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER,
|
||||
DEFAULT_PASSWORD_SECURE_STRING)));
|
||||
TEST_PASSWORD_SECURE_STRING)));
|
||||
fail("request should have failed");
|
||||
} catch (ResponseException e) {
|
||||
assertThat(e.getResponse().getStatusLine().getStatusCode(), is(403));
|
||||
|
@ -153,14 +153,14 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
Response response = getRestClient().performRequest("GET", "/_nodes",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER,
|
||||
DEFAULT_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME));
|
||||
TEST_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.TEST_USER_NAME));
|
||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||
}
|
||||
|
||||
public void testEmptyUserImpersonationHeader() throws Exception {
|
||||
try (TransportClient client = getTransportClient(Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), TRANSPORT_CLIENT_USER + ":" + SecuritySettingsSource.DEFAULT_PASSWORD).build())) {
|
||||
.put(Security.USER_SETTING.getKey(), TRANSPORT_CLIENT_USER + ":" + SecuritySettingsSource.TEST_PASSWORD).build())) {
|
||||
//ensure the client can connect
|
||||
awaitBusy(() -> {
|
||||
return client.connectedNodes().size() > 0;
|
||||
|
@ -169,7 +169,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
try {
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER,
|
||||
new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray())));
|
||||
new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray())));
|
||||
headers.put(AuthenticationService.RUN_AS_USER_HEADER, "");
|
||||
|
||||
client.filterWithHeader(headers).admin().cluster().prepareHealth().get();
|
||||
|
@ -185,7 +185,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
getRestClient().performRequest("GET", "/_nodes",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER,
|
||||
DEFAULT_PASSWORD_SECURE_STRING)),
|
||||
TEST_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, ""));
|
||||
fail("request should have failed");
|
||||
} catch(ResponseException e) {
|
||||
|
@ -195,7 +195,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
|
||||
public void testNonExistentRunAsUser() throws Exception {
|
||||
try (TransportClient client = getTransportClient(Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), TRANSPORT_CLIENT_USER + ":" + SecuritySettingsSource.DEFAULT_PASSWORD).build())) {
|
||||
.put(Security.USER_SETTING.getKey(), TRANSPORT_CLIENT_USER + ":" + SecuritySettingsSource.TEST_PASSWORD).build())) {
|
||||
//ensure the client can connect
|
||||
awaitBusy(() -> {
|
||||
return client.connectedNodes().size() > 0;
|
||||
|
@ -204,7 +204,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
try {
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER,
|
||||
new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray())));
|
||||
new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray())));
|
||||
headers.put(AuthenticationService.RUN_AS_USER_HEADER, "idontexist");
|
||||
|
||||
client.filterWithHeader(headers).admin().cluster().prepareHealth().get();
|
||||
|
@ -220,7 +220,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
|
|||
getRestClient().performRequest("GET", "/_nodes",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER,
|
||||
DEFAULT_PASSWORD_SECURE_STRING)),
|
||||
TEST_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, "idontexist"));
|
||||
fail("request should have failed");
|
||||
} catch (ResponseException e) {
|
||||
|
|
|
@ -50,8 +50,8 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
SecurityClient securityClient = new SecurityClient(client);
|
||||
CreateTokenResponse response = securityClient.prepareCreateToken()
|
||||
.setGrantType("password")
|
||||
.setUsername(SecuritySettingsSource.DEFAULT_USER_NAME)
|
||||
.setPassword(new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()))
|
||||
.setUsername(SecuritySettingsSource.TEST_USER_NAME)
|
||||
.setPassword(new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray()))
|
||||
.get();
|
||||
Instant created = Instant.now();
|
||||
|
||||
|
@ -90,8 +90,8 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
public void testExpireMultipleTimes() throws Exception {
|
||||
CreateTokenResponse response = securityClient().prepareCreateToken()
|
||||
.setGrantType("password")
|
||||
.setUsername(SecuritySettingsSource.DEFAULT_USER_NAME)
|
||||
.setPassword(new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()))
|
||||
.setUsername(SecuritySettingsSource.TEST_USER_NAME)
|
||||
.setPassword(new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray()))
|
||||
.get();
|
||||
|
||||
InvalidateTokenResponse invalidateResponse = securityClient().prepareInvalidateToken(response.getTokenString()).get();
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.test.SecuritySettingsSource;
|
|||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.authc.support.CharArrays;
|
||||
import org.elasticsearch.xpack.security.client.SecurityClient;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -39,6 +40,11 @@ public class ESNativeMigrateToolTests extends NativeRealmIntegTestCase {
|
|||
useSSL = randomBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSetReservedUserPasswords() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings nodeSettings(int nodeOrdinal) {
|
||||
logger.info("--> use SSL? {}", useSSL);
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.cli.Terminal.Verbosity;
|
|||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.security.authz.RoleDescriptor;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
|
@ -104,9 +105,12 @@ public class ESNativeRealmMigrateToolTests extends CommandTestCase {
|
|||
Files.createDirectories(xpackConfDir);
|
||||
|
||||
ESNativeRealmMigrateTool.MigrateUserOrRoles muor = new ESNativeRealmMigrateTool.MigrateUserOrRoles();
|
||||
OptionSet options = muor.getParser().parse("-u", "elastic", "-p", "changeme", "-U", "http://localhost:9200");
|
||||
|
||||
OptionSet options = muor.getParser().parse("-u", "elastic", "-p", SecuritySettingsSource.TEST_PASSWORD,
|
||||
"-U", "http://localhost:9200");
|
||||
Settings settings = Settings.builder().put("path.home", homeDir).build();
|
||||
Environment environment = new Environment(settings, confDir);
|
||||
|
||||
MockTerminal mockTerminal = new MockTerminal();
|
||||
|
||||
FileNotFoundException fnfe = expectThrows(FileNotFoundException.class,
|
||||
|
|
|
@ -252,13 +252,13 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
public void testUpdatingUserAndAuthentication() throws Exception {
|
||||
SecurityClient c = securityClient();
|
||||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.DEFAULT_ROLE).get();
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.TEST_ROLE).get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SecurityLifecycleService.SECURITY_INDEX_NAME);
|
||||
logger.info("--> retrieving user");
|
||||
GetUsersResponse resp = c.prepareGetUsers("joe").get();
|
||||
assertTrue("user should exist", resp.hasUsers());
|
||||
assertThat(resp.users()[0].roles(), arrayContaining(SecuritySettingsSource.DEFAULT_ROLE));
|
||||
assertThat(resp.users()[0].roles(), arrayContaining(SecuritySettingsSource.TEST_ROLE));
|
||||
|
||||
createIndex("idx");
|
||||
ensureGreen("idx");
|
||||
|
@ -269,7 +269,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
|
||||
assertEquals(searchResp.getHits().getTotalHits(), 1L);
|
||||
|
||||
c.preparePutUser("joe", "s3krit2".toCharArray(), SecuritySettingsSource.DEFAULT_ROLE).get();
|
||||
c.preparePutUser("joe", "s3krit2".toCharArray(), SecuritySettingsSource.TEST_ROLE).get();
|
||||
|
||||
try {
|
||||
client().filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch("idx").get();
|
||||
|
@ -287,13 +287,13 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
public void testCreateDeleteAuthenticate() {
|
||||
SecurityClient c = securityClient();
|
||||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.DEFAULT_ROLE).get();
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.TEST_ROLE).get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SecurityLifecycleService.SECURITY_INDEX_NAME);
|
||||
logger.info("--> retrieving user");
|
||||
GetUsersResponse resp = c.prepareGetUsers("joe").get();
|
||||
assertTrue("user should exist", resp.hasUsers());
|
||||
assertThat(resp.users()[0].roles(), arrayContaining(SecuritySettingsSource.DEFAULT_ROLE));
|
||||
assertThat(resp.users()[0].roles(), arrayContaining(SecuritySettingsSource.TEST_ROLE));
|
||||
|
||||
createIndex("idx");
|
||||
ensureGreen("idx");
|
||||
|
@ -417,9 +417,9 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
assertThat(client.prepareGetUsers("joes").get().hasUsers(), is(false));
|
||||
|
||||
// create joe with a password and verify the user works
|
||||
client.preparePutUser("joe", "changeme".toCharArray(), "admin_role").get();
|
||||
client.preparePutUser("joe", SecuritySettingsSource.TEST_PASSWORD.toCharArray(), "admin_role").get();
|
||||
assertThat(client.prepareGetUsers("joe").get().hasUsers(), is(true));
|
||||
final String token = basicAuthHeaderValue("joe", new SecureString("changeme".toCharArray()));
|
||||
final String token = basicAuthHeaderValue("joe", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster()
|
||||
.prepareHealth().get();
|
||||
assertFalse(response.isTimedOut());
|
||||
|
@ -445,7 +445,8 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
}
|
||||
|
||||
// update the user with password and admin role again
|
||||
client.preparePutUser("joe", "changeme2".toCharArray(), "admin_role").fullName("Joe Smith").get();
|
||||
String secondPassword = SecuritySettingsSource.TEST_PASSWORD + "2";
|
||||
client.preparePutUser("joe", secondPassword.toCharArray(), "admin_role").fullName("Joe Smith").get();
|
||||
getUsersResponse = client.prepareGetUsers("joe").get();
|
||||
assertThat(getUsersResponse.hasUsers(), is(true));
|
||||
assertThat(getUsersResponse.users().length, is(1));
|
||||
|
@ -465,7 +466,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
response = client()
|
||||
.filterWithHeader(
|
||||
Collections.singletonMap("Authorization",
|
||||
basicAuthHeaderValue("joe", new SecureString("changeme2".toCharArray()))))
|
||||
basicAuthHeaderValue("joe", new SecureString(secondPassword.toCharArray()))))
|
||||
.admin().cluster().prepareHealth().get();
|
||||
assertFalse(response.isTimedOut());
|
||||
}
|
||||
|
@ -493,7 +494,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
|
||||
SecurityClient client = securityClient();
|
||||
if (randomBoolean()) {
|
||||
client.preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.DEFAULT_ROLE).get();
|
||||
client.preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.TEST_ROLE).get();
|
||||
} else {
|
||||
client.preparePutRole("read_role")
|
||||
.cluster("none")
|
||||
|
@ -512,7 +513,8 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
public void testOperationsOnReservedUsers() throws Exception {
|
||||
final String username = randomFrom(ElasticUser.NAME, KibanaUser.NAME);
|
||||
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
|
||||
() -> securityClient().preparePutUser(username, randomBoolean() ? "changeme".toCharArray() : null, "admin").get());
|
||||
() -> securityClient().preparePutUser(username, randomBoolean() ? SecuritySettingsSource.TEST_PASSWORD.toCharArray()
|
||||
: null, "admin").get());
|
||||
assertThat(exception.getMessage(), containsString("Username [" + username + "] is reserved"));
|
||||
|
||||
exception = expectThrows(IllegalArgumentException.class,
|
||||
|
@ -551,7 +553,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
// authenticate should work
|
||||
AuthenticateResponse authenticateResponse = client()
|
||||
.filterWithHeader(Collections.singletonMap("Authorization",
|
||||
basicAuthHeaderValue(username, new SecureString("changeme".toCharArray()))))
|
||||
basicAuthHeaderValue(username, getReservedPassword())))
|
||||
.execute(AuthenticateAction.INSTANCE, new AuthenticateRequest(username))
|
||||
.get();
|
||||
assertThat(authenticateResponse.user().principal(), is(username));
|
||||
|
@ -574,7 +576,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
}
|
||||
|
||||
public void testCreateAndChangePassword() throws Exception {
|
||||
securityClient().preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.DEFAULT_ROLE).get();
|
||||
securityClient().preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.TEST_ROLE).get();
|
||||
final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray()));
|
||||
ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token))
|
||||
.admin().cluster().prepareHealth().get();
|
||||
|
@ -582,7 +584,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
|
||||
ChangePasswordResponse passwordResponse = securityClient(
|
||||
client().filterWithHeader(Collections.singletonMap("Authorization", token)))
|
||||
.prepareChangePassword("joe", "changeme".toCharArray())
|
||||
.prepareChangePassword("joe", SecuritySettingsSource.TEST_PASSWORD.toCharArray())
|
||||
.get();
|
||||
assertThat(passwordResponse, notNullValue());
|
||||
|
||||
|
@ -594,7 +596,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
response = client()
|
||||
.filterWithHeader(
|
||||
Collections.singletonMap("Authorization",
|
||||
basicAuthHeaderValue("joe", new SecureString("changeme".toCharArray()))))
|
||||
basicAuthHeaderValue("joe", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING)))
|
||||
.admin().cluster().prepareHealth().get();
|
||||
assertThat(response.isTimedOut(), is(false));
|
||||
}
|
||||
|
@ -660,7 +662,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
}
|
||||
|
||||
public void testSetEnabled() throws Exception {
|
||||
securityClient().preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.DEFAULT_ROLE).get();
|
||||
securityClient().preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.TEST_ROLE).get();
|
||||
final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray()));
|
||||
ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token))
|
||||
.admin().cluster().prepareHealth().get();
|
||||
|
@ -720,7 +722,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
* the loader returned a null value, while the other caller(s) would get a null value unexpectedly
|
||||
*/
|
||||
public void testConcurrentRunAs() throws Exception {
|
||||
securityClient().preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.DEFAULT_ROLE).get();
|
||||
securityClient().preparePutUser("joe", "s3krit".toCharArray(), SecuritySettingsSource.TEST_ROLE).get();
|
||||
securityClient().preparePutUser("executor", "s3krit".toCharArray(), "superuser").get();
|
||||
final String token = basicAuthHeaderValue("executor", new SecureString("s3krit".toCharArray()));
|
||||
final Client client = client().filterWithHeader(MapBuilder.<String, String>newMapBuilder()
|
||||
|
|
|
@ -168,7 +168,7 @@ public class NativeRealmMigratorTests extends ESTestCase {
|
|||
this.reservedUsers = Collections.singletonMap(
|
||||
KibanaUser.NAME,
|
||||
MapBuilder.<String, Object>newMapBuilder()
|
||||
.put(User.Fields.PASSWORD.getPreferredName(), new String(Hasher.BCRYPT.hash(ReservedRealm.DEFAULT_PASSWORD_TEXT)))
|
||||
.put(User.Fields.PASSWORD.getPreferredName(), new String(Hasher.BCRYPT.hash(ReservedRealm.EMPTY_PASSWORD_TEXT)))
|
||||
.put(User.Fields.ENABLED.getPreferredName(), false)
|
||||
.immutableMap()
|
||||
);
|
||||
|
@ -181,7 +181,7 @@ public class NativeRealmMigratorTests extends ESTestCase {
|
|||
this.reservedUsers = Collections.singletonMap(
|
||||
KibanaUser.NAME,
|
||||
MapBuilder.<String, Object>newMapBuilder()
|
||||
.put(User.Fields.PASSWORD.getPreferredName(), new String(Hasher.BCRYPT.hash(ReservedRealm.DEFAULT_PASSWORD_TEXT)))
|
||||
.put(User.Fields.PASSWORD.getPreferredName(), new String(Hasher.BCRYPT.hash(ReservedRealm.EMPTY_PASSWORD_TEXT)))
|
||||
.put(User.Fields.ENABLED.getPreferredName(), false)
|
||||
.immutableMap()
|
||||
);
|
||||
|
@ -195,7 +195,7 @@ public class NativeRealmMigratorTests extends ESTestCase {
|
|||
.stream().collect(Collectors.toMap(Function.identity(),
|
||||
name -> MapBuilder.<String, Object>newMapBuilder()
|
||||
.put(User.Fields.PASSWORD.getPreferredName(),
|
||||
new String(Hasher.BCRYPT.hash(ReservedRealm.DEFAULT_PASSWORD_TEXT)))
|
||||
new String(Hasher.BCRYPT.hash(ReservedRealm.EMPTY_PASSWORD_TEXT)))
|
||||
.put(User.Fields.ENABLED.getPreferredName(), randomBoolean())
|
||||
.immutableMap()
|
||||
));
|
||||
|
|
|
@ -111,9 +111,9 @@ public class NativeUsersStoreTests extends ESTestCase {
|
|||
actionRespond(GetRequest.class, new GetResponse(result));
|
||||
|
||||
final NativeUsersStore.ReservedUserInfo userInfo = future.get();
|
||||
assertThat(userInfo.hasDefaultPassword, equalTo(true));
|
||||
assertThat(userInfo.hasEmptyPassword, equalTo(true));
|
||||
assertThat(userInfo.enabled, equalTo(true));
|
||||
assertThat(userInfo.passwordHash, equalTo(ReservedRealm.DEFAULT_PASSWORD_HASH));
|
||||
assertThat(userInfo.passwordHash, equalTo(ReservedRealm.EMPTY_PASSWORD_HASH));
|
||||
}
|
||||
|
||||
public void testInContainerTrueReturnsEmptyPasswordForNonElasticReservedUsers() throws Exception {
|
||||
|
@ -142,9 +142,9 @@ public class NativeUsersStoreTests extends ESTestCase {
|
|||
actionRespond(GetRequest.class, new GetResponse(result));
|
||||
|
||||
final NativeUsersStore.ReservedUserInfo userInfo = future.get();
|
||||
assertThat(userInfo.hasDefaultPassword, equalTo(true));
|
||||
assertThat(userInfo.hasEmptyPassword, equalTo(true));
|
||||
assertThat(userInfo.enabled, equalTo(true));
|
||||
assertThat(userInfo.passwordHash, equalTo(ReservedRealm.DEFAULT_PASSWORD_HASH));
|
||||
assertThat(userInfo.passwordHash, equalTo(ReservedRealm.EMPTY_PASSWORD_HASH));
|
||||
}
|
||||
|
||||
public void testInContainerTrueReturnsBootstrapPasswordForElastic() throws Exception {
|
||||
|
@ -171,7 +171,7 @@ public class NativeUsersStoreTests extends ESTestCase {
|
|||
actionRespond(GetRequest.class, new GetResponse(result));
|
||||
|
||||
final NativeUsersStore.ReservedUserInfo userInfo = future.get();
|
||||
assertThat(userInfo.hasDefaultPassword, equalTo(false));
|
||||
assertThat(userInfo.hasEmptyPassword, equalTo(false));
|
||||
assertThat(userInfo.enabled, equalTo(true));
|
||||
assertThat(userInfo.passwordHash, equalTo(passwordHash));
|
||||
}
|
||||
|
|
|
@ -8,11 +8,13 @@ package org.elasticsearch.xpack.security.authc.esnative;
|
|||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.test.NativeRealmIntegTestCase;
|
||||
import org.elasticsearch.xpack.security.action.user.ChangePasswordResponse;
|
||||
import org.elasticsearch.xpack.security.client.SecurityClient;
|
||||
import org.elasticsearch.xpack.security.user.BeatsSystemUser;
|
||||
import org.elasticsearch.xpack.security.user.ElasticUser;
|
||||
import org.elasticsearch.xpack.security.user.KibanaUser;
|
||||
import org.elasticsearch.xpack.security.action.user.ChangePasswordResponse;
|
||||
import org.elasticsearch.test.NativeRealmIntegTestCase;
|
||||
import org.elasticsearch.xpack.security.user.LogstashSystemUser;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
@ -27,12 +29,10 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
*/
|
||||
public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
|
||||
|
||||
private static final SecureString DEFAULT_PASSWORD = new SecureString("changeme".toCharArray());
|
||||
|
||||
public void testAuthenticate() {
|
||||
for (String username : Arrays.asList(ElasticUser.NAME, KibanaUser.NAME)) {
|
||||
for (String username : Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, BeatsSystemUser.NAME, LogstashSystemUser.NAME)) {
|
||||
ClusterHealthResponse response = client()
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, DEFAULT_PASSWORD)))
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, getReservedPassword())))
|
||||
.admin()
|
||||
.cluster()
|
||||
.prepareHealth()
|
||||
|
@ -43,15 +43,15 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Enabling a user forces a doc to be written to the security index, and "user doc with default password" has a special case code in
|
||||
* Enabling a user forces a doc to be written to the security index, and "user doc with empty password" has a special case code in
|
||||
* the reserved realm.
|
||||
*/
|
||||
public void testAuthenticateAfterEnablingUser() {
|
||||
final SecurityClient c = securityClient();
|
||||
for (String username : Arrays.asList(ElasticUser.NAME, KibanaUser.NAME)) {
|
||||
for (String username : Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, BeatsSystemUser.NAME, LogstashSystemUser.NAME)) {
|
||||
c.prepareSetEnabled(username, true).get();
|
||||
ClusterHealthResponse response = client()
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, DEFAULT_PASSWORD)))
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, getReservedPassword())))
|
||||
.admin()
|
||||
.cluster()
|
||||
.prepareHealth()
|
||||
|
@ -62,12 +62,12 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
}
|
||||
|
||||
public void testChangingPassword() {
|
||||
String username = randomFrom(ElasticUser.NAME, KibanaUser.NAME);
|
||||
String username = randomFrom(ElasticUser.NAME, KibanaUser.NAME, BeatsSystemUser.NAME, LogstashSystemUser.NAME);
|
||||
final char[] newPassword = "supersecretvalue".toCharArray();
|
||||
|
||||
if (randomBoolean()) {
|
||||
ClusterHealthResponse response = client()
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, DEFAULT_PASSWORD)))
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, getReservedPassword())))
|
||||
.admin()
|
||||
.cluster()
|
||||
.prepareHealth()
|
||||
|
@ -81,7 +81,7 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
assertThat(response, notNullValue());
|
||||
|
||||
ElasticsearchSecurityException elasticsearchSecurityException = expectThrows(ElasticsearchSecurityException.class, () -> client()
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, DEFAULT_PASSWORD)))
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(username, getReservedPassword())))
|
||||
.admin()
|
||||
.cluster()
|
||||
.prepareHealth()
|
||||
|
@ -100,7 +100,7 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
public void testDisablingUser() throws Exception {
|
||||
// validate the user works
|
||||
ClusterHealthResponse response = client()
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(ElasticUser.NAME, DEFAULT_PASSWORD)))
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(ElasticUser.NAME, getReservedPassword())))
|
||||
.admin()
|
||||
.cluster()
|
||||
.prepareHealth()
|
||||
|
@ -110,7 +110,7 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
// disable user
|
||||
securityClient().prepareSetEnabled(ElasticUser.NAME, false).get();
|
||||
ElasticsearchSecurityException elasticsearchSecurityException = expectThrows(ElasticsearchSecurityException.class, () -> client()
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(ElasticUser.NAME, DEFAULT_PASSWORD)))
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(ElasticUser.NAME, getReservedPassword())))
|
||||
.admin()
|
||||
.cluster()
|
||||
.prepareHealth()
|
||||
|
@ -120,7 +120,7 @@ public class ReservedRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
//enable
|
||||
securityClient().prepareSetEnabled(ElasticUser.NAME, true).get();
|
||||
response = client()
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(ElasticUser.NAME, DEFAULT_PASSWORD)))
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(ElasticUser.NAME, getReservedPassword())))
|
||||
.admin()
|
||||
.cluster()
|
||||
.prepareHealth()
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.security.authc.esnative;
|
||||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.NativeRealmIntegTestCase;
|
||||
import org.elasticsearch.xpack.security.client.SecurityClient;
|
||||
import org.elasticsearch.xpack.security.user.KibanaUser;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
/**
|
||||
* Integration tests for the built in realm with default passwords disabled
|
||||
*/
|
||||
public class ReservedRealmNoDefaultPasswordIntegTests extends NativeRealmIntegTestCase {
|
||||
|
||||
private static final SecureString DEFAULT_PASSWORD = new SecureString("changeme".toCharArray());
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
Settings.Builder builder = Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(ReservedRealm.ACCEPT_DEFAULT_PASSWORD_SETTING.getKey(), false);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* This ensures that if a user is explicitly enabled, thus creating an entry in the security index, but no password is ever set,
|
||||
* then the user is treated as having a default password, and cannot login.
|
||||
*/
|
||||
public void testEnablingUserWithoutPasswordCannotLogin() throws Exception {
|
||||
final SecurityClient c = securityClient();
|
||||
c.prepareSetEnabled(KibanaUser.NAME, true).get();
|
||||
|
||||
ElasticsearchSecurityException elasticsearchSecurityException = expectThrows(ElasticsearchSecurityException.class, () -> client()
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(KibanaUser.NAME, DEFAULT_PASSWORD)))
|
||||
.admin()
|
||||
.cluster()
|
||||
.prepareHealth()
|
||||
.get());
|
||||
assertThat(elasticsearchSecurityException.getMessage(), containsString("authenticate"));
|
||||
|
||||
final SecureString newPassword = new SecureString("not-the-default-password".toCharArray());
|
||||
c.prepareChangePassword(KibanaUser.NAME, newPassword.clone().getChars()).get();
|
||||
|
||||
ClusterHealthResponse response = client()
|
||||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(KibanaUser.NAME, newPassword)))
|
||||
.admin()
|
||||
.cluster()
|
||||
.prepareHealth()
|
||||
.get();
|
||||
|
||||
assertThat(response.getClusterName(), is(cluster().getClusterName()));
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import org.elasticsearch.ElasticsearchSecurityException;
|
|||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.PlainActionFuture;
|
||||
import org.elasticsearch.common.SuppressForbidden;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
|
@ -16,6 +17,7 @@ import org.elasticsearch.env.Environment;
|
|||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.XPackSettings;
|
||||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore.ReservedUserInfo;
|
||||
import org.elasticsearch.xpack.security.authc.support.Hasher;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
|
@ -28,6 +30,9 @@ import org.elasticsearch.xpack.security.user.User;
|
|||
import org.junit.Before;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
@ -58,62 +63,38 @@ import static org.mockito.Mockito.when;
|
|||
*/
|
||||
public class ReservedRealmTests extends ESTestCase {
|
||||
|
||||
private static final SecureString DEFAULT_PASSWORD = new SecureString("changeme".toCharArray());
|
||||
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;
|
||||
private IncomingRequest incomingRequest;
|
||||
|
||||
@Before
|
||||
public void setupMocks() throws Exception {
|
||||
usersStore = mock(NativeUsersStore.class);
|
||||
securityLifecycleService = mock(SecurityLifecycleService.class);
|
||||
incomingRequest = mock(IncomingRequest.class);
|
||||
when(securityLifecycleService.isSecurityIndexAvailable()).thenReturn(true);
|
||||
when(securityLifecycleService.checkSecurityMappingVersion(any())).thenReturn(true);
|
||||
mockGetAllReservedUserInfo(usersStore, Collections.emptyMap());
|
||||
}
|
||||
|
||||
public void testMappingVersionFromBeforeUserExisted() throws ExecutionException, InterruptedException {
|
||||
@SuppressForbidden(reason = "allow getting localhost")
|
||||
public void testMappingVersionFromBeforeUserExisted() throws ExecutionException, InterruptedException, UnknownHostException {
|
||||
when(securityLifecycleService.checkSecurityMappingVersion(any())).thenReturn(false);
|
||||
final ReservedRealm reservedRealm =
|
||||
new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
|
||||
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
final String principal = randomFrom(ElasticUser.NAME, KibanaUser.NAME, LogstashSystemUser.NAME);
|
||||
final String principal = ElasticUser.NAME;
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
reservedRealm.authenticate(new UsernamePasswordToken(principal, DEFAULT_PASSWORD), future);
|
||||
InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 100);
|
||||
when(incomingRequest.getRemoteAddress()).thenReturn(address);
|
||||
when(incomingRequest.getType()).thenReturn(IncomingRequest.RequestType.REST);
|
||||
reservedRealm.authenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), future, incomingRequest);
|
||||
assertThat(future.get().enabled(), equalTo(false));
|
||||
}
|
||||
|
||||
public void testSuccessfulDefaultPasswordAuthentication() throws Throwable {
|
||||
final User expected = randomFrom(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true));
|
||||
final String principal = expected.principal();
|
||||
final boolean securityIndexExists = randomBoolean();
|
||||
if (securityIndexExists) {
|
||||
when(securityLifecycleService.isSecurityIndexExisting()).thenReturn(true);
|
||||
doAnswer((i) -> {
|
||||
ActionListener listener = (ActionListener) i.getArguments()[1];
|
||||
listener.onResponse(null);
|
||||
return null;
|
||||
}).when(usersStore).getReservedUserInfo(eq(principal), any(ActionListener.class));
|
||||
}
|
||||
final ReservedRealm reservedRealm =
|
||||
new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
|
||||
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
|
||||
PlainActionFuture<User> listener = new PlainActionFuture<>();
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, DEFAULT_PASSWORD), listener);
|
||||
final User authenticated = listener.actionGet();
|
||||
assertEquals(expected, authenticated);
|
||||
verify(securityLifecycleService).isSecurityIndexExisting();
|
||||
if (securityIndexExists) {
|
||||
verify(usersStore).getReservedUserInfo(eq(principal), any(ActionListener.class));
|
||||
}
|
||||
final ArgumentCaptor<Predicate> predicateCaptor = ArgumentCaptor.forClass(Predicate.class);
|
||||
verify(securityLifecycleService).checkSecurityMappingVersion(predicateCaptor.capture());
|
||||
verifyVersionPredicate(principal, predicateCaptor.getValue());
|
||||
verifyNoMoreInteractions(usersStore);
|
||||
}
|
||||
|
||||
public void testDisableDefaultPasswordAuthentication() throws Throwable {
|
||||
final User expected = randomFrom(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true));
|
||||
|
||||
|
@ -135,7 +116,51 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
assertThat(e.getMessage(), containsString("failed to authenticate"));
|
||||
}
|
||||
};
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(expected.principal(), DEFAULT_PASSWORD), listener);
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(expected.principal(), EMPTY_PASSWORD), listener, incomingRequest);
|
||||
}
|
||||
|
||||
public void testElasticEmptyPasswordAuthenticationFailsFromNonLocalhost() 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));
|
||||
|
||||
PlainActionFuture<User> listener = new PlainActionFuture<>();
|
||||
|
||||
InetSocketAddress address = new InetSocketAddress(InetAddress.getByName("128.9.8.1"), 100);
|
||||
|
||||
when(incomingRequest.getRemoteAddress()).thenReturn(address);
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener, incomingRequest);
|
||||
|
||||
ElasticsearchSecurityException actual = expectThrows(ElasticsearchSecurityException.class, listener::actionGet);
|
||||
assertThat(actual.getMessage(), containsString("failed to authenticate user [" + principal));
|
||||
}
|
||||
|
||||
@SuppressForbidden(reason = "allow getting localhost")
|
||||
public void testElasticEmptyPasswordAuthenticationSucceedsInSetupModeIfRestRequestComesFromLocalhost() throws Throwable {
|
||||
final User expected = new ElasticUser(true, 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));
|
||||
|
||||
PlainActionFuture<User> listener = new PlainActionFuture<>();
|
||||
|
||||
InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 100);
|
||||
|
||||
when(incomingRequest.getRemoteAddress()).thenReturn(address);
|
||||
when(incomingRequest.getType()).thenReturn(IncomingRequest.RequestType.REST);
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener, incomingRequest);
|
||||
|
||||
User user = listener.actionGet();
|
||||
|
||||
assertEquals(expected, user);
|
||||
assertNotEquals(new ElasticUser(true, false), user);
|
||||
}
|
||||
|
||||
public void testAuthenticationDisabled() throws Throwable {
|
||||
|
@ -151,7 +176,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
final String principal = expected.principal();
|
||||
|
||||
PlainActionFuture<User> listener = new PlainActionFuture<>();
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, DEFAULT_PASSWORD), listener);
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener, mock(IncomingRequest.class));
|
||||
final User authenticated = listener.actionGet();
|
||||
assertNull(authenticated);
|
||||
verifyZeroInteractions(usersStore);
|
||||
|
@ -179,9 +204,9 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
return null;
|
||||
}).when(usersStore).getReservedUserInfo(eq(principal), any(ActionListener.class));
|
||||
|
||||
// test default password
|
||||
// test empty password
|
||||
final PlainActionFuture<User> listener = new PlainActionFuture<>();
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, DEFAULT_PASSWORD), listener);
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener, incomingRequest);
|
||||
ElasticsearchSecurityException expected = expectThrows(ElasticsearchSecurityException.class, listener::actionGet);
|
||||
assertThat(expected.getMessage(), containsString("failed to authenticate user [" + principal));
|
||||
|
||||
|
@ -194,7 +219,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
|
||||
// test new password
|
||||
final PlainActionFuture<User> authListener = new PlainActionFuture<>();
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, newPassword), authListener);
|
||||
reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, newPassword), authListener, incomingRequest);
|
||||
final User authenticated = authListener.actionGet();
|
||||
assertEquals(expectedUser, authenticated);
|
||||
assertThat(expectedUser.enabled(), is(enabled));
|
||||
|
@ -211,7 +236,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
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(true), new KibanaUser(true), new LogstashSystemUser(true));
|
||||
final User expectedUser = randomFrom(new ElasticUser(true, true), new KibanaUser(true), new LogstashSystemUser(true));
|
||||
final String principal = expectedUser.principal();
|
||||
|
||||
PlainActionFuture<User> listener = new PlainActionFuture<>();
|
||||
|
@ -299,7 +324,7 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
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),
|
||||
assertThat(userFuture.actionGet(), containsInAnyOrder(new ElasticUser(true, true), new KibanaUser(true),
|
||||
new LogstashSystemUser(true), new BeatsSystemUser(true)));
|
||||
}
|
||||
|
||||
|
@ -321,19 +346,29 @@ public class ReservedRealmTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testFailedAuthentication() {
|
||||
@SuppressForbidden(reason = "allow getting localhost")
|
||||
public void testFailedAuthentication() throws UnknownHostException {
|
||||
final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore,
|
||||
new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY));
|
||||
InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 100);
|
||||
|
||||
// maybe cache a successful auth
|
||||
if (randomBoolean()) {
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
reservedRealm.authenticate(new UsernamePasswordToken(ElasticUser.NAME, new SecureString("changeme".toCharArray())), future);
|
||||
|
||||
IncomingRequest r = mock(IncomingRequest.class);
|
||||
when(r.getRemoteAddress()).thenReturn(address);
|
||||
when(r.getType()).thenReturn(IncomingRequest.RequestType.REST);
|
||||
reservedRealm.authenticate(new UsernamePasswordToken(ElasticUser.NAME, EMPTY_PASSWORD), future, r);
|
||||
User user = future.actionGet();
|
||||
assertEquals(new ElasticUser(true), user);
|
||||
assertEquals(new ElasticUser(true, true), user);
|
||||
}
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
reservedRealm.authenticate(new UsernamePasswordToken(ElasticUser.NAME, new SecureString("foobar".toCharArray())), future);
|
||||
IncomingRequest r = mock(IncomingRequest.class);
|
||||
when(r.getRemoteAddress()).thenReturn(address);
|
||||
when(r.getType()).thenReturn(IncomingRequest.RequestType.REST);
|
||||
reservedRealm.authenticate(new UsernamePasswordToken(ElasticUser.NAME, new SecureString("foobar".toCharArray())), future, r);
|
||||
ElasticsearchSecurityException e = expectThrows(ElasticsearchSecurityException.class, future::actionGet);
|
||||
assertThat(e.getMessage(), containsString("failed to authenticate"));
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ public class SetupPasswordToolTests extends CommandTestCase {
|
|||
execute("auto", pathHomeParameter, "-b", "true");
|
||||
|
||||
ArgumentCaptor<String> passwordCaptor = ArgumentCaptor.forClass(String.class);
|
||||
SecureString defaultPassword = new SecureString("changeme".toCharArray());
|
||||
SecureString defaultPassword = new SecureString("".toCharArray());
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(httpClient);
|
||||
String elasticUrl = "http://localhost:9200/_xpack/security/user/elastic/_password";
|
||||
|
@ -80,7 +80,7 @@ public class SetupPasswordToolTests extends CommandTestCase {
|
|||
execute("auto", pathHomeParameter, "-u", url, "-b");
|
||||
|
||||
ArgumentCaptor<String> passwordCaptor = ArgumentCaptor.forClass(String.class);
|
||||
SecureString defaultPassword = new SecureString("changeme".toCharArray());
|
||||
SecureString defaultPassword = new SecureString("".toCharArray());
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(httpClient);
|
||||
String elasticUrl = url + "/_xpack/security/user/elastic/_password";
|
||||
|
@ -99,7 +99,7 @@ public class SetupPasswordToolTests extends CommandTestCase {
|
|||
|
||||
execute("interactive", pathHomeParameter);
|
||||
|
||||
SecureString defaultPassword = new SecureString("changeme".toCharArray());
|
||||
SecureString defaultPassword = new SecureString("".toCharArray());
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(httpClient);
|
||||
String elasticUrl = "http://localhost:9200/_xpack/security/user/elastic/_password";
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.common.settings.SecureString;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.support.Hasher;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
|
@ -53,7 +54,7 @@ public class FileRealmTests extends ESTestCase {
|
|||
RealmConfig config = new RealmConfig("file-test", Settings.EMPTY, globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
|
||||
FileRealm realm = new FileRealm(config, userPasswdStore, userRolesStore);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, notNullValue());
|
||||
assertThat(user.principal(), equalTo("user1"));
|
||||
|
@ -71,10 +72,10 @@ public class FileRealmTests extends ESTestCase {
|
|||
when(userRolesStore.roles("user1")).thenReturn(new String[]{"role1", "role2"});
|
||||
FileRealm realm = new FileRealm(config, userPasswdStore, userRolesStore);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class));
|
||||
User user1 = future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class));
|
||||
User user2 = future.actionGet();
|
||||
assertThat(user1, sameInstance(user2));
|
||||
}
|
||||
|
@ -87,32 +88,32 @@ public class FileRealmTests extends ESTestCase {
|
|||
doReturn(new String[] { "role1", "role2" }).when(userRolesStore).roles("user1");
|
||||
FileRealm realm = new FileRealm(config, userPasswdStore, userRolesStore);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class));
|
||||
User user1 = future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class));
|
||||
User user2 = future.actionGet();
|
||||
assertThat(user1, sameInstance(user2));
|
||||
|
||||
userPasswdStore.notifyRefresh();
|
||||
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class));
|
||||
User user3 = future.actionGet();
|
||||
assertThat(user2, not(sameInstance(user3)));
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class));
|
||||
User user4 = future.actionGet();
|
||||
assertThat(user3, sameInstance(user4));
|
||||
|
||||
userRolesStore.notifyRefresh();
|
||||
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class));
|
||||
User user5 = future.actionGet();
|
||||
assertThat(user4, not(sameInstance(user5)));
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class));
|
||||
User user6 = future.actionGet();
|
||||
assertThat(user5, sameInstance(user6));
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.common.io.PathUtilsForTesting;
|
|||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.XPackSettings;
|
||||
import org.elasticsearch.xpack.security.authc.support.Hasher;
|
||||
import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
|
||||
|
@ -64,10 +65,11 @@ public class UsersToolTests extends CommandTestCase {
|
|||
IOUtils.rm(homeDir);
|
||||
confDir = homeDir.resolve("config").resolve(XPackPlugin.NAME);
|
||||
Files.createDirectories(confDir);
|
||||
String defaultPassword = SecuritySettingsSource.TEST_PASSWORD;
|
||||
Files.write(confDir.resolve("users"), Arrays.asList(
|
||||
"existing_user:" + new String(Hasher.BCRYPT.hash(new SecureString("changeme".toCharArray()))),
|
||||
"existing_user2:" + new String(Hasher.BCRYPT.hash(new SecureString("changeme2".toCharArray()))),
|
||||
"existing_user3:" + new String(Hasher.BCRYPT.hash(new SecureString("changeme3".toCharArray())))
|
||||
"existing_user:" + new String(Hasher.BCRYPT.hash(SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING)),
|
||||
"existing_user2:" + new String(Hasher.BCRYPT.hash(new SecureString((defaultPassword + "2").toCharArray()))),
|
||||
"existing_user3:" + new String(Hasher.BCRYPT.hash(new SecureString((defaultPassword + "3").toCharArray())))
|
||||
), StandardCharsets.UTF_8);
|
||||
Files.write(confDir.resolve("users_roles"), Arrays.asList(
|
||||
"test_admin:existing_user,existing_user2",
|
||||
|
@ -268,20 +270,20 @@ public class UsersToolTests extends CommandTestCase {
|
|||
}
|
||||
|
||||
public void testUseraddNoPassword() throws Exception {
|
||||
terminal.addSecretInput("changeme");
|
||||
terminal.addSecretInput("changeme");
|
||||
terminal.addSecretInput(SecuritySettingsSource.TEST_PASSWORD);
|
||||
terminal.addSecretInput(SecuritySettingsSource.TEST_PASSWORD);
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "username");
|
||||
assertUser("username", "changeme");
|
||||
assertUser("username", SecuritySettingsSource.TEST_PASSWORD);
|
||||
}
|
||||
|
||||
public void testUseraddPasswordOption() throws Exception {
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", "changeme");
|
||||
assertUser("username", "changeme");
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", SecuritySettingsSource.TEST_PASSWORD);
|
||||
assertUser("username", SecuritySettingsSource.TEST_PASSWORD);
|
||||
}
|
||||
|
||||
public void testUseraddUserExists() throws Exception {
|
||||
UserException e = expectThrows(UserException.class, () -> {
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "existing_user", "-p", "changeme");
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "existing_user", "-p", SecuritySettingsSource.TEST_PASSWORD);
|
||||
});
|
||||
assertEquals(ExitCodes.CODE_ERROR, e.exitCode);
|
||||
assertEquals("User [existing_user] already exists", e.getMessage());
|
||||
|
@ -290,7 +292,7 @@ public class UsersToolTests extends CommandTestCase {
|
|||
public void testUseraddReservedUser() throws Exception {
|
||||
final String name = randomFrom(ElasticUser.NAME, KibanaUser.NAME);
|
||||
UserException e = expectThrows(UserException.class, () -> {
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, name, "-p", "changeme");
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, name, "-p", SecuritySettingsSource.TEST_PASSWORD);
|
||||
});
|
||||
assertEquals(ExitCodes.DATA_ERROR, e.exitCode);
|
||||
assertEquals("Invalid username [" + name + "]... Username [" + name + "] is reserved and may not be used.", e.getMessage());
|
||||
|
@ -299,7 +301,7 @@ public class UsersToolTests extends CommandTestCase {
|
|||
public void testUseraddNoRoles() throws Exception {
|
||||
Files.delete(confDir.resolve("users_roles"));
|
||||
Files.createFile(confDir.resolve("users_roles"));
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", "changeme");
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", SecuritySettingsSource.TEST_PASSWORD);
|
||||
List<String> lines = Files.readAllLines(confDir.resolve("users_roles"), StandardCharsets.UTF_8);
|
||||
assertTrue(lines.toString(), lines.isEmpty());
|
||||
}
|
||||
|
@ -319,7 +321,7 @@ public class UsersToolTests extends CommandTestCase {
|
|||
|
||||
public void testPasswdUnknownUser() throws Exception {
|
||||
UserException e = expectThrows(UserException.class, () -> {
|
||||
execute("passwd", pathHomeParameter, fileTypeParameter, "unknown", "-p", "changeme");
|
||||
execute("passwd", pathHomeParameter, fileTypeParameter, "unknown", "-p", SecuritySettingsSource.TEST_PASSWORD);
|
||||
});
|
||||
assertEquals(ExitCodes.NO_USER, e.exitCode);
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("User [unknown] doesn't exist"));
|
||||
|
@ -365,7 +367,8 @@ public class UsersToolTests extends CommandTestCase {
|
|||
}
|
||||
|
||||
public void testRolesRemoveLeavesExisting() throws Exception {
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", "changeme", "-r", "test_admin");
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", SecuritySettingsSource.TEST_PASSWORD,
|
||||
"-r", "test_admin");
|
||||
execute("roles", pathHomeParameter, fileTypeParameter, "existing_user", "-r", "test_admin");
|
||||
assertRole("test_admin", "username");
|
||||
}
|
||||
|
@ -407,7 +410,8 @@ public class UsersToolTests extends CommandTestCase {
|
|||
}
|
||||
|
||||
public void testListUnknownRoles() throws Exception {
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", "changeme", "-r", "test_r1,r2,r3");
|
||||
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", SecuritySettingsSource.TEST_PASSWORD,
|
||||
"-r", "test_r1,r2,r3");
|
||||
String output = execute("list", pathHomeParameter, fileTypeParameter, "username");
|
||||
assertTrue(output, output.contains("username"));
|
||||
assertTrue(output, output.contains("r2*,r3*,test_r1"));
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.elasticsearch.common.settings.SecureString;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.ActiveDirectorySessionFactory.DownLevelADAuthenticator;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.ActiveDirectorySessionFactory.UpnADAuthenticator;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
|
@ -53,6 +54,7 @@ import static org.hamcrest.Matchers.is;
|
|||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
@ -138,7 +140,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future);
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, is(notNullValue()));
|
||||
assertThat(user.roles(), arrayContaining(containsString("Avengers")));
|
||||
|
@ -153,7 +155,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
|
||||
// Thor does not have a UPN of form CN=Thor@ad.test.elasticsearch.com
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("CN=Thor", new SecureString(PASSWORD)), future);
|
||||
realm.authenticate(new UsernamePasswordToken("CN=Thor", new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, is(notNullValue()));
|
||||
assertThat(user.roles(), arrayContaining(containsString("Avengers")));
|
||||
|
@ -178,7 +180,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
int count = randomIntBetween(2, 10);
|
||||
for (int i = 0; i < count; i++) {
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future);
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
}
|
||||
|
||||
|
@ -196,7 +198,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
int count = randomIntBetween(2, 10);
|
||||
for (int i = 0; i < count; i++) {
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future);
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
}
|
||||
|
||||
|
@ -214,7 +216,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
int count = randomIntBetween(2, 10);
|
||||
for (int i = 0; i < count; i++) {
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future);
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
}
|
||||
|
||||
|
@ -226,7 +228,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
|
||||
for (int i = 0; i < count; i++) {
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future);
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
}
|
||||
|
||||
|
@ -243,7 +245,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future);
|
||||
realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, is(notNullValue()));
|
||||
assertThat(user.roles(), arrayContaining(equalTo("group_role")));
|
||||
|
@ -259,7 +261,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("CN=Thor", new SecureString(PASSWORD)), future);
|
||||
realm.authenticate(new UsernamePasswordToken("CN=Thor", new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, is(notNullValue()));
|
||||
assertThat(user.roles(), arrayContainingInAnyOrder(equalTo("group_role"), equalTo("user_role")));
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.SecureString;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSearchScope;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.LdapTestCase;
|
||||
|
@ -44,6 +45,7 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
@ -85,7 +87,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
threadPool);
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, notNullValue());
|
||||
assertThat(user.roles(), arrayContaining("HMS Victory"));
|
||||
|
@ -108,7 +110,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService), threadPool);
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, notNullValue());
|
||||
assertThat("For roles " + Arrays.toString(user.roles()), user.roles(), arrayContaining("HMS Victory"));
|
||||
|
@ -131,10 +133,10 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
LdapRealm ldap =
|
||||
new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService), threadPool);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
//verify one and only one session -> caching is working
|
||||
|
@ -154,10 +156,10 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
ldapFactory = spy(ldapFactory);
|
||||
LdapRealm ldap = new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory, roleMapper, threadPool);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
//verify one and only one session -> caching is working
|
||||
|
@ -166,7 +168,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
roleMapper.notifyRefresh();
|
||||
|
||||
future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
//we need to session again
|
||||
|
@ -187,10 +189,10 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
LdapRealm ldap =
|
||||
new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService), threadPool);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
//verify two and only two binds -> caching is disabled
|
||||
|
@ -281,7 +283,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
new DnRoleMapper(LdapRealm.LDAP_TYPE, config, resourceWatcherService), threadPool);
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken("Horatio Hornblower", new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken("Horatio Hornblower", new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, notNullValue());
|
||||
assertThat(user.roles(), arrayContaining("avenger"));
|
||||
|
@ -305,7 +307,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
threadPool);
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future);
|
||||
ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, nullValue());
|
||||
}
|
||||
|
|
|
@ -82,8 +82,8 @@ public class PkiOptionalClientAuthTests extends SecurityIntegTestCase {
|
|||
|
||||
Response response = restClient.performRequest("GET", "_nodes",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.DEFAULT_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()))));
|
||||
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray()))));
|
||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
|
@ -104,7 +105,7 @@ public class PkiRealmTests extends ESTestCase {
|
|||
}).when(roleMapper).resolveRoles(any(UserRoleMapper.UserData.class), any(ActionListener.class));
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(token, future);
|
||||
realm.authenticate(token, future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, is(notNullValue()));
|
||||
assertThat(user.principal(), is("Elasticsearch Test Node"));
|
||||
|
@ -128,7 +129,7 @@ public class PkiRealmTests extends ESTestCase {
|
|||
|
||||
X509AuthenticationToken token = realm.token(threadContext);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(token, future);
|
||||
realm.authenticate(token, future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, is(notNullValue()));
|
||||
assertThat(user.principal(), is("elasticsearch"));
|
||||
|
@ -159,7 +160,7 @@ public class PkiRealmTests extends ESTestCase {
|
|||
|
||||
X509AuthenticationToken token = realm.token(threadContext);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(token, future);
|
||||
realm.authenticate(token, future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, is(notNullValue()));
|
||||
assertThat(user.principal(), is("Elasticsearch Test Node"));
|
||||
|
@ -190,7 +191,7 @@ public class PkiRealmTests extends ESTestCase {
|
|||
|
||||
X509AuthenticationToken token = realm.token(threadContext);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(token, future);
|
||||
realm.authenticate(token, future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, is(nullValue()));
|
||||
}
|
||||
|
|
|
@ -5,11 +5,6 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.PlainActionFuture;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
|
@ -17,11 +12,18 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.security.authc.IncomingRequest;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -31,6 +33,7 @@ import static org.hamcrest.Matchers.is;
|
|||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
||||
|
||||
|
@ -55,8 +58,8 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
RealmConfig config = new RealmConfig("test_realm", settings, globalSettings, new ThreadContext(Settings.EMPTY));
|
||||
CachingUsernamePasswordRealm realm = new CachingUsernamePasswordRealm("test", config) {
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
listener.onResponse(new User("username", new String[] { "r1", "r2", "r3" }));
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
listener.onResponse(new User("username", new String[]{"r1", "r2", "r3"}));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,25 +75,25 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
AlwaysAuthenticateCachingRealm realm = new AlwaysAuthenticateCachingRealm(globalSettings);
|
||||
SecureString pass = new SecureString("pass");
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("a", pass), future);
|
||||
realm.authenticate(new UsernamePasswordToken("a", pass), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("b", pass), future);
|
||||
realm.authenticate(new UsernamePasswordToken("b", pass), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("c", pass), future);
|
||||
realm.authenticate(new UsernamePasswordToken("c", pass), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(3));
|
||||
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("a", pass), future);
|
||||
realm.authenticate(new UsernamePasswordToken("a", pass), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("b", pass), future);
|
||||
realm.authenticate(new UsernamePasswordToken("b", pass), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("c", pass), future);
|
||||
realm.authenticate(new UsernamePasswordToken("c", pass), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(3));
|
||||
|
@ -136,7 +139,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
|
||||
// now authenticate
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("a", new SecureString("pass")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("a", new SecureString("pass")), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(realm.lookupInvocationCounter.intValue(), is(1));
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(1));
|
||||
|
@ -145,7 +148,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
|
||||
// authenticate a different user first
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("b", new SecureString("pass")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("b", new SecureString("pass")), future, mock(IncomingRequest.class));
|
||||
user = future.actionGet();
|
||||
assertThat(realm.lookupInvocationCounter.intValue(), is(1));
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(2));
|
||||
|
@ -167,19 +170,19 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
SecureString pass2 = new SecureString("password");
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken(user, pass1), future);
|
||||
realm.authenticate(new UsernamePasswordToken(user, pass1), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken(user, pass1), future);
|
||||
realm.authenticate(new UsernamePasswordToken(user, pass1), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(1));
|
||||
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken(user, pass2), future);
|
||||
realm.authenticate(new UsernamePasswordToken(user, pass2), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken(user, pass2), future);
|
||||
realm.authenticate(new UsernamePasswordToken(user, pass2), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(2));
|
||||
|
@ -193,21 +196,21 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
SecureString password = new SecureString("password");
|
||||
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken(user, password), future);
|
||||
realm.authenticate(new UsernamePasswordToken(user, password), future, mock(IncomingRequest.class));
|
||||
assertThat(future.actionGet().enabled(), equalTo(false));
|
||||
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(1));
|
||||
|
||||
realm.setUsersEnabled(true);
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken(user, password), future);
|
||||
realm.authenticate(new UsernamePasswordToken(user, password), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
assertThat(future.actionGet().enabled(), equalTo(true));
|
||||
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(2));
|
||||
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken(user, password), future);
|
||||
realm.authenticate(new UsernamePasswordToken(user, password), future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
assertThat(future.actionGet().enabled(), equalTo(true));
|
||||
|
||||
|
@ -226,7 +229,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
|
||||
// authenticate
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(authToken, future);
|
||||
realm.authenticate(authToken, future, mock(IncomingRequest.class));
|
||||
final User user1 = future.actionGet();
|
||||
assertThat(user1.roles(), arrayContaining("testRole1", "testRole2"));
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(1));
|
||||
|
@ -235,7 +238,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
|
||||
// authenticate
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(authToken, future);
|
||||
realm.authenticate(authToken, future, mock(IncomingRequest.class));
|
||||
final User user2 = future.actionGet();
|
||||
assertThat(user2.roles(), arrayContaining("testRole1", "testRole2"));
|
||||
assertThat(user2, not(sameInstance(user1)));
|
||||
|
@ -254,7 +257,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
|
||||
// authenticate
|
||||
realm.authenticate(authToken, future);
|
||||
realm.authenticate(authToken, future, mock(IncomingRequest.class));
|
||||
final long start = System.currentTimeMillis();
|
||||
final User user1 = future.actionGet();
|
||||
assertThat(realm.authInvocationCounter.intValue(), is(1));
|
||||
|
@ -262,19 +265,19 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
// After 100 ms (from the original start time), authenticate (read from cache). We don't care about the result
|
||||
sleepUntil(start + 100);
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(authToken, future);
|
||||
realm.authenticate(authToken, future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
// After 200 ms (from the original start time), authenticate (read from cache). We don't care about the result
|
||||
sleepUntil(start + 200);
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(authToken, future);
|
||||
realm.authenticate(authToken, future, mock(IncomingRequest.class));
|
||||
future.actionGet();
|
||||
|
||||
// After 300 ms (from the original start time), authenticate again. The cache entry should have expired (despite the previous reads)
|
||||
sleepUntil(start + 300);
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(authToken, future);
|
||||
realm.authenticate(authToken, future, mock(IncomingRequest.class));
|
||||
final User user2 = future.actionGet();
|
||||
assertThat(user2, not(sameInstance(user1)));
|
||||
// Due to slow VMs etc, the cache might have expired more than once during the test, but we can accept that.
|
||||
|
@ -292,13 +295,13 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
public void testAuthenticateContract() throws Exception {
|
||||
Realm realm = new FailingAuthenticationRealm(Settings.EMPTY, globalSettings);
|
||||
PlainActionFuture<User> future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user", new SecureString("pass")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user", new SecureString("pass")), future, mock(IncomingRequest.class));
|
||||
User user = future.actionGet();
|
||||
assertThat(user, nullValue());
|
||||
|
||||
realm = new ThrowingAuthenticationRealm(Settings.EMPTY, globalSettings);
|
||||
future = new PlainActionFuture<>();
|
||||
realm.authenticate(new UsernamePasswordToken("user", new SecureString("pass")), future);
|
||||
realm.authenticate(new UsernamePasswordToken("user", new SecureString("pass")), future, mock(IncomingRequest.class));
|
||||
RuntimeException e = expectThrows(RuntimeException.class, future::actionGet);
|
||||
assertThat(e.getMessage(), containsString("whatever exception"));
|
||||
}
|
||||
|
@ -319,17 +322,17 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
|
||||
public void testCacheConcurrency() throws Exception {
|
||||
final String username = "username";
|
||||
final SecureString password = new SecureString("changeme".toCharArray());
|
||||
final SecureString password = SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING;
|
||||
final SecureString randomPassword = new SecureString(randomAlphaOfLength(password.length()).toCharArray());
|
||||
|
||||
final String passwordHash = new String(Hasher.BCRYPT.hash(password));
|
||||
RealmConfig config = new RealmConfig("test_realm", Settings.EMPTY, globalSettings, new ThreadContext(Settings.EMPTY));
|
||||
final CachingUsernamePasswordRealm realm = new CachingUsernamePasswordRealm("test", config) {
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
// do something slow
|
||||
if (BCrypt.checkpw(token.credentials(), passwordHash)) {
|
||||
listener.onResponse(new User(username, new String[] { "r1", "r2", "r3" }));
|
||||
listener.onResponse(new User(username, new String[]{"r1", "r2", "r3"}));
|
||||
} else {
|
||||
listener.onResponse(null);
|
||||
}
|
||||
|
@ -365,7 +368,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
}, (e) -> {
|
||||
logger.error("caught exception", e);
|
||||
fail("unexpected exception");
|
||||
}));
|
||||
}), mock(IncomingRequest.class));
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -389,13 +392,13 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
RealmConfig config = new RealmConfig("test_realm", Settings.EMPTY, globalSettings, new ThreadContext(Settings.EMPTY));
|
||||
final CachingUsernamePasswordRealm realm = new CachingUsernamePasswordRealm("test", config) {
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
listener.onFailure(new UnsupportedOperationException("authenticate should not be called!"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLookupUser(String username, ActionListener<User> listener) {
|
||||
listener.onResponse(new User(username, new String[] { "r1", "r2", "r3" }));
|
||||
listener.onResponse(new User(username, new String[]{"r1", "r2", "r3"}));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -443,7 +446,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
listener.onResponse(null);
|
||||
}
|
||||
|
||||
|
@ -460,7 +463,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
listener.onFailure(new RuntimeException("whatever exception"));
|
||||
}
|
||||
|
||||
|
@ -490,16 +493,16 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
authInvocationCounter.incrementAndGet();
|
||||
final User user = new User(token.principal(), new String[] { "testRole1", "testRole2" }, null, null, emptyMap(), usersEnabled);
|
||||
final User user = new User(token.principal(), new String[]{"testRole1", "testRole2"}, null, null, emptyMap(), usersEnabled);
|
||||
listener.onResponse(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLookupUser(String username, ActionListener<User> listener) {
|
||||
lookupInvocationCounter.incrementAndGet();
|
||||
listener.onResponse(new User(username, new String[] { "lookupRole1", "lookupRole2" }));
|
||||
listener.onResponse(new User(username, new String[]{"lookupRole1", "lookupRole2"}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,9 +516,9 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
|
||||
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener, IncomingRequest incomingRequest) {
|
||||
authInvocationCounter.incrementAndGet();
|
||||
listener.onResponse(new User(token.principal(), new String[] { "testRole1", "testRole2" }));
|
||||
listener.onResponse(new User(token.principal(), new String[]{"testRole1", "testRole2"}));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -119,6 +119,7 @@ import org.elasticsearch.xpack.security.authz.permission.Role;
|
|||
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
|
||||
import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
|
||||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||
import org.elasticsearch.xpack.security.user.ElasticUser;
|
||||
import org.elasticsearch.xpack.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
import org.elasticsearch.xpack.security.user.XPackUser;
|
||||
|
@ -348,6 +349,30 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testElasticUserOnlyAuthorizedForChangePasswordRequestsInSetupMode() {
|
||||
final User user = new ElasticUser(true, true);
|
||||
final ChangePasswordRequest changePasswordrequest = new ChangePasswordRequestBuilder(mock(Client.class))
|
||||
.username(user.principal()).request();
|
||||
|
||||
authorize(createAuthentication(user), ChangePasswordAction.NAME, changePasswordrequest);
|
||||
|
||||
verify(auditTrail).accessGranted(user, ChangePasswordAction.NAME, changePasswordrequest);
|
||||
|
||||
Tuple<String, TransportRequest> request = randomCompositeRequest();
|
||||
assertThrowsAuthorizationException(() -> authorize(createAuthentication(user), request.v1(), request.v2()),
|
||||
request.v1(), "elastic");
|
||||
|
||||
verify(auditTrail).accessDenied(user, request.v1(), request.v2());
|
||||
}
|
||||
|
||||
public void testElasticUserAuthorizedForNonChangePasswordRequestsWhenNotInSetupMode() {
|
||||
final User user = new ElasticUser(true, false);
|
||||
Tuple<String, TransportRequest> request = randomCompositeRequest();
|
||||
authorize(createAuthentication(user), request.v1(), request.v2());
|
||||
|
||||
verify(auditTrail).accessGranted(user, request.v1(), request.v2());
|
||||
}
|
||||
|
||||
public void testSearchAgainstEmptyCluster() {
|
||||
User user = new User("test user", "a_all");
|
||||
roleMap.put("a_all", new RoleDescriptor("a_role", null,
|
||||
|
|
|
@ -37,7 +37,7 @@ public class ReadActionsTests extends SecurityIntegTestCase {
|
|||
|
||||
@Override
|
||||
protected String configRoles() {
|
||||
return SecuritySettingsSource.DEFAULT_ROLE + ":\n" +
|
||||
return SecuritySettingsSource.TEST_ROLE + ":\n" +
|
||||
" cluster: [ ALL ]\n" +
|
||||
" indices:\n" +
|
||||
" - names: '*'\n" +
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.common.unit.TimeValue;
|
|||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.search.SearchContextMissingException;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
import org.junit.After;
|
||||
|
@ -33,7 +34,7 @@ public class SecurityScrollTests extends SecurityIntegTestCase {
|
|||
securityClient().preparePutRole("scrollable")
|
||||
.addIndices(new String[] { randomAlphaOfLengthBetween(4, 12) }, new String[] { "read" }, null, null, null)
|
||||
.get();
|
||||
securityClient().preparePutUser("other", "changeme".toCharArray(), "scrollable").get();
|
||||
securityClient().preparePutUser("other", SecuritySettingsSource.TEST_PASSWORD.toCharArray(), "scrollable").get();
|
||||
|
||||
final int numDocs = randomIntBetween(4, 16);
|
||||
IndexRequestBuilder[] docs = new IndexRequestBuilder[numDocs];
|
||||
|
@ -60,7 +61,7 @@ public class SecurityScrollTests extends SecurityIntegTestCase {
|
|||
SearchPhaseExecutionException e = expectThrows(SearchPhaseExecutionException.class, () ->
|
||||
client()
|
||||
.filterWithHeader(Collections.singletonMap("Authorization",
|
||||
UsernamePasswordToken.basicAuthHeaderValue("other", new SecureString("changeme".toCharArray()))))
|
||||
UsernamePasswordToken.basicAuthHeaderValue("other", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING)))
|
||||
.prepareSearchScroll(scrollId)
|
||||
.get());
|
||||
for (ShardSearchFailure failure : e.shardFailures()) {
|
||||
|
|
|
@ -29,7 +29,7 @@ public class WriteActionsTests extends SecurityIntegTestCase {
|
|||
|
||||
@Override
|
||||
protected String configRoles() {
|
||||
return SecuritySettingsSource.DEFAULT_ROLE + ":\n" +
|
||||
return SecuritySettingsSource.TEST_ROLE + ":\n" +
|
||||
" cluster: [ ALL ]\n" +
|
||||
" indices:\n" +
|
||||
" - names: 'missing'\n" +
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.elasticsearch.rest.RestHandler;
|
|||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||
import org.elasticsearch.xpack.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.security.authc.Authentication.RealmRef;
|
||||
|
@ -112,7 +113,8 @@ public class SecurityRestFilterTests extends ESTestCase {
|
|||
|
||||
public void testProcessFiltersBodyCorrectly() throws Exception {
|
||||
FakeRestRequest restRequest = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY)
|
||||
.withContent(new BytesArray("{\"password\": \"changeme\", \"foo\": \"bar\"}"), XContentType.JSON).build();
|
||||
.withContent(new BytesArray("{\"password\": \"" + SecuritySettingsSource.TEST_PASSWORD + "\", \"foo\": \"bar\"}"),
|
||||
XContentType.JSON).build();
|
||||
when(channel.request()).thenReturn(restRequest);
|
||||
SetOnce<RestRequest> handlerRequest = new SetOnce<>();
|
||||
restHandler = new FilteredRestHandler() {
|
||||
|
@ -143,7 +145,7 @@ public class SecurityRestFilterTests extends ESTestCase {
|
|||
Map<String, Object> original = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, handlerRequest.get()
|
||||
.content()).map();
|
||||
assertEquals(2, original.size());
|
||||
assertEquals("changeme", original.get("password"));
|
||||
assertEquals(SecuritySettingsSource.TEST_PASSWORD, original.get("password"));
|
||||
assertEquals("bar", original.get("foo"));
|
||||
|
||||
assertNotEquals(restRequest, authcServiceRequest.get());
|
||||
|
|
|
@ -42,7 +42,7 @@ public class RestAuthenticateActionTests extends SecurityIntegTestCase {
|
|||
|
||||
if (anonymousEnabled) {
|
||||
builder.put(AnonymousUser.USERNAME_SETTING.getKey(), "anon")
|
||||
.putArray(AnonymousUser.ROLES_SETTING.getKey(), SecuritySettingsSource.DEFAULT_ROLE, "foo")
|
||||
.putArray(AnonymousUser.ROLES_SETTING.getKey(), SecuritySettingsSource.TEST_ROLE, "foo")
|
||||
.put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false);
|
||||
}
|
||||
return builder.build();
|
||||
|
@ -50,15 +50,15 @@ public class RestAuthenticateActionTests extends SecurityIntegTestCase {
|
|||
|
||||
public void testAuthenticateApi() throws Exception {
|
||||
Response response = getRestClient().performRequest("GET", "/_xpack/security/_authenticate",
|
||||
new BasicHeader("Authorization", basicAuthHeaderValue(SecuritySettingsSource.DEFAULT_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()))));
|
||||
new BasicHeader("Authorization", basicAuthHeaderValue(SecuritySettingsSource.TEST_USER_NAME,
|
||||
new SecureString(SecuritySettingsSource.TEST_PASSWORD.toCharArray()))));
|
||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||
ObjectPath objectPath = ObjectPath.createFromResponse(response);
|
||||
assertThat(objectPath.evaluate("username").toString(), equalTo(SecuritySettingsSource.DEFAULT_USER_NAME));
|
||||
assertThat(objectPath.evaluate("username").toString(), equalTo(SecuritySettingsSource.TEST_USER_NAME));
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> roles = (List<String>) objectPath.evaluate("roles");
|
||||
assertThat(roles.size(), is(1));
|
||||
assertThat(roles, contains(SecuritySettingsSource.DEFAULT_ROLE));
|
||||
assertThat(roles, contains(SecuritySettingsSource.TEST_ROLE));
|
||||
}
|
||||
|
||||
public void testAuthenticateApiWithoutAuthentication() throws Exception {
|
||||
|
@ -71,7 +71,7 @@ public class RestAuthenticateActionTests extends SecurityIntegTestCase {
|
|||
@SuppressWarnings("unchecked")
|
||||
List<String> roles = (List<String>) objectPath.evaluate("roles");
|
||||
assertThat(roles.size(), is(2));
|
||||
assertThat(roles, contains(SecuritySettingsSource.DEFAULT_ROLE, "foo"));
|
||||
assertThat(roles, contains(SecuritySettingsSource.TEST_ROLE, "foo"));
|
||||
} else {
|
||||
fail("request should have failed");
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ package org.elasticsearch.xpack.security.rest.action.oauth2;
|
|||
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
|
@ -18,6 +17,7 @@ import org.elasticsearch.rest.RestChannel;
|
|||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||
import org.elasticsearch.xpack.security.action.token.CreateTokenRequest;
|
||||
import org.elasticsearch.xpack.security.action.token.CreateTokenResponse;
|
||||
|
@ -85,7 +85,7 @@ public class RestGetTokenActionTests extends ESTestCase {
|
|||
final String request = "{" +
|
||||
"\"grant_type\": \"password\"," +
|
||||
"\"username\": \"user1\"," +
|
||||
"\"password\": \"changeme\"," +
|
||||
"\"password\": \"" + SecuritySettingsSource.TEST_PASSWORD + "\"," +
|
||||
"\"scope\": \"FULL\"" +
|
||||
"}";
|
||||
try (XContentParser parser = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, request)) {
|
||||
|
@ -93,7 +93,7 @@ public class RestGetTokenActionTests extends ESTestCase {
|
|||
assertEquals("password", createTokenRequest.getGrantType());
|
||||
assertEquals("user1", createTokenRequest.getUsername());
|
||||
assertEquals("FULL", createTokenRequest.getScope());
|
||||
assertTrue(new SecureString("changeme".toCharArray()).equals(createTokenRequest.getPassword()));
|
||||
assertTrue(SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING.equals(createTokenRequest.getPassword()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ public class ServerTransportFilterIntegrationTests extends SecurityIntegTestCase
|
|||
.put("xpack.security.authc.realms.file.type", FileRealm.TYPE)
|
||||
.put("xpack.security.authc.realms.file.order", 0)
|
||||
.put("node.name", "my-test-node")
|
||||
.put(Security.USER_SETTING.getKey(), "test_user:changeme")
|
||||
.put(Security.USER_SETTING.getKey(), "test_user:" + SecuritySettingsSource.TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("discovery.zen.ping.unicast.hosts", unicastHost)
|
||||
.put("discovery.zen.minimum_master_nodes",
|
||||
|
|
|
@ -76,7 +76,8 @@ public class DNSOnlyHostnameVerificationTests extends SecurityIntegTestCase {
|
|||
|
||||
keystore = KeyStore.getInstance("JKS");
|
||||
keystore.load(null, null);
|
||||
keystore.setKeyEntry("private key", keyPair.getPrivate(), "changeme".toCharArray(), new Certificate[]{cert});
|
||||
keystore.setKeyEntry("private key", keyPair.getPrivate(), SecuritySettingsSource.TEST_PASSWORD.toCharArray(),
|
||||
new Certificate[]{cert});
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
@ -98,15 +99,15 @@ public class DNSOnlyHostnameVerificationTests extends SecurityIntegTestCase {
|
|||
.put("transport.host", hostName);
|
||||
Path keystorePath = nodeConfigPath(nodeOrdinal).resolve("keystore.jks");
|
||||
try (OutputStream os = Files.newOutputStream(keystorePath)) {
|
||||
keystore.store(os, "changeme".toCharArray());
|
||||
keystore.store(os, SecuritySettingsSource.TEST_PASSWORD.toCharArray());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
|
||||
throw new ElasticsearchException("unable to write keystore for node", e);
|
||||
}
|
||||
SecuritySettingsSource.addSecureSettings(builder, secureSettings -> {
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", "changeme");
|
||||
secureSettings.setString("xpack.ssl.truststore.secure_password", "changeme");
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", SecuritySettingsSource.TEST_PASSWORD);
|
||||
secureSettings.setString("xpack.ssl.truststore.secure_password", SecuritySettingsSource.TEST_PASSWORD);
|
||||
});
|
||||
builder.put("xpack.ssl.keystore.path", keystorePath.toAbsolutePath())
|
||||
.put("xpack.ssl.truststore.path", keystorePath.toAbsolutePath());
|
||||
|
@ -127,15 +128,15 @@ public class DNSOnlyHostnameVerificationTests extends SecurityIntegTestCase {
|
|||
.put(defaultSettings.filter((s) -> s.startsWith("xpack.ssl.") == false));
|
||||
Path path = createTempDir().resolve("keystore.jks");
|
||||
try (OutputStream os = Files.newOutputStream(path)) {
|
||||
keystore.store(os, "changeme".toCharArray());
|
||||
keystore.store(os, SecuritySettingsSource.TEST_PASSWORD.toCharArray());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
|
||||
throw new ElasticsearchException("unable to write keystore for node", e);
|
||||
}
|
||||
SecuritySettingsSource.addSecureSettings(builder, secureSettings -> {
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", "changeme");
|
||||
secureSettings.setString("xpack.ssl.truststore.secure_password", "changeme");
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", SecuritySettingsSource.TEST_PASSWORD);
|
||||
secureSettings.setString("xpack.ssl.truststore.secure_password", SecuritySettingsSource.TEST_PASSWORD);
|
||||
});
|
||||
builder.put("xpack.ssl.keystore.path", path.toAbsolutePath())
|
||||
.put("xpack.ssl.truststore.path", path.toAbsolutePath());
|
||||
|
|
|
@ -9,19 +9,19 @@ import org.elasticsearch.client.transport.NoNodeAvailableException;
|
|||
import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.ssl.SSLClientAuth;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.xpack.TestXPackTransportClient;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.ssl.SSLClientAuth;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.elasticsearch.test.SecuritySettingsSource.DEFAULT_PASSWORD;
|
||||
import static org.elasticsearch.test.SecuritySettingsSource.DEFAULT_USER_NAME;
|
||||
import static org.elasticsearch.test.SecuritySettingsSource.TEST_PASSWORD;
|
||||
import static org.elasticsearch.test.SecuritySettingsSource.TEST_USER_NAME;
|
||||
import static org.elasticsearch.test.SecuritySettingsSource.addSSLSettingsForStore;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -189,7 +189,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
|||
*/
|
||||
public void testThatTransportClientCannotConnectToDefaultProfile() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.build();
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
|
@ -207,7 +207,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
|||
*/
|
||||
public void testThatTransportClientCannotConnectToClientProfile() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.build();
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
|
@ -225,7 +225,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
|||
*/
|
||||
public void testThatTransportClientCannotConnectToNoClientAuthProfile() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.build();
|
||||
try (TransportClient transportClient = new TestXPackTransportClient(settings)) {
|
||||
|
@ -245,7 +245,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
|||
*/
|
||||
public void testThatTransportClientWithOnlyTruststoreCanConnectToNoClientAuthProfile() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("xpack.ssl.truststore.path",
|
||||
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/truststore-testnode-only.jks"))
|
||||
|
@ -266,7 +266,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
|||
*/
|
||||
public void testThatTransportClientWithOnlyTruststoreCannotConnectToClientProfile() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("xpack.ssl.client_authentication", SSLClientAuth.REQUIRED)
|
||||
.put("xpack.ssl.truststore.path",
|
||||
|
@ -290,7 +290,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
|||
*/
|
||||
public void testThatTransportClientWithOnlyTruststoreCannotConnectToDefaultProfile() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("xpack.ssl.client_authentication", SSLClientAuth.REQUIRED)
|
||||
.put("xpack.ssl.truststore.path",
|
||||
|
@ -313,7 +313,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
|||
*/
|
||||
public void testThatSSLTransportClientWithNoTruststoreCannotConnectToDefaultProfile() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("xpack.ssl.client_authentication", SSLClientAuth.REQUIRED)
|
||||
.build();
|
||||
|
@ -333,7 +333,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
|||
*/
|
||||
public void testThatSSLTransportClientWithNoTruststoreCannotConnectToClientProfile() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("xpack.ssl.client_authentication", SSLClientAuth.REQUIRED)
|
||||
.build();
|
||||
|
@ -353,7 +353,7 @@ public class SslMultiPortTests extends SecurityIntegTestCase {
|
|||
*/
|
||||
public void testThatSSLTransportClientWithNoTruststoreCannotConnectToNoClientAuthProfile() throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put(Security.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("xpack.ssl.client_authentication", SSLClientAuth.REQUIRED)
|
||||
.build();
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.common.network.NetworkAddress;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.ssl.CertificateTool.CAInfo;
|
||||
import org.elasticsearch.xpack.ssl.CertificateTool.CertificateInformation;
|
||||
import org.elasticsearch.xpack.ssl.CertificateTool.Name;
|
||||
|
@ -249,7 +250,7 @@ public class CertificateToolTests extends ESTestCase {
|
|||
X509Certificate caCert = CertUtils.generateCACertificate(new X500Principal("CN=test ca"), keyPair, days);
|
||||
|
||||
final boolean generatedCa = randomBoolean();
|
||||
final char[] keyPassword = randomBoolean() ? "changeme".toCharArray() : null;
|
||||
final char[] keyPassword = randomBoolean() ? SecuritySettingsSource.TEST_PASSWORD.toCharArray() : null;
|
||||
assertFalse(Files.exists(outputFile));
|
||||
CAInfo caInfo = new CAInfo(caCert, keyPair.getPrivate(), generatedCa, keyPassword);
|
||||
CertificateTool.generateAndWriteSignedCertificates(outputFile, certInfos, caInfo, keysize, days);
|
||||
|
@ -289,7 +290,8 @@ public class CertificateToolTests extends ESTestCase {
|
|||
}
|
||||
|
||||
try (Reader reader = Files.newBufferedReader(zipRoot.resolve("ca").resolve("ca.key"))) {
|
||||
PrivateKey privateKey = CertUtils.readPrivateKey(reader, () -> keyPassword != null ? "changeme".toCharArray() : null);
|
||||
PrivateKey privateKey = CertUtils.readPrivateKey(reader, () -> keyPassword != null ?
|
||||
SecuritySettingsSource.TEST_PASSWORD.toCharArray() : null);
|
||||
assertEquals(caInfo.privateKey, privateKey);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -94,13 +94,14 @@ public class SSLReloadIntegTests extends SecurityIntegTestCase {
|
|||
X509Certificate certificate = getCertificate(keyPair);
|
||||
KeyStore keyStore = KeyStore.getInstance("jks");
|
||||
keyStore.load(null, null);
|
||||
keyStore.setKeyEntry("key", keyPair.getPrivate(), "changeme".toCharArray(), new Certificate[] { certificate });
|
||||
keyStore.setKeyEntry("key", keyPair.getPrivate(), SecuritySettingsSource.TEST_PASSWORD.toCharArray(),
|
||||
new Certificate[] { certificate });
|
||||
Path keystorePath = createTempDir().resolve("newcert.jks");
|
||||
try (OutputStream out = Files.newOutputStream(keystorePath)) {
|
||||
keyStore.store(out, "changeme".toCharArray());
|
||||
keyStore.store(out, SecuritySettingsSource.TEST_PASSWORD.toCharArray());
|
||||
}
|
||||
MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", "changeme");
|
||||
secureSettings.setString("xpack.ssl.keystore.secure_password", SecuritySettingsSource.TEST_PASSWORD);
|
||||
secureSettings.setString("xpack.ssl.truststore.secure_password", "testnode");
|
||||
Settings settings = Settings.builder()
|
||||
.put("path.home", createTempDir())
|
||||
|
|
|
@ -8,8 +8,11 @@ package org.elasticsearch.xpack.test.rest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.client.ResponseException;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
|
@ -17,11 +20,15 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth;
|
||||
import org.elasticsearch.xpack.ml.MachineLearningTemplateRegistry;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
|
@ -31,7 +38,9 @@ import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordTok
|
|||
public abstract class XPackRestTestCase extends ESClientYamlSuiteTestCase {
|
||||
|
||||
private static final String BASIC_AUTH_VALUE =
|
||||
basicAuthHeaderValue("elastic", new SecureString("changeme".toCharArray()));
|
||||
basicAuthHeaderValue("elastic", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
|
||||
private final SetOnce<Integer> oneAllowed401 = new SetOnce<>();
|
||||
|
||||
public XPackRestTestCase(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
|
@ -49,6 +58,26 @@ public abstract class XPackRestTestCase extends ESClientYamlSuiteTestCase {
|
|||
.build();
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void setPasswords() throws IOException {
|
||||
BasicHeader authHeader = new BasicHeader("Authorization",
|
||||
basicAuthHeaderValue("elastic", new SecureString("".toCharArray())));
|
||||
String elasticUserPayload = "{\"password\" : \"" + SecuritySettingsSource.TEST_PASSWORD + "\"}";
|
||||
try {
|
||||
client().performRequest("put", "_xpack/security/user/elastic/_password", Collections.emptyMap(),
|
||||
new StringEntity(elasticUserPayload, ContentType.APPLICATION_JSON), authHeader);
|
||||
} catch (ResponseException e) {
|
||||
// The password might have already been set by the build.gradle file. So we ignore unsuccessful attempts
|
||||
// due to failed authentication
|
||||
if (e.getResponse().getStatusLine().getStatusCode() != 401) {
|
||||
throw e;
|
||||
} else {
|
||||
oneAllowed401.set(e.getResponse().getStatusLine().getStatusCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the Machine Learning templates to be created by {@link MachineLearningTemplateRegistry}.
|
||||
*/
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.http.HttpServerTransport;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.test.http.MockResponse;
|
||||
import org.elasticsearch.test.http.MockWebServer;
|
||||
import org.elasticsearch.xpack.common.http.HttpMethod;
|
||||
|
@ -146,7 +147,7 @@ public class WebhookIntegrationTests extends AbstractWatcherIntegrationTestCase
|
|||
HttpRequestTemplate.Builder builder = HttpRequestTemplate.builder(host, publishAddress.getPort())
|
||||
.path(new TextTemplate("/%3Clogstash-%7Bnow%2Fd%7D%3E/log/1"))
|
||||
.body(new TextTemplate("{\"foo\":\"bar\"}"))
|
||||
.auth(new BasicAuth("test", "changeme".toCharArray()))
|
||||
.auth(new BasicAuth("test", SecuritySettingsSource.TEST_PASSWORD.toCharArray()))
|
||||
.putHeader("Content-Type", new TextTemplate("application/json"))
|
||||
.method(HttpMethod.PUT);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.common.http.HttpRequestTemplate;
|
||||
import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth;
|
||||
import org.elasticsearch.xpack.watcher.condition.AlwaysCondition;
|
||||
|
@ -143,7 +144,7 @@ public class ChainInputTests extends ESTestCase {
|
|||
HttpInput.Builder httpInputBuilder = httpInput(HttpRequestTemplate.builder("theHost", 1234)
|
||||
.path("/index/_search")
|
||||
.body(jsonBuilder().startObject().field("size", 1).endObject().string())
|
||||
.auth(new BasicAuth("test", "changeme".toCharArray())));
|
||||
.auth(new BasicAuth("test", SecuritySettingsSource.TEST_PASSWORD.toCharArray())));
|
||||
|
||||
ChainInput.Builder chainedInputBuilder = chainInput()
|
||||
.add("foo", httpInputBuilder)
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.transport.Netty4Plugin;
|
||||
import org.elasticsearch.xpack.common.http.HttpRequestTemplate;
|
||||
import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth;
|
||||
|
@ -61,7 +62,7 @@ public class ChainIntegrationTests extends AbstractWatcherIntegrationTestCase {
|
|||
HttpInput.Builder httpInputBuilder = httpInput(HttpRequestTemplate.builder(address.getHostString(), address.getPort())
|
||||
.path("/" + index + "/_search")
|
||||
.body(jsonBuilder().startObject().field("size", 1).endObject().string())
|
||||
.auth(securityEnabled() ? new BasicAuth("test", "changeme".toCharArray()) : null));
|
||||
.auth(securityEnabled() ? new BasicAuth("test", SecuritySettingsSource.TEST_PASSWORD.toCharArray()) : null));
|
||||
|
||||
ChainInput.Builder chainedInputBuilder = chainInput()
|
||||
.add("first", simpleInput("url", "/" + index + "/_search"))
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||
import org.elasticsearch.transport.Netty4Plugin;
|
||||
import org.elasticsearch.xpack.common.http.HttpRequestTemplate;
|
||||
|
@ -77,7 +78,8 @@ public class HttpInputIntegrationTests extends AbstractWatcherIntegrationTestCas
|
|||
.path("/index/_search")
|
||||
.body(jsonBuilder().startObject().field("size", 1).endObject().string())
|
||||
.putHeader("Content-Type", new TextTemplate("application/json"))
|
||||
.auth(securityEnabled() ? new BasicAuth("test", "changeme".toCharArray()) : null)))
|
||||
.auth(securityEnabled() ? new BasicAuth("test", SecuritySettingsSource.TEST_PASSWORD.toCharArray())
|
||||
: null)))
|
||||
.condition(new CompareCondition("ctx.payload.hits.total", CompareCondition.Op.EQ, 1L))
|
||||
.addAction("_id", loggingAction("anything")))
|
||||
.get();
|
||||
|
@ -94,7 +96,8 @@ public class HttpInputIntegrationTests extends AbstractWatcherIntegrationTestCas
|
|||
.trigger(schedule(interval("1s")))
|
||||
.input(httpInput(HttpRequestTemplate.builder(address.getHostString(), address.getPort())
|
||||
.path("/_cluster/stats")
|
||||
.auth(securityEnabled() ? new BasicAuth("test", "changeme".toCharArray()) : null)))
|
||||
.auth(securityEnabled() ? new BasicAuth("test", SecuritySettingsSource.TEST_PASSWORD.toCharArray())
|
||||
: null)))
|
||||
.condition(new CompareCondition("ctx.payload.nodes.count.total", CompareCondition.Op.GTE, 1L))
|
||||
.addAction("_id", loggingAction("anything")))
|
||||
.get();
|
||||
|
@ -120,7 +123,7 @@ public class HttpInputIntegrationTests extends AbstractWatcherIntegrationTestCas
|
|||
.path(new TextTemplate("/idx/_search"))
|
||||
.body(body.string());
|
||||
if (securityEnabled()) {
|
||||
requestBuilder.auth(new BasicAuth("test", "changeme".toCharArray()));
|
||||
requestBuilder.auth(new BasicAuth("test", SecuritySettingsSource.TEST_PASSWORD.toCharArray()));
|
||||
}
|
||||
|
||||
watcherClient.preparePutWatch("_name1")
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.watcher.security;
|
||||
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.watcher.WatcherState;
|
||||
import org.elasticsearch.xpack.watcher.client.WatcherClient;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
|
@ -40,7 +40,7 @@ public class BasicSecurityTests extends AbstractWatcherIntegrationTestCase {
|
|||
}
|
||||
|
||||
public void testNoAuthorization() throws Exception {
|
||||
String basicAuth = basicAuthHeaderValue("transport_client", new SecureString("changeme".toCharArray()));
|
||||
String basicAuth = basicAuthHeaderValue("transport_client", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
WatcherClient watcherClient = watcherClient().filterWithHeader(Collections.singletonMap(BASIC_AUTH_HEADER, basicAuth));
|
||||
Exception e = expectThrows(Exception.class, () -> watcherClient.prepareWatcherStats().get());
|
||||
assertThat(e.getMessage(), equalTo("action [cluster:monitor/xpack/watcher/stats] is unauthorized for user [transport_client]"));
|
||||
|
@ -48,7 +48,7 @@ public class BasicSecurityTests extends AbstractWatcherIntegrationTestCase {
|
|||
|
||||
public void testWatcherMonitorRole() throws Exception {
|
||||
// stats and get watch apis require at least monitor role:
|
||||
String token = basicAuthHeaderValue("test", new SecureString("changeme".toCharArray()));
|
||||
String token = basicAuthHeaderValue("test", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
try {
|
||||
watcherClient().filterWithHeader(Collections.singletonMap("Authorization", token)).prepareWatcherStats()
|
||||
.get();
|
||||
|
@ -66,7 +66,7 @@ public class BasicSecurityTests extends AbstractWatcherIntegrationTestCase {
|
|||
}
|
||||
|
||||
// stats and get watch are allowed by role monitor:
|
||||
token = basicAuthHeaderValue("monitor", new SecureString("changeme".toCharArray()));
|
||||
token = basicAuthHeaderValue("monitor", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
WatcherStatsResponse statsResponse = watcherClient().filterWithHeader(Collections.singletonMap("Authorization", token))
|
||||
.prepareWatcherStats().get();
|
||||
boolean watcherStarted = statsResponse.getNodes().stream().anyMatch(node -> node.getWatcherState() == WatcherState.STARTED);
|
||||
|
@ -88,7 +88,7 @@ public class BasicSecurityTests extends AbstractWatcherIntegrationTestCase {
|
|||
|
||||
public void testWatcherAdminRole() throws Exception {
|
||||
// put, execute and delete watch apis requires watcher admin role:
|
||||
String token = basicAuthHeaderValue("test", new SecureString("changeme".toCharArray()));
|
||||
String token = basicAuthHeaderValue("test", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
try {
|
||||
watcherClient().filterWithHeader(Collections.singletonMap("Authorization", token)).preparePutWatch("_id")
|
||||
.setSource(watchBuilder().trigger(schedule(interval(5, IntervalSchedule.Interval.Unit.SECONDS))))
|
||||
|
@ -117,7 +117,7 @@ public class BasicSecurityTests extends AbstractWatcherIntegrationTestCase {
|
|||
}
|
||||
|
||||
// put, execute and delete watch apis are allowed by role admin:
|
||||
token = basicAuthHeaderValue("admin", new SecureString("changeme".toCharArray()));
|
||||
token = basicAuthHeaderValue("admin", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
PutWatchResponse putWatchResponse = watcherClient().filterWithHeader(Collections.singletonMap("Authorization", token))
|
||||
.preparePutWatch("_id")
|
||||
.setSource(watchBuilder().trigger(schedule(interval(5, IntervalSchedule.Interval.Unit.SECONDS))))
|
||||
|
@ -134,7 +134,7 @@ public class BasicSecurityTests extends AbstractWatcherIntegrationTestCase {
|
|||
assertThat(deleteWatchResponse.isFound(), is(true));
|
||||
|
||||
// stats and get watch are also allowed by role monitor:
|
||||
token = basicAuthHeaderValue("admin", new SecureString("changeme".toCharArray()));
|
||||
token = basicAuthHeaderValue("admin",SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING);
|
||||
WatcherStatsResponse statsResponse = watcherClient().filterWithHeader(Collections.singletonMap("Authorization", token))
|
||||
.prepareWatcherStats()
|
||||
.get();
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
|
|||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.test.InternalTestCluster;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.test.TestCluster;
|
||||
import org.elasticsearch.test.disruption.ServiceDisruptionScheme;
|
||||
import org.elasticsearch.test.store.MockFSIndexStore;
|
||||
|
@ -293,7 +294,7 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
|
|||
|
||||
return Settings.builder()
|
||||
.put("client.transport.sniff", false)
|
||||
.put(Security.USER_SETTING.getKey(), "admin:changeme")
|
||||
.put(Security.USER_SETTING.getKey(), "admin:" + SecuritySettingsSource.TEST_PASSWORD)
|
||||
.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4)
|
||||
.put(NetworkModule.HTTP_TYPE_KEY, Security.NAME4)
|
||||
.build();
|
||||
|
@ -686,7 +687,7 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
|
|||
public static class SecuritySettings {
|
||||
|
||||
public static final String TEST_USERNAME = "test";
|
||||
public static final String TEST_PASSWORD = "changeme";
|
||||
public static final String TEST_PASSWORD = SecuritySettingsSource.TEST_PASSWORD;
|
||||
private static final String TEST_PASSWORD_HASHED = new String(Hasher.BCRYPT.hash(new SecureString(TEST_PASSWORD.toCharArray())));
|
||||
|
||||
static boolean auditLogsEnabled = SystemPropertyUtil.getBoolean("tests.audit_logs", true);
|
||||
|
|
|
@ -1 +1 @@
|
|||
test_user:{plain}changeme
|
||||
test_user:{plain}x-pack-test-password
|
|
@ -12,7 +12,7 @@ setup:
|
|||
username: "authenticate_user"
|
||||
body: >
|
||||
{
|
||||
"password" : "changeme",
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "superuser" ],
|
||||
"full_name" : "Authenticate User"
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ teardown:
|
|||
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic YXV0aGVudGljYXRlX3VzZXI6Y2hhbmdlbWU="
|
||||
Authorization: "Basic YXV0aGVudGljYXRlX3VzZXI6eC1wYWNrLXRlc3QtcGFzc3dvcmQ="
|
||||
xpack.security.authenticate: {}
|
||||
|
||||
- match: { username: "authenticate_user" }
|
||||
|
|
|
@ -39,7 +39,7 @@ setup:
|
|||
username: "full"
|
||||
body: >
|
||||
{
|
||||
"password" : "changeme",
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "readall" ],
|
||||
"full_name" : "user who can read all data"
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ setup:
|
|||
username: "limited"
|
||||
body: >
|
||||
{
|
||||
"password" : "changeme",
|
||||
"password" : "x-pack-test-password",
|
||||
"roles" : [ "limitread" ],
|
||||
"full_name" : "user who can read some data"
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ teardown:
|
|||
- '{"marker": "test_2", "location.city": "ams"}'
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic ZnVsbDpjaGFuZ2VtZQ==" } # full - user
|
||||
headers: { Authorization: "Basic ZnVsbDp4LXBhY2stdGVzdC1wYXNzd29yZA==" } # full - user
|
||||
search:
|
||||
index: the_alias
|
||||
size: 0
|
||||
|
@ -126,7 +126,7 @@ teardown:
|
|||
- match: { aggregations.cities.buckets.1.doc_count: 1 }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic bGltaXRlZDpjaGFuZ2VtZQ==" } # limited - user
|
||||
headers: { Authorization: "Basic bGltaXRlZDp4LXBhY2stdGVzdC1wYXNzd29yZA==" } # limited - user
|
||||
search:
|
||||
index: the_alias
|
||||
size: 0
|
||||
|
@ -144,7 +144,7 @@ teardown:
|
|||
- match: { aggregations.cities.buckets.0.doc_count: 1 }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic bGltaXRlZDpjaGFuZ2VtZQ==" } # limited - user
|
||||
headers: { Authorization: "Basic bGltaXRlZDp4LXBhY2stdGVzdC1wYXNzd29yZA==" } # limited - user
|
||||
search:
|
||||
index: the_*
|
||||
size: 0
|
||||
|
@ -162,7 +162,7 @@ teardown:
|
|||
- match: { aggregations.cities.buckets.0.doc_count: 1 }
|
||||
|
||||
- do:
|
||||
headers: { Authorization: "Basic bGltaXRlZDpjaGFuZ2VtZQ==" } # limited - user
|
||||
headers: { Authorization: "Basic bGltaXRlZDp4LXBhY2stdGVzdC1wYXNzd29yZA==" } # limited - user
|
||||
search:
|
||||
index: test_*
|
||||
size: 0
|
||||
|
|
|
@ -11,5 +11,5 @@ setup:
|
|||
index: "*"
|
||||
- length: { cluster_settings: 0 }
|
||||
- length: { node_settings: 0 }
|
||||
- length: { index_settings: 0 }
|
||||
- length: { index_settings: 1 }
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ setup:
|
|||
username: "joe"
|
||||
body: >
|
||||
{
|
||||
"password": "changeme",
|
||||
"password": "x-pack-test-password",
|
||||
"roles" : [ "role" ]
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ teardown:
|
|||
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic am9lOmNoYW5nZW1l"
|
||||
Authorization: "Basic am9lOngtcGFjay10ZXN0LXBhc3N3b3Jk"
|
||||
index:
|
||||
index: index
|
||||
type: type
|
||||
|
@ -64,7 +64,7 @@ teardown:
|
|||
- do:
|
||||
catch: /terms query with terms lookup isn't supported as part of a role query/
|
||||
headers:
|
||||
Authorization: "Basic am9lOmNoYW5nZW1l"
|
||||
Authorization: "Basic am9lOngtcGFjay10ZXN0LXBhc3N3b3Jk"
|
||||
search:
|
||||
index: index
|
||||
body: { "query" : { "match_all" : {} } }
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue