Merge branch 'master' into feature/sql
Original commit: elastic/x-pack-elasticsearch@b3f6d3fd70
This commit is contained in:
commit
216058035b
|
@ -4,9 +4,24 @@
|
|||
|
||||
The Authenticate API enables you to submit a request with a basic auth header to
|
||||
authenticate a user and retrieve information about the authenticated user.
|
||||
Returns a 401 status code if the user cannot be authenticated.
|
||||
|
||||
To authenticate a user, submit a GET request to the `_xpack/security/_authenticate` endpoint:
|
||||
|
||||
==== Request
|
||||
|
||||
`GET _xpack/security/_authenticate`
|
||||
|
||||
|
||||
==== Description
|
||||
|
||||
A successful call returns a JSON structure that shows what roles are assigned
|
||||
to the user as well as any assigned metadata.
|
||||
|
||||
If the user cannot be authenticated, this API returns a 401 status code.
|
||||
|
||||
==== Examples
|
||||
|
||||
To authenticate a user, submit a GET request to the
|
||||
`_xpack/security/_authenticate` endpoint:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
|
@ -14,8 +29,7 @@ GET _xpack/security/_authenticate
|
|||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
|
||||
A successful call returns a JSON structure that shows what roles are assigned
|
||||
to the user as well as any assigned metadata.
|
||||
The following example output provides information about the "rdeniro" user:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
|
|
|
@ -3,11 +3,37 @@
|
|||
=== Change Password API
|
||||
|
||||
The Change Password API enables you to submit a request to change the password
|
||||
of a user. Every user can change their own password and users with the
|
||||
`manage_security` privilege can change passwords of other users.
|
||||
of a user.
|
||||
|
||||
To change the password of the logged in user, submit a POST request to the
|
||||
`_xpack/security/user/_password` endpoint:
|
||||
==== Request
|
||||
|
||||
`POST _xpack/security/user/_password` +
|
||||
|
||||
`POST _xpack/security/user/<username>/_password`
|
||||
|
||||
|
||||
==== Path Parameters
|
||||
|
||||
`username`::
|
||||
(string) The user whose password you want to change. If you do not specify
|
||||
this parameter, the password is changed for the current user.
|
||||
|
||||
|
||||
==== Request Body
|
||||
|
||||
`password` (required)::
|
||||
(string) The new password value.
|
||||
|
||||
|
||||
==== Authorization
|
||||
|
||||
Every user can change their own password. Users with the `manage_security`
|
||||
privilege can change passwords of other users.
|
||||
|
||||
|
||||
==== Examples
|
||||
|
||||
The following example updates the password for the `elastic` user:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
|
|
|
@ -5,6 +5,31 @@
|
|||
The Clear Cache API evicts users from the user cache. You can completely clear
|
||||
the cache or evict specific users.
|
||||
|
||||
==== Request
|
||||
|
||||
`POST _xpack/security/realm/<realms>/_clear_cache` +
|
||||
|
||||
`POST _xpack/security/realm/<realms>/_clear_cache?usernames=<usernames>`
|
||||
|
||||
|
||||
==== Description
|
||||
|
||||
User credentials are cached in memory on each node to avoid connecting to a
|
||||
remote authentication service or hitting the disk for every incoming request.
|
||||
There are realm settings that you can use to configure the user cache. For more
|
||||
information, see {xpack-ref}/controlling-user-cache.html[Controlling the User Cache].
|
||||
|
||||
==== Path Parameters
|
||||
|
||||
`realms` (required)::
|
||||
(list) A comma-separated list of the realms to clear.
|
||||
|
||||
`usernames`::
|
||||
(list) A comma-separated list of the users to clear from the cache. If you
|
||||
do not specify this parameter, the API evicts all users from the user cache.
|
||||
|
||||
==== Examples
|
||||
|
||||
For example, to evict all users cached by the `file` realm:
|
||||
|
||||
[source,js]
|
||||
|
@ -29,6 +54,3 @@ list:
|
|||
POST _xpack/security/realm/default_file,ldap1/_clear_cache
|
||||
------------------------------------------------------------
|
||||
// CONSOLE
|
||||
|
||||
For more information, see
|
||||
{xpack-ref}/controlling-user-cache.html[Controlling the User Cache].
|
||||
|
|
|
@ -7,13 +7,41 @@
|
|||
The `has_privileges` API allows you to determine whether the logged in user has
|
||||
a specified list of privileges.
|
||||
|
||||
==== Request
|
||||
|
||||
`GET _xpack/security/user/_has_privileges`
|
||||
|
||||
|
||||
==== Description
|
||||
|
||||
For a list of the privileges that you can specify in this API,
|
||||
see {xpack-ref}/security-privileges.html[Security Privileges].
|
||||
|
||||
A successful call returns a JSON structure that shows whether each specified
|
||||
privilege is assigned to the user.
|
||||
|
||||
|
||||
==== Request Body
|
||||
|
||||
`cluster`:: (list) A list of the cluster privileges that you want to check.
|
||||
|
||||
`index`::
|
||||
`names`::: (list) A list of indices.
|
||||
`privileges`::: (list) A list of the privileges that you want to check for the
|
||||
specified indices.
|
||||
|
||||
==== Authorization
|
||||
|
||||
All users can use this API, but only to determine their own privileges.
|
||||
To check the privileges of other users, you must use the run as feature. For
|
||||
more information, see
|
||||
more information, see
|
||||
{xpack-ref}/run-as-privilege.html[Submitting Requests on Behalf of Other Users].
|
||||
|
||||
To check you privileges, submit a GET request to the
|
||||
`_xpack/security/user/_has_privileges` endpoint:
|
||||
|
||||
==== Examples
|
||||
|
||||
The following example checks whether the current user has a specific set of
|
||||
cluster and indices privileges:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
|
@ -34,8 +62,7 @@ GET _xpack/security/user/_has_privileges
|
|||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
|
||||
A successful call returns a JSON structure that shows whether each specified
|
||||
privilege is assigned to the user
|
||||
The following example output indicates which privileges the "rdeniro" user has:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
|
|
|
@ -2,15 +2,69 @@
|
|||
[[security-api-role-mapping]]
|
||||
=== Role Mapping APIs
|
||||
|
||||
The Role Mapping API enables you to add, remove, and retrieve role-mappings.
|
||||
To use this API, you must have at least the `manage_security` cluster privilege.
|
||||
The Role Mapping API enables you to add, remove, and retrieve role mappings.
|
||||
|
||||
NOTE: The API requires that each role-mapping have a distinct name. The name is
|
||||
==== Request
|
||||
|
||||
`GET /_xpack/security/role_mapping` +
|
||||
|
||||
`GET /_xpack/security/role_mapping/<name>` +
|
||||
|
||||
`DELETE /_xpack/security/role_mapping/<name>` +
|
||||
|
||||
`POST /_xpack/security/role_mapping/<name>` +
|
||||
|
||||
`PUT /_xpack/security/role_mapping/<name>`
|
||||
|
||||
==== Description
|
||||
|
||||
NOTE: The API requires that each role mapping have a distinct name. The name is
|
||||
used solely as an identifier to facilitate interaction via the API, and does
|
||||
not affect the behavior of the mapping in any way.
|
||||
|
||||
For more information, see
|
||||
{xpack-ref}/mapping-roles.html[Mapping Users and Groups to Roles].
|
||||
|
||||
==== Path Parameters
|
||||
|
||||
`name`::
|
||||
(string) The distinct name that identifies the role mapping. If you do not
|
||||
specify this parameter, the Get Role Mappings API returns information about all
|
||||
role mappings.
|
||||
|
||||
|
||||
==== Request Body
|
||||
|
||||
The following parameters can be specified in the body of a PUT or POST request
|
||||
and pertain to adding a role mapping:
|
||||
|
||||
`enabled` (required)::
|
||||
(boolean) Mappings that have `enabled` set to `false` are ignored when role
|
||||
mapping is performed.
|
||||
|
||||
`metadata`::
|
||||
(object) Additional metadata that helps define which roles are assigned to each
|
||||
user. Within the `metadata` object, keys beginning with `_` are reserved for
|
||||
system usage.
|
||||
|
||||
`roles` (required)::
|
||||
(list) A list of roles that are granted to the users that match the role-mapping
|
||||
rules.
|
||||
|
||||
`rules` (required)::
|
||||
(object) The rules that determine which users should be matched by the mapping.
|
||||
A rule is a logical condition that is expressed by using a JSON DSL.
|
||||
|
||||
|
||||
==== Authorization
|
||||
|
||||
To use this API, you must have at least the `manage_security` cluster privilege.
|
||||
|
||||
|
||||
==== Examples
|
||||
|
||||
[[security-api-put-role-mapping]]
|
||||
To add a role-mapping, submit a PUT or POST request to the `/_xpack/security/role_mapping/<name>`
|
||||
To add a role mapping, submit a PUT or POST request to the `/_xpack/security/role_mapping/<name>`
|
||||
endpoint:
|
||||
|
||||
[source,js]
|
||||
|
@ -28,14 +82,10 @@ POST /_xpack/security/role_mapping/administrators
|
|||
}
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
<1> Mappings that have `enabled` set to `false` will be ignored when role-mapping
|
||||
<1> Mappings that have `enabled` set to `false` will be ignored when role mapping
|
||||
is performed.
|
||||
<2> Metadata is optional
|
||||
|
||||
The `roles`, `enabled`, and `rules` fields are required at the top-level.
|
||||
Within the `metadata` object, keys beginning with `_` are reserved for system
|
||||
usage.
|
||||
|
||||
A successful call returns a JSON structure that shows whether the mapping has
|
||||
been created or updated.
|
||||
|
||||
|
@ -51,7 +101,7 @@ been created or updated.
|
|||
<1> When an existing mapping is updated, `created` is set to false.
|
||||
|
||||
[[security-api-get-role-mapping]]
|
||||
To retrieve a role-mapping, issue a GET request to the
|
||||
To retrieve a role mapping, issue a GET request to the
|
||||
`/_xpack/security/role_mapping/<name>` endpoint:
|
||||
|
||||
[source,js]
|
||||
|
@ -61,7 +111,7 @@ GET /_xpack/security/role_mapping/administrators
|
|||
// CONSOLE
|
||||
// TEST[continued]
|
||||
|
||||
A successful call an object, where the keys are the
|
||||
A successful call retrieves an object, where the keys are the
|
||||
names of the request mappings, and the values are
|
||||
the JSON representation of those mappings.
|
||||
If there is no mapping with the requested name, the
|
||||
|
@ -107,7 +157,7 @@ GET /_xpack/security/role_mapping
|
|||
// TEST[continued]
|
||||
|
||||
[[security-api-delete-role-mapping]]
|
||||
To delete a role-mapping, submit a DELETE request to the
|
||||
To delete a role mapping, submit a DELETE request to the
|
||||
`/_xpack/security/role_mapping/<name>` endpoint:
|
||||
|
||||
[source,js]
|
||||
|
|
|
@ -3,10 +3,72 @@
|
|||
=== Role Management APIs
|
||||
|
||||
The Roles API enables you to add, remove, and retrieve roles in the `native`
|
||||
realm. To use this API, you must have at least the `manage_security` cluster
|
||||
realm.
|
||||
|
||||
==== Request
|
||||
|
||||
`GET /_xpack/security/role` +
|
||||
|
||||
`GET /_xpack/security/role/<name>` +
|
||||
|
||||
`POST /_xpack/security/role/<name>/_clear_cache` +
|
||||
|
||||
`POST /_xpack/security/role/<name>` +
|
||||
|
||||
`PUT /_xpack/security/role/<name>`
|
||||
|
||||
|
||||
==== Description
|
||||
|
||||
The Roles API is generally the preferred way to manage roles, rather than using
|
||||
file-based role management. For more information, see
|
||||
{xpack-ref}/authorization.html[Configuring Role-based Access Control].
|
||||
|
||||
|
||||
==== Path Parameters
|
||||
|
||||
`name`::
|
||||
(string) The name of the role. If you do not specify this parameter, the
|
||||
Get Roles API returns information about all roles.
|
||||
|
||||
|
||||
==== Request Body
|
||||
|
||||
The following parameters can be specified in the body of a PUT or POST request
|
||||
and pertain to adding a role:
|
||||
|
||||
`cluster`:: (list) A list of cluster privileges. These privileges define the
|
||||
cluster level actions that users with this role are able to execute.
|
||||
|
||||
`indices`:: (list) A list of indices permissions entries.
|
||||
`field_security`::: (list) The document fields that the owners of the role have
|
||||
read access to. For more information, see
|
||||
{xpack-ref}/field-and-document-access-control.html[Setting Up Field and Document Level Security].
|
||||
`names` (required)::: (list) A list of indices (or index name patterns) to which the
|
||||
permissions in this entry apply.
|
||||
`privileges`(required)::: (list) The index level privileges that the owners of the role
|
||||
have on the specified indices.
|
||||
`query`::: A search query that defines the documents the owners of the role have
|
||||
read access to. A document within the specified indices must match this query in
|
||||
order for it to be accessible by the owners of the role.
|
||||
|
||||
`metadata`:: (object) Optional meta-data. Within the `metadata` object, keys
|
||||
that begin with `_` are reserved for system usage.
|
||||
|
||||
`run_as`:: (list) A list of users that the owners of this role can impersonate.
|
||||
For more information, see
|
||||
{xpack-ref}/run-as-privilege.html[Submitting Requests on Behalf of Other Users].
|
||||
|
||||
For more information, see {xpack-ref}/defining-roles.html[Defining Roles].
|
||||
|
||||
|
||||
==== Authorization
|
||||
|
||||
To use this API, you must have at least the `manage_security` cluster
|
||||
privilege.
|
||||
|
||||
NOTE: The Roles API is now the preferred way to manage roles.
|
||||
|
||||
==== Examples
|
||||
|
||||
[[security-api-put-role]]
|
||||
To add a role, submit a PUT or POST request to the `/_xpack/security/role/<rolename>`
|
||||
|
@ -35,15 +97,6 @@ POST /_xpack/security/role/my_admin_role
|
|||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
|
||||
The `name`, `cluster`, and `indices` fields are required at the top-level.
|
||||
Within the `indices` array, the `names` and `privileges` fields are required.
|
||||
Within the `metadata` object, keys beginning with `_` are reserved for system
|
||||
usage.
|
||||
|
||||
The `field_security` and `query` fields are both optional. They are used to
|
||||
implement field and document level security. For more information, see
|
||||
{xpack-ref}/field-and-document-access-control.html[Setting Up Field and Document Level Security].
|
||||
|
||||
A successful call returns a JSON structure that shows whether the role has been
|
||||
created or updated.
|
||||
|
||||
|
|
|
@ -3,10 +3,54 @@
|
|||
=== Token Management APIs
|
||||
|
||||
The `token` API enables you to create and invalidate bearer tokens for access
|
||||
without requiring basic authentication. The get token API takes the same
|
||||
parameters as a typical OAuth 2.0 token API except for the use of a JSON
|
||||
request body.
|
||||
without requiring basic authentication.
|
||||
|
||||
==== Request
|
||||
|
||||
`POST /_xpack/security/oauth2/token` +
|
||||
|
||||
`DELETE /_xpack/security/oauth2/token`
|
||||
|
||||
==== Description
|
||||
|
||||
The Get Token API takes the same parameters as a typical OAuth 2.0 token API
|
||||
except for the use of a JSON request body.
|
||||
|
||||
A successful Get Token API call returns a JSON structure that contains the access
|
||||
token, the amount of time (seconds) that the token expires in, the type, and the
|
||||
scope if available.
|
||||
|
||||
The tokens returned by the Get Token API have a finite period of time for which
|
||||
they are valid and after that time period, they can no longer be used. However,
|
||||
if you want to invalidate a token immediately, you can do so by using the Delete
|
||||
Token API.
|
||||
|
||||
|
||||
==== Request Body
|
||||
|
||||
The following parameters can be specified in the body of a POST request and
|
||||
pertain to creating a token:
|
||||
|
||||
`grant_type`::
|
||||
(string) The type of grant. Currently only the `password` grant type is supported.
|
||||
|
||||
`password` (required)::
|
||||
(string) The user's password.
|
||||
|
||||
`scope`::
|
||||
(string) The scope of the token. Currently tokens are only issued for a scope of
|
||||
`FULL` regardless of the value sent with the request.
|
||||
|
||||
`username` (required)::
|
||||
(string) The username that identifies the user.
|
||||
|
||||
The following parameters can be specified in the body of a DELETE request and
|
||||
pertain to deleting a token:
|
||||
|
||||
`token`::
|
||||
(string) An access token.
|
||||
|
||||
==== Examples
|
||||
[[security-api-get-token]]
|
||||
To obtain a token, submit a POST request to the `/_xpack/security/oauth2/token`
|
||||
endpoint.
|
||||
|
@ -22,22 +66,8 @@ POST /_xpack/security/oauth2/token
|
|||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
|
||||
.Token Request Fields
|
||||
[cols="4,^2,10"]
|
||||
|=======================
|
||||
| Name | Required | Description
|
||||
| `username` | yes | The username that identifies the user.
|
||||
| `password` | yes | The user's password.
|
||||
| `grant_type`| yes | The type of grant. Currently only the `password`
|
||||
grant type is supported.
|
||||
| `scope` | no | The scope of the token. Currently tokens are only
|
||||
issued for a scope of `FULL` regardless of the value
|
||||
sent with the request.
|
||||
|=======================
|
||||
|
||||
A successful call returns a JSON structure that contains the access token, the
|
||||
amount of time (seconds) that the token expires in, the type, and the scope if
|
||||
available.
|
||||
The following example output contains the access token, the amount of time (in
|
||||
seconds) that the token expires in, and the type:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
|
@ -49,9 +79,6 @@ available.
|
|||
--------------------------------------------------
|
||||
// TESTRESPONSE[s/dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==/$body.access_token/]
|
||||
|
||||
A successful call returns a JSON structure that shows whether the user has been
|
||||
created or updated.
|
||||
|
||||
The token returned by this API can be used by sending a request with a
|
||||
`Authorization` header with a value having the prefix `Bearer ` followed
|
||||
by the value of the `access_token`.
|
||||
|
@ -62,10 +89,8 @@ curl -H "Authorization: Bearer dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvb
|
|||
--------------------------------------------------
|
||||
|
||||
[[security-api-invalidate-token]]
|
||||
The tokens returned from this API have a finite period of time for which they
|
||||
are valid and after that time period, they can no longer be used. However, if
|
||||
a token must be invalidated immediately, you can do so by submitting a DELETE
|
||||
request to `/_xpack/security/oauth2/token`.
|
||||
If a token must be invalidated immediately, you can do so by submitting a DELETE
|
||||
request to `/_xpack/security/oauth2/token`. For example:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
|
|
|
@ -4,18 +4,78 @@
|
|||
|
||||
The `user` API enables you to create, read, update, and delete users from the
|
||||
`native` realm. These users are commonly referred to as *native users*.
|
||||
|
||||
|
||||
==== Request
|
||||
|
||||
`GET /_xpack/security/user` +
|
||||
|
||||
`GET /_xpack/security/user/<username>` +
|
||||
|
||||
`DELETE /_xpack/security/user/<username>` +
|
||||
|
||||
`POST /_xpack/security/user/<username>` +
|
||||
|
||||
`PUT /_xpack/security/user/<username>` +
|
||||
|
||||
`PUT /_xpack/security/user/<username>/_disable` +
|
||||
|
||||
`PUT /_xpack/security/user/<username>/_enable` +
|
||||
|
||||
`PUT /_xpack/security/user/<username>/_password`
|
||||
|
||||
|
||||
==== Description
|
||||
|
||||
You can use the PUT user API to create or update users. When updating a user,
|
||||
you can update everything but its `username` and `password`. To change a user's
|
||||
password, use the <<security-api-reset-user-password, reset password API>>.
|
||||
|
||||
[[username-validation]]
|
||||
NOTE: Usernames must be at least 1 and no more than 1024 characters. They can
|
||||
contain alphanumeric characters (`a-z`, `A-Z`, `0-9`), spaces, punctuation, and
|
||||
printable symbols in the https://en.wikipedia.org/wiki/Basic_Latin_(Unicode_block)[Basic Latin (ASCII) block].
|
||||
Leading or trailing whitespace is not allowed.
|
||||
|
||||
==== Path Parameters
|
||||
|
||||
`username`::
|
||||
(string) An identifier for the user. If you omit this parameter from a Get
|
||||
User API request, it retrieves information about all users.
|
||||
|
||||
|
||||
==== Request Body
|
||||
|
||||
The following parameters can be specified in the body of a POST or PUT request
|
||||
and pertain to creating a user:
|
||||
|
||||
`email`::
|
||||
(string) The email of the user.
|
||||
|
||||
`full_name`::
|
||||
(string) The full name of the user.
|
||||
|
||||
`metadata`::
|
||||
(object) Arbitrary metadata that you want to associate with the user.
|
||||
|
||||
`password` (required)::
|
||||
(string) The user's password. Passwords must be at least 6 characters long.
|
||||
|
||||
`roles` (required)::
|
||||
(list) A set of roles the user has. The roles determine the user's access
|
||||
permissions.
|
||||
|
||||
==== Authorization
|
||||
|
||||
To use this API, you must have at least the `manage_security` cluster privilege.
|
||||
|
||||
|
||||
==== Examples
|
||||
|
||||
[[security-api-put-user]]
|
||||
To add a user, submit a PUT or POST request to the `/_xpack/security/user/<username>`
|
||||
endpoint.
|
||||
|
||||
[[username-validation]]
|
||||
NOTE: Usernames must be at least 1 and no more than 1024 characters. They can
|
||||
contain alphanumeric characters (`a-z`, `A-Z`, `0-9`), spaces,
|
||||
punctuation, and printable symbols in the https://en.wikipedia.org/wiki/Basic_Latin_(Unicode_block)[Basic Latin (ASCII) block].
|
||||
Leading or trailing whitespace is not allowed.
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
POST /_xpack/security/user/jacknich
|
||||
|
@ -31,20 +91,6 @@ POST /_xpack/security/user/jacknich
|
|||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
|
||||
.User Fields
|
||||
[cols="4,^2,10"]
|
||||
|=======================
|
||||
| Name | Required | Description
|
||||
| `password` | yes | The user's password. Passwords must be at least 6
|
||||
characters long.
|
||||
| `roles` | yes | A set of roles the user has. The roles determine
|
||||
the user's access permissions
|
||||
| `full_name` | no | The full name of the user
|
||||
| `email` | no | The email of the user
|
||||
| `metadata` | no | Arbitrary metadata that you want to associate with
|
||||
the user.
|
||||
|=======================
|
||||
|
||||
A successful call returns a JSON structure that shows whether the user has been
|
||||
created or updated.
|
||||
|
||||
|
@ -59,11 +105,7 @@ created or updated.
|
|||
// TESTRESPONSE
|
||||
<1> When an existing user is updated, `created` is set to false.
|
||||
|
||||
NOTE: You also use the PUT user API to update users. When updating a user, you
|
||||
can update everything but its `username` and `password`. To change a user's
|
||||
password, use the <<security-api-reset-user-password, reset password API>>.
|
||||
|
||||
Once you add a user through the Users API, requests from that user can be
|
||||
After you add a user through the Users API, requests from that user can be
|
||||
authenticated.
|
||||
|
||||
[source,shell]
|
||||
|
|
|
@ -85,6 +85,9 @@ change between releases.
|
|||
Grants the minimum privileges required for any user of {kib}. This role grants
|
||||
access to the {kib} indices and grants monitoring privileges for the cluster.
|
||||
|
||||
[[built-in-roles-logstash-admin]] `logstash_admin` ::
|
||||
Grants access to the `.logstash*` indices for managing configurations.
|
||||
|
||||
[[built-in-roles-logstash-system]] `logstash_system` ::
|
||||
Grants access necessary for the Logstash system user to send system-level data
|
||||
(such as monitoring) to {es}. For more information, see
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
|
||||
public class GetTrialStatusAction extends Action<GetTrialStatusRequest, GetTrialStatusResponse, GetTrialStatusRequestBuilder> {
|
||||
|
||||
public static final GetTrialStatusAction INSTANCE = new GetTrialStatusAction();
|
||||
public static final String NAME = "cluster:admin/xpack/license/trial_status";
|
||||
|
||||
private GetTrialStatusAction() {
|
||||
super(NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetTrialStatusRequestBuilder newRequestBuilder(ElasticsearchClient client) {
|
||||
return new GetTrialStatusRequestBuilder(client, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetTrialStatusResponse newResponse() {
|
||||
return new GetTrialStatusResponse();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.master.MasterNodeReadRequest;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class GetTrialStatusRequest extends MasterNodeReadRequest<GetTrialStatusRequest> {
|
||||
|
||||
public GetTrialStatusRequest() {
|
||||
}
|
||||
|
||||
public GetTrialStatusRequest(StreamInput in) throws IOException {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionRequestValidationException validate() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.ActionRequestBuilder;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
|
||||
class GetTrialStatusRequestBuilder extends ActionRequestBuilder<GetTrialStatusRequest,
|
||||
GetTrialStatusResponse, GetTrialStatusRequestBuilder> {
|
||||
|
||||
GetTrialStatusRequestBuilder(ElasticsearchClient client, GetTrialStatusAction action) {
|
||||
super(client, action, new GetTrialStatusRequest());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class GetTrialStatusResponse extends ActionResponse {
|
||||
|
||||
private boolean eligibleToStartTrial;
|
||||
|
||||
GetTrialStatusResponse() {
|
||||
}
|
||||
|
||||
GetTrialStatusResponse(boolean eligibleToStartTrial) {
|
||||
this.eligibleToStartTrial = eligibleToStartTrial;
|
||||
}
|
||||
|
||||
boolean isEligibleToStartTrial() {
|
||||
return eligibleToStartTrial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
eligibleToStartTrial = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeBoolean(eligibleToStartTrial);
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.license;
|
|||
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||
import org.apache.logging.log4j.util.Supplier;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
|
||||
import org.elasticsearch.cluster.ClusterChangedEvent;
|
||||
|
@ -227,8 +228,14 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
|
||||
@Override
|
||||
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(newLicense));
|
||||
MetaData currentMetadata = currentState.metaData();
|
||||
LicensesMetaData licensesMetaData = currentMetadata.custom(LicensesMetaData.TYPE);
|
||||
Version trialVersion = null;
|
||||
if (licensesMetaData != null) {
|
||||
trialVersion = licensesMetaData.getMostRecentTrialVersion();
|
||||
}
|
||||
MetaData.Builder mdBuilder = MetaData.builder(currentMetadata);
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(newLicense, trialVersion));
|
||||
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||
}
|
||||
});
|
||||
|
@ -237,7 +244,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
}
|
||||
|
||||
|
||||
static TimeValue days(int days) {
|
||||
private static TimeValue days(int days) {
|
||||
return TimeValue.timeValueHours(days * 24);
|
||||
}
|
||||
|
||||
|
@ -273,7 +280,9 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
final LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
|
||||
if (currentLicenses.getLicense() != LicensesMetaData.LICENSE_TOMBSTONE) {
|
||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(LicensesMetaData.LICENSE_TOMBSTONE));
|
||||
LicensesMetaData newMetadata = new LicensesMetaData(LicensesMetaData.LICENSE_TOMBSTONE,
|
||||
currentLicenses.getMostRecentTrialVersion());
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, newMetadata);
|
||||
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||
} else {
|
||||
return currentState;
|
||||
|
@ -287,6 +296,40 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
return license == LicensesMetaData.LICENSE_TOMBSTONE ? null : license;
|
||||
}
|
||||
|
||||
void upgradeSelfGeneratedLicense(final ActionListener<PostStartTrialResponse> listener) {
|
||||
clusterService.submitStateUpdateTask("upgrade self generated license",
|
||||
new ClusterStateUpdateTask() {
|
||||
@Override
|
||||
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
||||
LicensesMetaData licensesMetaData = oldState.metaData().custom(LicensesMetaData.TYPE);
|
||||
logger.debug("upgraded self generated license: {}", licensesMetaData);
|
||||
|
||||
if (licensesMetaData == null || licensesMetaData.isEligibleForTrial()) {
|
||||
listener.onResponse(new PostStartTrialResponse(PostStartTrialResponse.STATUS.UPGRADED_TO_TRIAL));
|
||||
} else {
|
||||
listener.onResponse(new PostStartTrialResponse(PostStartTrialResponse.STATUS.TRIAL_ALREADY_ACTIVATED));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||
LicensesMetaData licensesMetaData = currentState.metaData().custom(LicensesMetaData.TYPE);
|
||||
|
||||
if (licensesMetaData == null || licensesMetaData.isEligibleForTrial()) {
|
||||
return updateWithLicense(currentState, "trial");
|
||||
} else {
|
||||
return currentState;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String source, @Nullable Exception e) {
|
||||
logger.error(new ParameterizedMessage("unexpected failure during [{}]", source), e);
|
||||
listener.onFailure(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Master-only operation to generate a one-time global trial license.
|
||||
* The trial license is only generated and stored if the current cluster state metaData
|
||||
|
@ -299,7 +342,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
||||
LicensesMetaData licensesMetaData = newState.metaData().custom(LicensesMetaData.TYPE);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("registered trial license: {}", licensesMetaData);
|
||||
logger.debug("registered self generated license: {}", licensesMetaData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,27 +350,18 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||
final MetaData metaData = currentState.metaData();
|
||||
final LicensesMetaData currentLicensesMetaData = metaData.custom(LicensesMetaData.TYPE);
|
||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
||||
// do not generate a trial license if any license is present
|
||||
if (currentLicensesMetaData == null) {
|
||||
long issueDate = clock.millis();
|
||||
String type = SELF_GENERATED_LICENSE_TYPE.get(settings);
|
||||
if (validSelfGeneratedType(type) == false) {
|
||||
throw new IllegalArgumentException("Illegal self generated license type [" + type +
|
||||
"]. Must be trial or basic.");
|
||||
}
|
||||
License.Builder specBuilder = License.builder()
|
||||
.uid(UUID.randomUUID().toString())
|
||||
.issuedTo(clusterService.getClusterName().value())
|
||||
.maxNodes(selfGeneratedLicenseMaxNodes)
|
||||
.issueDate(issueDate)
|
||||
.type(type)
|
||||
.expiryDate(issueDate + SELF_GENERATED_LICENSE_DURATION.getMillis());
|
||||
License selfGeneratedLicense = SelfGeneratedLicense.create(specBuilder);
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(selfGeneratedLicense));
|
||||
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||
|
||||
return updateWithLicense(currentState, type);
|
||||
} else {
|
||||
return currentState;
|
||||
}
|
||||
return currentState;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -338,6 +372,27 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
});
|
||||
}
|
||||
|
||||
private ClusterState updateWithLicense(ClusterState currentState, String type) {
|
||||
long issueDate = clock.millis();
|
||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
||||
License.Builder specBuilder = License.builder()
|
||||
.uid(UUID.randomUUID().toString())
|
||||
.issuedTo(clusterService.getClusterName().value())
|
||||
.maxNodes(selfGeneratedLicenseMaxNodes)
|
||||
.issueDate(issueDate)
|
||||
.type(type)
|
||||
.expiryDate(issueDate + SELF_GENERATED_LICENSE_DURATION.getMillis());
|
||||
License selfGeneratedLicense = SelfGeneratedLicense.create(specBuilder);
|
||||
LicensesMetaData licensesMetaData;
|
||||
if ("trial".equals(type)) {
|
||||
licensesMetaData = new LicensesMetaData(selfGeneratedLicense, Version.CURRENT);
|
||||
} else {
|
||||
licensesMetaData = new LicensesMetaData(selfGeneratedLicense, null);
|
||||
}
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, licensesMetaData);
|
||||
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() throws ElasticsearchException {
|
||||
clusterService.addListener(this);
|
||||
|
@ -436,7 +491,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
* Additionally schedules license expiry notifications and event callbacks
|
||||
* relative to the current license's expiry
|
||||
*/
|
||||
void onUpdate(final LicensesMetaData currentLicensesMetaData) {
|
||||
private void onUpdate(final LicensesMetaData currentLicensesMetaData) {
|
||||
final License license = getLicense(currentLicensesMetaData);
|
||||
// license can be null if the trial license is yet to be auto-generated
|
||||
// in this case, it is a no-op
|
||||
|
|
|
@ -5,15 +5,17 @@
|
|||
*/
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.AbstractNamedDiffable;
|
||||
import org.elasticsearch.cluster.MergableCustomMetaData;
|
||||
import org.elasticsearch.cluster.NamedDiff;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.inject.internal.Nullable;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.license.License.OperationMode;
|
||||
import org.elasticsearch.cluster.MergableCustomMetaData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
|
@ -48,33 +50,56 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
|||
|
||||
private License license;
|
||||
|
||||
LicensesMetaData(License license) {
|
||||
// This field describes the version of x-pack for which this cluster has exercised a trial. If the field
|
||||
// is null, then no trial has been exercised. We keep the version to leave open the possibility that we
|
||||
// may eventually allow a cluster to exercise a trial every time they upgrade to a new major version.
|
||||
@Nullable
|
||||
private Version trialVersion;
|
||||
|
||||
LicensesMetaData(License license, Version trialVersion) {
|
||||
this.license = license;
|
||||
this.trialVersion = trialVersion;
|
||||
}
|
||||
|
||||
public License getLicense() {
|
||||
return license;
|
||||
}
|
||||
|
||||
boolean isEligibleForTrial() {
|
||||
if (trialVersion == null) {
|
||||
return true;
|
||||
}
|
||||
return Version.CURRENT.major > trialVersion.major;
|
||||
}
|
||||
|
||||
Version getMostRecentTrialVersion() {
|
||||
return trialVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (license != null) {
|
||||
return license.toString();
|
||||
}
|
||||
return "";
|
||||
return "LicensesMetaData{" +
|
||||
"license=" + license +
|
||||
", trialVersion=" + trialVersion +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
LicensesMetaData that = (LicensesMetaData) o;
|
||||
return !(license != null ? !license.equals(that.license) : that.license != null);
|
||||
|
||||
if (license != null ? !license.equals(that.license) : that.license != null) return false;
|
||||
return trialVersion != null ? trialVersion.equals(that.trialVersion) : that.trialVersion == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return license != null ? license.hashCode() : 0;
|
||||
int result = license != null ? license.hashCode() : 0;
|
||||
result = 31 * result + (trialVersion != null ? trialVersion.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,6 +114,7 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
|||
|
||||
public static LicensesMetaData fromXContent(XContentParser parser) throws IOException {
|
||||
License license = LICENSE_TOMBSTONE;
|
||||
Version trialLicense = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
|
@ -101,11 +127,14 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
|||
} else if (token == XContentParser.Token.VALUE_NULL) {
|
||||
license = LICENSE_TOMBSTONE;
|
||||
}
|
||||
} else if (fieldName.equals(Fields.TRIAL_LICENSE)) {
|
||||
parser.nextToken();
|
||||
trialLicense = Version.fromString(parser.text());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new LicensesMetaData(license);
|
||||
return new LicensesMetaData(license, trialLicense);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,6 +146,9 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
|||
license.toInnerXContent(builder, params);
|
||||
builder.endObject();
|
||||
}
|
||||
if (trialVersion != null) {
|
||||
builder.field(Fields.TRIAL_LICENSE, trialVersion.toString());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
@ -128,6 +160,15 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
|||
streamOutput.writeBoolean(true); // has a license
|
||||
license.writeTo(streamOutput);
|
||||
}
|
||||
// TODO Eventually this should be 6.0. But it is 7.0 temporarily for bwc
|
||||
if (streamOutput.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) {
|
||||
if (trialVersion == null) {
|
||||
streamOutput.writeBoolean(false);
|
||||
} else {
|
||||
streamOutput.writeBoolean(true);
|
||||
Version.writeVersion(trialVersion, streamOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LicensesMetaData(StreamInput streamInput) throws IOException {
|
||||
|
@ -136,6 +177,13 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
|||
} else {
|
||||
license = LICENSE_TOMBSTONE;
|
||||
}
|
||||
// TODO Eventually this should be 6.0. But it is 7.0 temporarily for bwc
|
||||
if (streamInput.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) {
|
||||
boolean hasExercisedTrial = streamInput.readBoolean();
|
||||
if (hasExercisedTrial) {
|
||||
this.trialVersion = Version.readVersion(streamInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static NamedDiff<MetaData.Custom> readDiffFrom(StreamInput streamInput) throws IOException {
|
||||
|
@ -155,5 +203,6 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
|||
|
||||
private static final class Fields {
|
||||
private static final String LICENSE = "license";
|
||||
private static final String TRIAL_LICENSE = "trial_license";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class Licensing implements ActionPlugin {
|
|||
|
||||
public static final String NAME = "license";
|
||||
protected final Settings settings;
|
||||
protected final boolean isTransportClient;
|
||||
private final boolean isTransportClient;
|
||||
private final boolean isTribeNode;
|
||||
|
||||
public List<NamedWriteableRegistry.Entry> getNamedWriteables() {
|
||||
|
@ -53,6 +53,7 @@ public class Licensing implements ActionPlugin {
|
|||
LicensesMetaData::fromXContent));
|
||||
return entries;
|
||||
}
|
||||
|
||||
public Licensing(Settings settings) {
|
||||
this.settings = settings;
|
||||
isTransportClient = transportClientMode(settings);
|
||||
|
@ -66,7 +67,9 @@ public class Licensing implements ActionPlugin {
|
|||
}
|
||||
return Arrays.asList(new ActionHandler<>(PutLicenseAction.INSTANCE, TransportPutLicenseAction.class),
|
||||
new ActionHandler<>(GetLicenseAction.INSTANCE, TransportGetLicenseAction.class),
|
||||
new ActionHandler<>(DeleteLicenseAction.INSTANCE, TransportDeleteLicenseAction.class));
|
||||
new ActionHandler<>(DeleteLicenseAction.INSTANCE, TransportDeleteLicenseAction.class),
|
||||
new ActionHandler<>(PostStartTrialAction.INSTANCE, TransportPostStartTrialAction.class),
|
||||
new ActionHandler<>(GetTrialStatusAction.INSTANCE, TransportGetTrialStatusAction.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,6 +81,8 @@ public class Licensing implements ActionPlugin {
|
|||
if (false == isTribeNode) {
|
||||
handlers.add(new RestPutLicenseAction(settings, restController));
|
||||
handlers.add(new RestDeleteLicenseAction(settings, restController));
|
||||
handlers.add(new RestGetTrialStatus(settings, restController));
|
||||
handlers.add(new RestPostStartTrialLicense(settings, restController));
|
||||
}
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -39,4 +39,16 @@ public class LicensingClient {
|
|||
public void deleteLicense(DeleteLicenseRequest request, ActionListener<DeleteLicenseResponse> listener) {
|
||||
client.execute(DeleteLicenseAction.INSTANCE, request, listener);
|
||||
}
|
||||
|
||||
public PostStartTrialRequestBuilder preparePutUpgradeToTrial() {
|
||||
return new PostStartTrialRequestBuilder(client, PostStartTrialAction.INSTANCE);
|
||||
}
|
||||
|
||||
public GetTrialStatusRequestBuilder prepareGetUpgradeToTrial() {
|
||||
return new GetTrialStatusRequestBuilder(client, GetTrialStatusAction.INSTANCE);
|
||||
}
|
||||
|
||||
public void putUpgradeToTrial(PostStartTrialRequest request, ActionListener<PostStartTrialResponse> listener) {
|
||||
client.execute(PostStartTrialAction.INSTANCE, request, listener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
|
||||
public class PostStartTrialAction extends Action<PostStartTrialRequest, PostStartTrialResponse, PostStartTrialRequestBuilder> {
|
||||
|
||||
public static final PostStartTrialAction INSTANCE = new PostStartTrialAction();
|
||||
public static final String NAME = "cluster:admin/xpack/license/start_trial";
|
||||
|
||||
private PostStartTrialAction() {
|
||||
super(NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PostStartTrialRequestBuilder newRequestBuilder(ElasticsearchClient client) {
|
||||
return new PostStartTrialRequestBuilder(client, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PostStartTrialResponse newResponse() {
|
||||
return new PostStartTrialResponse();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.master.MasterNodeRequest;
|
||||
|
||||
public class PostStartTrialRequest extends MasterNodeRequest<PostStartTrialRequest> {
|
||||
|
||||
@Override
|
||||
public ActionRequestValidationException validate() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.ActionRequestBuilder;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
|
||||
class PostStartTrialRequestBuilder extends ActionRequestBuilder<PostStartTrialRequest,
|
||||
PostStartTrialResponse, PostStartTrialRequestBuilder> {
|
||||
|
||||
PostStartTrialRequestBuilder(ElasticsearchClient client, PostStartTrialAction action) {
|
||||
super(client, action, new PostStartTrialRequest());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class PostStartTrialResponse extends ActionResponse {
|
||||
|
||||
enum STATUS {
|
||||
UPGRADED_TO_TRIAL,
|
||||
TRIAL_ALREADY_ACTIVATED
|
||||
}
|
||||
|
||||
private STATUS status;
|
||||
|
||||
PostStartTrialResponse() {
|
||||
}
|
||||
|
||||
PostStartTrialResponse(STATUS status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public STATUS getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
status = in.readEnum(STATUS.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeEnum(status);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.RestBuilderListener;
|
||||
import org.elasticsearch.xpack.XPackClient;
|
||||
import org.elasticsearch.xpack.rest.XPackRestHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||
|
||||
public class RestGetTrialStatus extends XPackRestHandler {
|
||||
|
||||
RestGetTrialStatus(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
controller.registerHandler(GET, URI_BASE + "/license/trial_status", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RestChannelConsumer doPrepareRequest(RestRequest request, XPackClient client) throws IOException {
|
||||
return channel -> client.licensing().prepareGetUpgradeToTrial().execute(
|
||||
new RestBuilderListener<GetTrialStatusResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(GetTrialStatusResponse response, XContentBuilder builder) throws Exception {
|
||||
builder.startObject();
|
||||
builder.field("eligible_to_start_trial", response.isEligibleToStartTrial());
|
||||
builder.endObject();
|
||||
return new BytesRestResponse(RestStatus.OK, builder);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "xpack_trial_status_action";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.RestBuilderListener;
|
||||
import org.elasticsearch.xpack.XPackClient;
|
||||
import org.elasticsearch.xpack.rest.XPackRestHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||
|
||||
public class RestPostStartTrialLicense extends XPackRestHandler {
|
||||
|
||||
RestPostStartTrialLicense(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
controller.registerHandler(POST, URI_BASE + "/license/start_trial", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RestChannelConsumer doPrepareRequest(RestRequest request, XPackClient client) throws IOException {
|
||||
return channel -> client.licensing().preparePutUpgradeToTrial().execute(
|
||||
new RestBuilderListener<PostStartTrialResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(PostStartTrialResponse response, XContentBuilder builder) throws Exception {
|
||||
PostStartTrialResponse.STATUS status = response.getStatus();
|
||||
if (status == PostStartTrialResponse.STATUS.TRIAL_ALREADY_ACTIVATED) {
|
||||
builder.startObject()
|
||||
.field("trial_was_started", false)
|
||||
.field("error_message", "Operation failed: Trial was already activated.")
|
||||
.endObject();
|
||||
return new BytesRestResponse(RestStatus.FORBIDDEN, builder);
|
||||
} else if (status == PostStartTrialResponse.STATUS.UPGRADED_TO_TRIAL) {
|
||||
builder.startObject().field("trial_was_started", true).endObject();
|
||||
return new BytesRestResponse(RestStatus.OK, builder);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected status for PostStartTrialResponse: [" + status + "]");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "xpack_upgrade_to_trial_action";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.ActionFilters;
|
||||
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
public class TransportGetTrialStatusAction extends TransportMasterNodeReadAction<GetTrialStatusRequest, GetTrialStatusResponse> {
|
||||
|
||||
@Inject
|
||||
public TransportGetTrialStatusAction(Settings settings, TransportService transportService, ClusterService clusterService,
|
||||
ThreadPool threadPool, ActionFilters actionFilters,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||
super(settings, GetTrialStatusAction.NAME, transportService, clusterService, threadPool, actionFilters,
|
||||
GetTrialStatusRequest::new, indexNameExpressionResolver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String executor() {
|
||||
return ThreadPool.Names.SAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GetTrialStatusResponse newResponse() {
|
||||
return new GetTrialStatusResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void masterOperation(GetTrialStatusRequest request, ClusterState state,
|
||||
ActionListener<GetTrialStatusResponse> listener) throws Exception {
|
||||
LicensesMetaData licensesMetaData = state.metaData().custom(LicensesMetaData.TYPE);
|
||||
listener.onResponse(new GetTrialStatusResponse(licensesMetaData == null || licensesMetaData.isEligibleForTrial()));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClusterBlockException checkBlock(GetTrialStatusRequest request, ClusterState state) {
|
||||
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.ActionFilters;
|
||||
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
public class TransportPostStartTrialAction extends TransportMasterNodeAction<PostStartTrialRequest, PostStartTrialResponse> {
|
||||
|
||||
private final LicenseService licenseService;
|
||||
|
||||
@Inject
|
||||
public TransportPostStartTrialAction(Settings settings, TransportService transportService, ClusterService clusterService,
|
||||
LicenseService licenseService, ThreadPool threadPool, ActionFilters actionFilters,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||
super(settings, PostStartTrialAction.NAME, transportService, clusterService, threadPool, actionFilters,
|
||||
indexNameExpressionResolver, PostStartTrialRequest::new);
|
||||
this.licenseService = licenseService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String executor() {
|
||||
return ThreadPool.Names.SAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PostStartTrialResponse newResponse() {
|
||||
return new PostStartTrialResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void masterOperation(PostStartTrialRequest request, ClusterState state,
|
||||
ActionListener<PostStartTrialResponse> listener) throws Exception {
|
||||
licenseService.upgradeSelfGeneratedLicense(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClusterBlockException checkBlock(PostStartTrialRequest request, ClusterState state) {
|
||||
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
|
||||
}
|
||||
}
|
|
@ -13,8 +13,8 @@ public enum MonitoredSystem {
|
|||
|
||||
ES("es"),
|
||||
KIBANA("kibana"),
|
||||
// TODO: when "BEATS" is re-added, add it to tests where we randomly select "LOGSTASH"
|
||||
LOGSTASH("logstash"),
|
||||
BEATS("beats"),
|
||||
UNKNOWN("unknown");
|
||||
|
||||
private final String system;
|
||||
|
@ -35,8 +35,6 @@ public enum MonitoredSystem {
|
|||
return KIBANA;
|
||||
case "logstash":
|
||||
return LOGSTASH;
|
||||
case "beats":
|
||||
return BEATS;
|
||||
default:
|
||||
// Return an "unknown" monitored system
|
||||
// that can easily be filtered out if
|
||||
|
|
|
@ -41,7 +41,7 @@ public final class MonitoringTemplateUtils {
|
|||
/**
|
||||
* IDs of templates that can be used with {@linkplain #loadTemplate(String) loadTemplate}.
|
||||
*/
|
||||
public static final String[] TEMPLATE_IDS = { "alerts", "es", "kibana", "logstash", "beats" };
|
||||
public static final String[] TEMPLATE_IDS = { "alerts", "es", "kibana", "logstash" };
|
||||
|
||||
/**
|
||||
* IDs of templates that can be used with {@linkplain #createEmptyTemplate(String) createEmptyTemplate} that are not managed by a
|
||||
|
|
|
@ -56,8 +56,7 @@ public class RestMonitoringBulkAction extends MonitoringRestHandler {
|
|||
final Map<MonitoredSystem, List<String>> versionsMap = new HashMap<>();
|
||||
versionsMap.put(MonitoredSystem.KIBANA, allVersions);
|
||||
versionsMap.put(MonitoredSystem.LOGSTASH, allVersions);
|
||||
// Beats did not report data in the 5.x timeline, so it should never send the original version
|
||||
versionsMap.put(MonitoredSystem.BEATS, Collections.singletonList(MonitoringTemplateUtils.TEMPLATE_VERSION));
|
||||
// Beats did not report data in the 5.x timeline, so it should never send the original version [when we add it!]
|
||||
supportedApiVersions = Collections.unmodifiableMap(versionsMap);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@ import org.elasticsearch.common.Booleans;
|
|||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.xpack.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.common.http.HttpMethod;
|
||||
import org.elasticsearch.xpack.common.http.HttpProxy;
|
||||
|
@ -18,6 +22,7 @@ import org.elasticsearch.xpack.common.http.Scheme;
|
|||
import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
|
@ -68,7 +73,15 @@ public class JiraAccount {
|
|||
if (Strings.isEmpty(this.password)) {
|
||||
throw requiredSettingException(name, PASSWORD_SETTING);
|
||||
}
|
||||
this.issueDefaults = Collections.unmodifiableMap(settings.getAsSettings(ISSUE_DEFAULTS_SETTING).getAsStructuredMap());
|
||||
try (XContentBuilder builder = XContentBuilder.builder(XContentType.JSON.xContent())) {
|
||||
builder.startObject();
|
||||
settings.getAsSettings(ISSUE_DEFAULTS_SETTING).toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
builder.endObject();
|
||||
this.issueDefaults = Collections.unmodifiableMap(XContentType.JSON.xContent()
|
||||
.createParser(new NamedXContentRegistry(Collections.emptyList()), builder.bytes()).map());
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.elasticsearch.action.ActionListener;
|
|||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.watcher.FileChangesListener;
|
||||
import org.elasticsearch.watcher.FileWatcher;
|
||||
|
@ -127,8 +128,8 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
}
|
||||
}
|
||||
|
||||
try (InputStream in = Files.newInputStream(path)) {
|
||||
Settings settings = Settings.builder().loadFromStream(path.toString(), in).build();
|
||||
try {
|
||||
Settings settings = Settings.builder().loadFromPath(path).build();
|
||||
|
||||
Map<DN, Set<String>> dnToRoles = new HashMap<>();
|
||||
Set<String> roles = settings.names();
|
||||
|
@ -163,7 +164,7 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
logger.debug("[{}] role mappings found in file [{}] for realm [{}/{}]", dnToRoles.size(), path.toAbsolutePath(), realmType,
|
||||
realmName);
|
||||
return unmodifiableMap(dnToRoles);
|
||||
} catch (IOException | YAMLException e) {
|
||||
} catch (IOException | SettingsException e) {
|
||||
throw new ElasticsearchException("could not read realm [" + realmType + "/" + realmName + "] role mappings file [" +
|
||||
path.toAbsolutePath() + "]", e);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ public final class SystemPrivilege extends Privilege {
|
|||
"cluster:admin/reroute", // added for DiskThresholdDecider.DiskListener
|
||||
"indices:admin/mapping/put", // needed for recovery and shrink api
|
||||
"indices:admin/template/put", // needed for the TemplateUpgradeService
|
||||
"indices:admin/template/delete" // needed for the TemplateUpgradeService
|
||||
"indices:admin/template/delete", // needed for the TemplateUpgradeService
|
||||
"indices:admin/seq_no/global_checkpoint_sync*" // needed for global checkpoint syncs
|
||||
), Automatons.patterns("internal:transport/proxy/*"))); // no proxy actions for system user!
|
||||
|
||||
private SystemPrivilege() {
|
||||
|
|
|
@ -83,10 +83,8 @@ public final class RestrictedTrustConfig extends TrustConfig {
|
|||
}
|
||||
|
||||
private CertificateTrustRestrictions readTrustGroup(Path path) throws IOException {
|
||||
try (InputStream in = Files.newInputStream(path)) {
|
||||
Settings settings = Settings.builder().loadFromStream(path.toString(), in).build();
|
||||
final String[] trustNodeNames = settings.getAsArray(RESTRICTIONS_KEY_SUBJECT_NAME);
|
||||
return new CertificateTrustRestrictions(Arrays.asList(trustNodeNames));
|
||||
}
|
||||
Settings settings = Settings.builder().loadFromPath(path).build();
|
||||
final String[] trustNodeNames = settings.getAsArray(RESTRICTIONS_KEY_SUBJECT_NAME);
|
||||
return new CertificateTrustRestrictions(Arrays.asList(trustNodeNames));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -586,7 +586,7 @@ public class DocumentLevelSecurityTests extends SecurityIntegTestCase {
|
|||
|
||||
public void testChildrenAggregation() throws Exception {
|
||||
assertAcked(client().admin().indices().prepareCreate("test")
|
||||
.setSettings("index.version.created", Version.V_5_6_0.id)
|
||||
.setSettings(Settings.builder().put("index.version.created", Version.V_5_6_0.id))
|
||||
.addMapping("type1", "field1", "type=text", "field2", "type=text")
|
||||
.addMapping("type2", "_parent", "type=type1", "field3", "type=text,fielddata=true")
|
||||
);
|
||||
|
@ -643,7 +643,7 @@ public class DocumentLevelSecurityTests extends SecurityIntegTestCase {
|
|||
|
||||
public void testParentChild_parentField() {
|
||||
assertAcked(prepareCreate("test")
|
||||
.setSettings("index.version.created", Version.V_5_6_0.id)
|
||||
.setSettings(Settings.builder().put("index.version.created", Version.V_5_6_0.id))
|
||||
.addMapping("parent")
|
||||
.addMapping("child", "_parent", "type=parent", "field1", "type=text", "field2", "type=text", "field3", "type=text"));
|
||||
ensureGreen();
|
||||
|
|
|
@ -1221,7 +1221,7 @@ public class FieldLevelSecurityTests extends SecurityIntegTestCase {
|
|||
|
||||
public void testParentChild_parentField() {
|
||||
assertAcked(prepareCreate("test")
|
||||
.setSettings("index.version.created", Version.V_5_6_0.id)
|
||||
.setSettings(Settings.builder().put("index.version.created", Version.V_5_6_0.id))
|
||||
.addMapping("parent")
|
||||
.addMapping("child", "_parent", "type=parent"));
|
||||
ensureGreen();
|
||||
|
|
|
@ -49,16 +49,20 @@ public abstract class AbstractLicenseServiceTestCase extends ESTestCase {
|
|||
}
|
||||
|
||||
protected void setInitialState(License license, XPackLicenseState licenseState, Settings settings) {
|
||||
setInitialState(license, licenseState, settings, randomBoolean() ? "trial" : "basic");
|
||||
}
|
||||
|
||||
protected void setInitialState(License license, XPackLicenseState licenseState, Settings settings, String selfGeneratedType) {
|
||||
Path tempDir = createTempDir();
|
||||
when(environment.configFile()).thenReturn(tempDir);
|
||||
licenseType = randomBoolean() ? "trial" : "basic";
|
||||
licenseType = selfGeneratedType;
|
||||
settings = Settings.builder().put(settings).put(LicenseService.SELF_GENERATED_LICENSE_TYPE.getKey(), licenseType).build();
|
||||
licenseService = new LicenseService(settings, clusterService, clock, environment, resourceWatcherService, licenseState);
|
||||
ClusterState state = mock(ClusterState.class);
|
||||
final ClusterBlocks noBlock = ClusterBlocks.builder().build();
|
||||
when(state.blocks()).thenReturn(noBlock);
|
||||
MetaData metaData = mock(MetaData.class);
|
||||
when(metaData.custom(LicensesMetaData.TYPE)).thenReturn(new LicensesMetaData(license));
|
||||
when(metaData.custom(LicensesMetaData.TYPE)).thenReturn(new LicensesMetaData(license, null));
|
||||
when(state.metaData()).thenReturn(metaData);
|
||||
final DiscoveryNode mockNode = new DiscoveryNode("b", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
||||
when(discoveryNodes.getMasterNode()).thenReturn(mockNode);
|
||||
|
|
|
@ -65,7 +65,7 @@ public abstract class AbstractLicensesIntegrationTestCase extends ESIntegTestCas
|
|||
@Override
|
||||
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(license));
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(license, null));
|
||||
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
|
|||
public void testNotificationOnNewLicense() throws Exception {
|
||||
ClusterState oldState = ClusterState.builder(new ClusterName("a")).build();
|
||||
final License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(24));
|
||||
MetaData metaData = MetaData.builder().putCustom(LicensesMetaData.TYPE, new LicensesMetaData(license)).build();
|
||||
MetaData metaData = MetaData.builder().putCustom(LicensesMetaData.TYPE, new LicensesMetaData(license, null)).build();
|
||||
ClusterState newState = ClusterState.builder(new ClusterName("a")).metaData(metaData).build();
|
||||
licenseService.clusterChanged(new ClusterChangedEvent("simulated", newState, oldState));
|
||||
assertThat(licenseState.activeUpdates.size(), equalTo(1));
|
||||
|
@ -56,7 +56,7 @@ public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
|
|||
|
||||
public void testNoNotificationOnExistingLicense() throws Exception {
|
||||
final License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(24));
|
||||
MetaData metaData = MetaData.builder().putCustom(LicensesMetaData.TYPE, new LicensesMetaData(license)).build();
|
||||
MetaData metaData = MetaData.builder().putCustom(LicensesMetaData.TYPE, new LicensesMetaData(license, null)).build();
|
||||
ClusterState newState = ClusterState.builder(new ClusterName("a")).metaData(metaData).build();
|
||||
ClusterState oldState = ClusterState.builder(newState).build();
|
||||
licenseService.clusterChanged(new ClusterChangedEvent("simulated", newState, oldState));
|
||||
|
|
|
@ -18,9 +18,9 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
public class LicenseRegistrationTests extends AbstractLicenseServiceTestCase {
|
||||
|
||||
public void testTrialLicenseRequestOnEmptyLicenseState() throws Exception {
|
||||
public void testSelfGeneratedTrialLicense() throws Exception {
|
||||
XPackLicenseState licenseState = new XPackLicenseState();
|
||||
setInitialState(null, licenseState, Settings.EMPTY);
|
||||
setInitialState(null, licenseState, Settings.EMPTY, "trial");
|
||||
when(discoveryNodes.isLocalNodeElectedMaster()).thenReturn(true);
|
||||
licenseService.start();
|
||||
|
||||
|
@ -31,6 +31,26 @@ public class LicenseRegistrationTests extends AbstractLicenseServiceTestCase {
|
|||
LicensesMetaData licenseMetaData = stateWithLicense.metaData().custom(LicensesMetaData.TYPE);
|
||||
assertNotNull(licenseMetaData);
|
||||
assertNotNull(licenseMetaData.getLicense());
|
||||
assertFalse(licenseMetaData.isEligibleForTrial());
|
||||
assertEquals("trial", licenseMetaData.getLicense().type());
|
||||
assertEquals(clock.millis() + LicenseService.SELF_GENERATED_LICENSE_DURATION.millis(), licenseMetaData.getLicense().expiryDate());
|
||||
}
|
||||
|
||||
public void testSelfGeneratedBasicLicense() throws Exception {
|
||||
XPackLicenseState licenseState = new XPackLicenseState();
|
||||
setInitialState(null, licenseState, Settings.EMPTY, "basic");
|
||||
when(discoveryNodes.isLocalNodeElectedMaster()).thenReturn(true);
|
||||
licenseService.start();
|
||||
|
||||
ClusterState state = ClusterState.builder(new ClusterName("a")).build();
|
||||
ArgumentCaptor<ClusterStateUpdateTask> stateUpdater = ArgumentCaptor.forClass(ClusterStateUpdateTask.class);
|
||||
verify(clusterService, Mockito.times(1)).submitStateUpdateTask(any(), stateUpdater.capture());
|
||||
ClusterState stateWithLicense = stateUpdater.getValue().execute(state);
|
||||
LicensesMetaData licenseMetaData = stateWithLicense.metaData().custom(LicensesMetaData.TYPE);
|
||||
assertNotNull(licenseMetaData);
|
||||
assertNotNull(licenseMetaData.getLicense());
|
||||
assertTrue(licenseMetaData.isEligibleForTrial());
|
||||
assertEquals("basic", licenseMetaData.getLicense().type());
|
||||
assertEquals(clock.millis() + LicenseService.SELF_GENERATED_LICENSE_DURATION.millis(), licenseMetaData.getLicense().expiryDate());
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.ClusterModule;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.metadata.RepositoriesMetaData;
|
||||
|
@ -29,9 +30,10 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class LicensesMetaDataSerializationTests extends ESTestCase {
|
||||
|
||||
public void testXContentSerializationOneSignedLicense() throws Exception {
|
||||
License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2));
|
||||
LicensesMetaData licensesMetaData = new LicensesMetaData(license);
|
||||
LicensesMetaData licensesMetaData = new LicensesMetaData(license, null);
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject();
|
||||
builder.startObject("licenses");
|
||||
|
@ -40,12 +42,27 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
|
|||
builder.endObject();
|
||||
LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(createParser(builder));
|
||||
assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(license));
|
||||
assertNull(licensesMetaDataFromXContent.getMostRecentTrialVersion());
|
||||
}
|
||||
|
||||
public void testXContentSerializationOneSignedLicenseWithUsedTrial() throws Exception {
|
||||
License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2));
|
||||
LicensesMetaData licensesMetaData = new LicensesMetaData(license, Version.CURRENT);
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject();
|
||||
builder.startObject("licenses");
|
||||
licensesMetaData.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(createParser(builder));
|
||||
assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(license));
|
||||
assertEquals(licensesMetaDataFromXContent.getMostRecentTrialVersion(), Version.CURRENT);
|
||||
}
|
||||
|
||||
public void testLicenseMetadataParsingDoesNotSwallowOtherMetaData() throws Exception {
|
||||
new Licensing(Settings.EMPTY); // makes sure LicensePlugin is registered in Custom MetaData
|
||||
License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2));
|
||||
LicensesMetaData licensesMetaData = new LicensesMetaData(license);
|
||||
LicensesMetaData licensesMetaData = new LicensesMetaData(license, Version.CURRENT);
|
||||
RepositoryMetaData repositoryMetaData = new RepositoryMetaData("repo", "fs", Settings.EMPTY);
|
||||
RepositoriesMetaData repositoriesMetaData = new RepositoriesMetaData(repositoryMetaData);
|
||||
final MetaData.Builder metaDataBuilder = MetaData.builder();
|
||||
|
@ -79,7 +96,7 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
|
|||
.type(randomBoolean() ? "trial" : "basic")
|
||||
.expiryDate(issueDate + TimeValue.timeValueHours(2).getMillis());
|
||||
final License trialLicense = SelfGeneratedLicense.create(specBuilder);
|
||||
LicensesMetaData licensesMetaData = new LicensesMetaData(trialLicense);
|
||||
LicensesMetaData licensesMetaData = new LicensesMetaData(trialLicense, Version.CURRENT);
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject();
|
||||
builder.startObject("licenses");
|
||||
|
@ -88,6 +105,7 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
|
|||
builder.endObject();
|
||||
LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(createParser(builder));
|
||||
assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(trialLicense));
|
||||
assertEquals(licensesMetaDataFromXContent.getMostRecentTrialVersion(), Version.CURRENT);
|
||||
}
|
||||
|
||||
public void testLicenseTombstoneFromXContext() throws Exception {
|
||||
|
@ -101,6 +119,19 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
|
|||
assertThat(metaDataFromXContent.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE));
|
||||
}
|
||||
|
||||
public void testLicenseTombstoneWithUsedTrialFromXContext() throws Exception {
|
||||
final XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject();
|
||||
builder.startObject("licenses");
|
||||
builder.nullField("license");
|
||||
builder.field("trial_license", Version.CURRENT.toString());
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
LicensesMetaData metaDataFromXContent = getLicensesMetaDataFromXContent(createParser(builder));
|
||||
assertThat(metaDataFromXContent.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE));
|
||||
assertEquals(metaDataFromXContent.getMostRecentTrialVersion(), Version.CURRENT);
|
||||
}
|
||||
|
||||
private static LicensesMetaData getLicensesMetaDataFromXContent(XContentParser parser) throws Exception {
|
||||
parser.nextToken(); // consume null
|
||||
parser.nextToken(); // consume "licenses"
|
||||
|
|
|
@ -348,6 +348,6 @@ public class TestUtils {
|
|||
}
|
||||
|
||||
public static void putLicense(MetaData.Builder builder, License license) {
|
||||
builder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(license));
|
||||
builder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(license, null));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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.license;
|
||||
|
||||
import org.elasticsearch.client.Response;
|
||||
import org.elasticsearch.client.ResponseException;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.transport.Netty4Plugin;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.elasticsearch.test.ESIntegTestCase.Scope.SUITE;
|
||||
|
||||
@ESIntegTestCase.ClusterScope(scope = SUITE)
|
||||
public class UpgradeToTrialTests extends AbstractLicensesIntegrationTestCase {
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return Settings.builder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("node.data", true)
|
||||
.put(LicenseService.SELF_GENERATED_LICENSE_TYPE.getKey(), "basic")
|
||||
.put(NetworkModule.HTTP_ENABLED.getKey(), true).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
||||
return Arrays.asList(XPackPlugin.class, Netty4Plugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Plugin>> transportClientPlugins() {
|
||||
return nodePlugins();
|
||||
}
|
||||
|
||||
public void testUpgradeToTrial() throws Exception {
|
||||
LicensingClient licensingClient = new LicensingClient(client());
|
||||
GetLicenseResponse getLicenseResponse = licensingClient.prepareGetLicense().get();
|
||||
|
||||
assertEquals("basic", getLicenseResponse.license().type());
|
||||
|
||||
RestClient restClient = getRestClient();
|
||||
Response response = restClient.performRequest("GET", "/_xpack/license/trial_status");
|
||||
String body = Streams.copyToString(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8));
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
assertEquals("{\"eligible_to_start_trial\":true}", body);
|
||||
|
||||
Response response2 = restClient.performRequest("POST", "/_xpack/license/start_trial");
|
||||
String body2 = Streams.copyToString(new InputStreamReader(response2.getEntity().getContent(), StandardCharsets.UTF_8));
|
||||
assertEquals(200, response2.getStatusLine().getStatusCode());
|
||||
assertEquals("{\"trial_was_started\":true}", body2);
|
||||
|
||||
Response response3 = restClient.performRequest("GET", "/_xpack/license/trial_status");
|
||||
String body3 = Streams.copyToString(new InputStreamReader(response3.getEntity().getContent(), StandardCharsets.UTF_8));
|
||||
assertEquals(200, response3.getStatusLine().getStatusCode());
|
||||
assertEquals("{\"eligible_to_start_trial\":false}", body3);
|
||||
|
||||
ResponseException ex = expectThrows(ResponseException.class,
|
||||
() -> restClient.performRequest("POST", "/_xpack/license/start_trial"));
|
||||
Response response4 = ex.getResponse();
|
||||
String body4 = Streams.copyToString(new InputStreamReader(response4.getEntity().getContent(), StandardCharsets.UTF_8));
|
||||
assertEquals(403, response4.getStatusLine().getStatusCode());
|
||||
assertTrue(body4.contains("\"trial_was_started\":false"));
|
||||
assertTrue(body4.contains("\"error_message\":\"Operation failed: Trial was already activated.\""));
|
||||
}
|
||||
}
|
|
@ -214,7 +214,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase {
|
|||
// Disable native ML autodetect_process as the c++ controller won't be available
|
||||
.put(MachineLearning.AUTODETECT_PROCESS.getKey(), false);
|
||||
Settings customSettings = customSecuritySettingsSource.nodeSettings(nodeOrdinal);
|
||||
builder.put(customSettings.getAsMap()); // handle secure settings separately
|
||||
builder.put(customSettings, false); // handle secure settings separately
|
||||
Settings.Builder customBuilder = Settings.builder().put(customSettings);
|
||||
if (customBuilder.getSecureSettings() != null) {
|
||||
SecuritySettingsSource.addSecureSettings(builder, secureSettings ->
|
||||
|
|
|
@ -79,7 +79,7 @@ public class GraphTests extends XPackSingleNodeTestCase {
|
|||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
assertAcked(client().admin().indices().prepareCreate("test")
|
||||
.setSettings(SETTING_NUMBER_OF_SHARDS, 2, SETTING_NUMBER_OF_REPLICAS, 0)
|
||||
.setSettings(Settings.builder().put(SETTING_NUMBER_OF_SHARDS, 2).put(SETTING_NUMBER_OF_REPLICAS, 0))
|
||||
.addMapping("type",
|
||||
"decade", "type=keyword",
|
||||
"people", "type=keyword",
|
||||
|
|
|
@ -92,16 +92,12 @@ public class MonitoringSettingsIntegTests extends MonitoringIntegTestCase {
|
|||
MonitoringSettings.JOB_STATS_TIMEOUT};
|
||||
for (Setting<?> setting : monitoringSettings) {
|
||||
if (setting.isDynamic()) {
|
||||
Object updated = null;
|
||||
if (setting.get(Settings.EMPTY) instanceof TimeValue) {
|
||||
updated = newRandomTimeValue();
|
||||
transientSettings.put(setting.getKey(), updated);
|
||||
transientSettings.put(setting.getKey(), newRandomTimeValue().toString());
|
||||
} else if (setting.get(Settings.EMPTY) instanceof Boolean) {
|
||||
updated = randomBoolean();
|
||||
transientSettings.put(setting.getKey(), updated);
|
||||
transientSettings.put(setting.getKey(), randomBoolean());
|
||||
} else if (setting.get(Settings.EMPTY) instanceof List) {
|
||||
updated = randomStringArray();
|
||||
transientSettings.putArray(setting.getKey(), (String[]) updated);
|
||||
transientSettings.putArray(setting.getKey(), randomStringArray());
|
||||
} else {
|
||||
fail("unknown dynamic setting [" + setting + "]");
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ public class TransportMonitoringBulkActionTests extends ESTestCase {
|
|||
|
||||
final MonitoringBulkRequest request = new MonitoringBulkRequest();
|
||||
|
||||
final MonitoredSystem system = randomFrom(MonitoredSystem.KIBANA, MonitoredSystem.BEATS, MonitoredSystem.LOGSTASH);
|
||||
final MonitoredSystem system = randomFrom(MonitoredSystem.KIBANA, MonitoredSystem.LOGSTASH);
|
||||
final String type = randomAlphaOfLength(5);
|
||||
final String id = randomBoolean() ? randomAlphaOfLength(5) : null;
|
||||
final long timestamp = randomNonNegativeLong();
|
||||
|
@ -198,7 +198,7 @@ public class TransportMonitoringBulkActionTests extends ESTestCase {
|
|||
public void testAsyncActionCreateMonitoringDocs() throws Exception {
|
||||
final List<MonitoringBulkDoc> docs = new ArrayList<>();
|
||||
|
||||
final MonitoredSystem system = randomFrom(MonitoredSystem.KIBANA, MonitoredSystem.BEATS, MonitoredSystem.LOGSTASH);
|
||||
final MonitoredSystem system = randomFrom(MonitoredSystem.KIBANA, MonitoredSystem.LOGSTASH);
|
||||
final String type = randomAlphaOfLength(5);
|
||||
final String id = randomBoolean() ? randomAlphaOfLength(5) : null;
|
||||
final long timestamp = randomBoolean() ? randomNonNegativeLong() : 0L;
|
||||
|
@ -235,7 +235,7 @@ public class TransportMonitoringBulkActionTests extends ESTestCase {
|
|||
|
||||
public void testAsyncActionCreateMonitoringDocWithNoTimestamp() throws Exception {
|
||||
final MonitoringBulkDoc monitoringBulkDoc =
|
||||
new MonitoringBulkDoc(MonitoredSystem.BEATS, "_type", "_id", 0L, 0L, BytesArray.EMPTY, XContentType.JSON);
|
||||
new MonitoringBulkDoc(MonitoredSystem.LOGSTASH, "_type", "_id", 0L, 0L, BytesArray.EMPTY, XContentType.JSON);
|
||||
|
||||
final MonitoringDoc monitoringDoc =
|
||||
new TransportMonitoringBulkAction.AsyncAction(null, null, null, "", 456L, null).createMonitoringDoc(monitoringBulkDoc);
|
||||
|
|
|
@ -96,8 +96,6 @@ public class MonitoringTemplateUtilsTests extends ESTestCase {
|
|||
DateTimeFormatter formatter = DateTimeFormat.forPattern("YYYY.MM.dd").withZoneUTC();
|
||||
assertThat(indexName(formatter, MonitoredSystem.ES, timestamp),
|
||||
equalTo(".monitoring-es-" + TEMPLATE_VERSION + "-2017.08.03"));
|
||||
assertThat(indexName(formatter, MonitoredSystem.BEATS, timestamp),
|
||||
equalTo(".monitoring-beats-" + TEMPLATE_VERSION + "-2017.08.03"));
|
||||
assertThat(indexName(formatter, MonitoredSystem.KIBANA, timestamp),
|
||||
equalTo(".monitoring-kibana-" + TEMPLATE_VERSION + "-2017.08.03"));
|
||||
assertThat(indexName(formatter, MonitoredSystem.LOGSTASH, timestamp),
|
||||
|
@ -106,8 +104,6 @@ public class MonitoringTemplateUtilsTests extends ESTestCase {
|
|||
formatter = DateTimeFormat.forPattern("YYYY-dd-MM-HH.mm.ss").withZoneUTC();
|
||||
assertThat(indexName(formatter, MonitoredSystem.ES, timestamp),
|
||||
equalTo(".monitoring-es-" + TEMPLATE_VERSION + "-2017-03-08-13.47.58"));
|
||||
assertThat(indexName(formatter, MonitoredSystem.BEATS, timestamp),
|
||||
equalTo(".monitoring-beats-" + TEMPLATE_VERSION + "-2017-03-08-13.47.58"));
|
||||
assertThat(indexName(formatter, MonitoredSystem.KIBANA, timestamp),
|
||||
equalTo(".monitoring-kibana-" + TEMPLATE_VERSION + "-2017-03-08-13.47.58"));
|
||||
assertThat(indexName(formatter, MonitoredSystem.LOGSTASH, timestamp),
|
||||
|
|
|
@ -61,9 +61,9 @@ public class HttpExporterResourceTests extends AbstractPublishableHttpResourceTe
|
|||
private final boolean createOldTemplates = randomBoolean();
|
||||
|
||||
/**
|
||||
* kibana, logstash, beats
|
||||
* kibana, logstash (and beats in the future)
|
||||
*/
|
||||
private final int EXPECTED_TEMPLATES = 5 + (createOldTemplates ? OLD_TEMPLATE_IDS.length : 0);
|
||||
private final int EXPECTED_TEMPLATES = TEMPLATE_IDS.length + (createOldTemplates ? OLD_TEMPLATE_IDS.length : 0);
|
||||
private final int EXPECTED_PIPELINES = PIPELINE_IDS.length;
|
||||
private final int EXPECTED_WATCHES = ClusterAlertsUtil.WATCH_IDS.length;
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils.OLD_TEMPLATE_IDS;
|
||||
import static org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils.PIPELINE_IDS;
|
||||
import static org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils.TEMPLATE_IDS;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
@ -347,7 +348,7 @@ public class HttpExporterTests extends ESTestCase {
|
|||
assertThat(multiResource.getResources().size(),
|
||||
equalTo(version + templates.size() + pipelines.size() + watcherCheck.size()));
|
||||
assertThat(version, equalTo(1));
|
||||
assertThat(templates, hasSize(createOldTemplates ? 5 + OLD_TEMPLATE_IDS.length : 5));
|
||||
assertThat(templates, hasSize(createOldTemplates ? TEMPLATE_IDS.length + OLD_TEMPLATE_IDS.length : TEMPLATE_IDS.length));
|
||||
assertThat(pipelines, hasSize(useIngest ? PIPELINE_IDS.length : 0));
|
||||
assertThat(watcherCheck, hasSize(clusterAlertManagement ? 1 : 0));
|
||||
assertThat(watches, hasSize(clusterAlertManagement ? ClusterAlertsUtil.WATCH_IDS.length : 0));
|
||||
|
|
|
@ -55,7 +55,6 @@ import java.util.stream.Collectors;
|
|||
import static org.elasticsearch.search.aggregations.AggregationBuilders.max;
|
||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.elasticsearch.xpack.monitoring.MonitoredSystem.BEATS;
|
||||
import static org.elasticsearch.xpack.monitoring.MonitoredSystem.KIBANA;
|
||||
import static org.elasticsearch.xpack.monitoring.MonitoredSystem.LOGSTASH;
|
||||
import static org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils.PIPELINE_IDS;
|
||||
|
@ -231,12 +230,9 @@ public class LocalExporterIntegTests extends LocalExporterIntegTestCase {
|
|||
templates.add(".monitoring-es");
|
||||
templates.add(".monitoring-kibana");
|
||||
templates.add(".monitoring-logstash");
|
||||
templates.add(".monitoring-beats");
|
||||
|
||||
GetIndexTemplatesResponse response =
|
||||
client().admin().indices().prepareGetTemplates(".monitoring-*").get();
|
||||
Set<String> actualTemplates = response.getIndexTemplates().stream()
|
||||
.map(IndexTemplateMetaData::getName).collect(Collectors.toSet());
|
||||
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates(".monitoring-*").get();
|
||||
Set<String> actualTemplates = response.getIndexTemplates().stream().map(IndexTemplateMetaData::getName).collect(Collectors.toSet());
|
||||
assertEquals(templates, actualTemplates);
|
||||
}
|
||||
|
||||
|
@ -330,7 +326,7 @@ public class LocalExporterIntegTests extends LocalExporterIntegTestCase {
|
|||
}
|
||||
|
||||
private static MonitoringBulkDoc createMonitoringBulkDoc() throws IOException {
|
||||
final MonitoredSystem system = randomFrom(BEATS, KIBANA, LOGSTASH);
|
||||
final MonitoredSystem system = randomFrom(KIBANA, LOGSTASH);
|
||||
final XContentType xContentType = randomFrom(XContentType.values());
|
||||
final BytesReference source;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.apache.http.entity.ContentType;
|
|||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.nio.entity.NStringEntity;
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.client.Response;
|
||||
|
@ -63,6 +64,7 @@ import static org.hamcrest.Matchers.not;
|
|||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
@LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/2609")
|
||||
public class MonitoringIT extends ESRestTestCase {
|
||||
|
||||
private static final String BASIC_AUTH_VALUE = basicAuthHeaderValue("x_pack_rest_user", TEST_PASSWORD_SECURE_STRING);
|
||||
|
@ -410,7 +412,7 @@ public class MonitoringIT extends ESRestTestCase {
|
|||
assertEquals(5, source.size());
|
||||
|
||||
final Map<String, Object> nodeStats = (Map<String, Object>) source.get(NodeStatsMonitoringDoc.TYPE);
|
||||
assertEquals(9, nodeStats.size());
|
||||
assertEquals(Constants.WINDOWS ? 8 : 9, nodeStats.size());
|
||||
|
||||
NodeStatsMonitoringDoc.XCONTENT_FILTERS.forEach(filter -> {
|
||||
if (Constants.WINDOWS && filter.startsWith("node_stats.os.cpu.load_average")) {
|
||||
|
@ -650,6 +652,6 @@ public class MonitoringIT extends ESRestTestCase {
|
|||
* Returns a {@link MonitoredSystem} supported by the Monitoring Bulk API
|
||||
*/
|
||||
private static MonitoredSystem randomSystem() {
|
||||
return randomFrom(MonitoredSystem.LOGSTASH, MonitoredSystem.KIBANA, MonitoredSystem.BEATS);
|
||||
return randomFrom(MonitoredSystem.LOGSTASH, MonitoredSystem.KIBANA);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ public class JiraAccountTests extends ESTestCase {
|
|||
for (Map.Entry<String, Object> setting : defaults.entrySet()) {
|
||||
String key = "xpack.notification.jira.account." + name + "." + JiraAccount.ISSUE_DEFAULTS_SETTING + "." + setting.getKey();
|
||||
if (setting.getValue() instanceof String) {
|
||||
builder.put(key, setting.getValue());
|
||||
builder.put(key, setting.getValue().toString());
|
||||
} else if (setting.getValue() instanceof Map) {
|
||||
builder.putProperties((Map) setting.getValue(), s -> key + "." + s);
|
||||
}
|
||||
|
|
|
@ -226,17 +226,19 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase {
|
|||
}
|
||||
};
|
||||
final Settings settingsTemplate = cluster2SettingsSource.nodeSettings(0);
|
||||
|
||||
Map<String, String> asMap = new HashMap<>(settingsTemplate.getAsMap());
|
||||
asMap.remove(NodeEnvironment.MAX_LOCAL_STORAGE_NODES_SETTING.getKey());
|
||||
Settings.Builder tribe1Defaults = Settings.builder();
|
||||
Settings.Builder tribe2Defaults = Settings.builder();
|
||||
for (Map.Entry<String, String> entry : asMap.entrySet()) {
|
||||
if (entry.getKey().startsWith("path.")) {
|
||||
continue;
|
||||
} else if (entry.getKey().equals("transport.tcp.port")) {
|
||||
continue;
|
||||
Settings tribeSettings = settingsTemplate.filter(k -> {
|
||||
if (k.equals(NodeEnvironment.MAX_LOCAL_STORAGE_NODES_SETTING.getKey())) {
|
||||
return false;
|
||||
} if (k.startsWith("path.")) {
|
||||
return false;
|
||||
} else if (k.equals("transport.tcp.port")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
for (Map.Entry<String, String> entry : tribeSettings.getAsMap().entrySet()) {
|
||||
tribe1Defaults.put("tribe.t1." + entry.getKey(), entry.getValue());
|
||||
tribe2Defaults.put("tribe.t2." + entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
@ -255,7 +257,7 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase {
|
|||
|
||||
Settings merged = Settings.builder()
|
||||
.put(internalCluster().getDefaultSettings())
|
||||
.put(asMap)
|
||||
.put(tribeSettings, false)
|
||||
.put("tribe.t1.cluster.name", internalCluster().getClusterName())
|
||||
.put("tribe.t2.cluster.name", cluster2.getClusterName())
|
||||
.put("tribe.blocks.write", false)
|
||||
|
|
|
@ -123,5 +123,8 @@ public class PrivilegeTests extends ESTestCase {
|
|||
assertThat(predicate.test("indices:admin/mapping/put"), is(true));
|
||||
assertThat(predicate.test("indices:admin/mapping/whatever"), is(false));
|
||||
assertThat(predicate.test("internal:transport/proxy/indices:data/read/query"), is(false));
|
||||
assertThat(predicate.test("indices:admin/seq_no/global_checkpoint_sync"), is(true));
|
||||
assertThat(predicate.test("indices:admin/seq_no/global_checkpoint_sync[p]"), is(true));
|
||||
assertThat(predicate.test("indices:admin/seq_no/global_checkpoint_sync[r]"), is(true));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,6 @@ public class ServerTransportFilterIntegrationTests extends SecurityIntegTestCase
|
|||
|
||||
// test that starting up a node works
|
||||
Settings.Builder nodeSettings = Settings.builder()
|
||||
.put()
|
||||
.put("node.name", "my-test-node")
|
||||
.put("network.host", "localhost")
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
|
|
|
@ -95,7 +95,7 @@ public class DNSOnlyHostnameVerificationTests extends SecurityIntegTestCase {
|
|||
public Settings nodeSettings(int nodeOrdinal) {
|
||||
Settings defaultSettings = super.nodeSettings(nodeOrdinal);
|
||||
Settings.Builder builder = Settings.builder()
|
||||
.put(defaultSettings.filter((s) -> s.startsWith("xpack.ssl.") == false).getAsMap())
|
||||
.put(defaultSettings.filter((s) -> s.startsWith("xpack.ssl.") == false), false)
|
||||
.put("transport.host", hostName);
|
||||
Path keystorePath = nodeConfigPath(nodeOrdinal).resolve("keystore.jks");
|
||||
try (OutputStream os = Files.newOutputStream(keystorePath)) {
|
||||
|
|
|
@ -31,7 +31,7 @@ public class IPHostnameVerificationTests extends SecurityIntegTestCase {
|
|||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
Settings settings = super.nodeSettings(nodeOrdinal);
|
||||
Settings.Builder builder = Settings.builder()
|
||||
.put(settings.filter((s) -> s.startsWith("xpack.ssl.") == false).getAsMap());
|
||||
.put(settings.filter((s) -> s.startsWith("xpack.ssl.") == false), false);
|
||||
settings = builder.build();
|
||||
|
||||
// The default Unicast test behavior is to use 'localhost' with the port number. For this test we need to use IP
|
||||
|
|
|
@ -162,3 +162,5 @@ indices:data/write/delete/byquery
|
|||
indices:data/write/reindex
|
||||
cluster:admin/xpack/deprecation/info
|
||||
cluster:admin/xpack/ml/job/forecast
|
||||
cluster:admin/xpack/license/start_trial
|
||||
cluster:admin/xpack/license/trial_status
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"xpack.license.get_trial_status": {
|
||||
"documentation": "https://www.elastic.co/guide/en/x-pack/current/license-management.html",
|
||||
"methods": ["GET"],
|
||||
"url": {
|
||||
"path": "/_xpack/license/trial_status",
|
||||
"paths": ["/_xpack/license/trial_status"],
|
||||
"parts" : {
|
||||
},
|
||||
"params": {
|
||||
}
|
||||
},
|
||||
"body": null
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"xpack.license.post_start_trial": {
|
||||
"documentation": "https://www.elastic.co/guide/en/x-pack/current/license-management.html",
|
||||
"methods": ["POST"],
|
||||
"url": {
|
||||
"path": "/_xpack/license/start_trial",
|
||||
"paths": ["/_xpack/license/start_trial"],
|
||||
"parts" : {
|
||||
},
|
||||
"params": {
|
||||
}
|
||||
},
|
||||
"body": null
|
||||
}
|
||||
}
|
|
@ -161,7 +161,7 @@
|
|||
|
||||
- do:
|
||||
xpack.monitoring.bulk:
|
||||
system_id: "beats"
|
||||
system_id: "logstash"
|
||||
system_api_version: "6"
|
||||
interval: "5s"
|
||||
body:
|
||||
|
@ -183,17 +183,17 @@
|
|||
|
||||
- do:
|
||||
search:
|
||||
index: .monitoring-beats-*
|
||||
index: .monitoring-logstash-*
|
||||
- match: { hits.total: 2 }
|
||||
|
||||
- do:
|
||||
indices.close:
|
||||
index: .monitoring-beats-*
|
||||
index: .monitoring-logstash-*
|
||||
|
||||
- do:
|
||||
catch: /export_exception/
|
||||
xpack.monitoring.bulk:
|
||||
system_id: "beats"
|
||||
system_id: "logstash"
|
||||
system_api_version: "6"
|
||||
interval: "5s"
|
||||
body:
|
||||
|
|
|
@ -38,7 +38,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
|||
protected Settings externalClusterClientSettings() {
|
||||
return Settings.builder()
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW.toString())
|
||||
.put(NetworkModule.TRANSPORT_TYPE_KEY, "security4")
|
||||
.build();
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
|||
.put("cluster.name", clusterName)
|
||||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toAbsolutePath().toString())
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW.toString())
|
||||
.build();
|
||||
try (TransportClient client = new PreBuiltXPackTransportClient(settings)) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
|
@ -98,7 +98,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
|||
.put("cluster.name", clusterName)
|
||||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toAbsolutePath().toString())
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER + randomAlphaOfLength(1))
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW.toString())
|
||||
.build();
|
||||
try (TransportClient client = new PreBuiltXPackTransportClient(settings)) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
|
|
|
@ -40,7 +40,7 @@ public class CustomRolesProviderIT extends ESIntegTestCase {
|
|||
protected Settings externalClusterClientSettings() {
|
||||
return Settings.builder()
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW.toString())
|
||||
.put(NetworkModule.TRANSPORT_TYPE_KEY, "security4")
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.test;
|
||||
|
||||
import org.elasticsearch.Build;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
|
@ -101,6 +102,7 @@ public class LicensingTribeIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
public void testLicensePropagateToTribeNode() throws Exception {
|
||||
assumeTrue("License is only valid when tested against snapshot/test keys", Build.CURRENT.isSnapshot());
|
||||
// test that auto-generated trial license propagates to tribe
|
||||
assertBusy(() -> {
|
||||
GetLicenseResponse getLicenseResponse = new LicensingClient(tribeNode.client()).prepareGetLicense().get();
|
||||
|
|
Loading…
Reference in New Issue