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
|
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.
|
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]
|
[source,js]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
@ -14,8 +29,7 @@ GET _xpack/security/_authenticate
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
// CONSOLE
|
// CONSOLE
|
||||||
|
|
||||||
A successful call returns a JSON structure that shows what roles are assigned
|
The following example output provides information about the "rdeniro" user:
|
||||||
to the user as well as any assigned metadata.
|
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
|
@ -3,11 +3,37 @@
|
||||||
=== Change Password API
|
=== Change Password API
|
||||||
|
|
||||||
The Change Password API enables you to submit a request to change the password
|
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
|
of a user.
|
||||||
`manage_security` privilege can change passwords of other users.
|
|
||||||
|
|
||||||
To change the password of the logged in user, submit a POST request to the
|
==== Request
|
||||||
`_xpack/security/user/_password` endpoint:
|
|
||||||
|
`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]
|
[source,js]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
|
@ -5,6 +5,31 @@
|
||||||
The Clear Cache API evicts users from the user cache. You can completely clear
|
The Clear Cache API evicts users from the user cache. You can completely clear
|
||||||
the cache or evict specific users.
|
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:
|
For example, to evict all users cached by the `file` realm:
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
|
@ -29,6 +54,3 @@ list:
|
||||||
POST _xpack/security/realm/default_file,ldap1/_clear_cache
|
POST _xpack/security/realm/default_file,ldap1/_clear_cache
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
// CONSOLE
|
// 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
|
The `has_privileges` API allows you to determine whether the logged in user has
|
||||||
a specified list of privileges.
|
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.
|
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
|
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].
|
{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]
|
[source,js]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
@ -34,8 +62,7 @@ GET _xpack/security/user/_has_privileges
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
// CONSOLE
|
// CONSOLE
|
||||||
|
|
||||||
A successful call returns a JSON structure that shows whether each specified
|
The following example output indicates which privileges the "rdeniro" user has:
|
||||||
privilege is assigned to the user
|
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
|
@ -2,15 +2,69 @@
|
||||||
[[security-api-role-mapping]]
|
[[security-api-role-mapping]]
|
||||||
=== Role Mapping APIs
|
=== Role Mapping APIs
|
||||||
|
|
||||||
The Role Mapping API enables you to add, remove, and retrieve role-mappings.
|
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.
|
|
||||||
|
|
||||||
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
|
used solely as an identifier to facilitate interaction via the API, and does
|
||||||
not affect the behavior of the mapping in any way.
|
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]]
|
[[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:
|
endpoint:
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
|
@ -28,14 +82,10 @@ POST /_xpack/security/role_mapping/administrators
|
||||||
}
|
}
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
// CONSOLE
|
// 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.
|
is performed.
|
||||||
<2> Metadata is optional
|
<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
|
A successful call returns a JSON structure that shows whether the mapping has
|
||||||
been created or updated.
|
been created or updated.
|
||||||
|
|
||||||
|
@ -51,7 +101,7 @@ been created or updated.
|
||||||
<1> When an existing mapping is updated, `created` is set to false.
|
<1> When an existing mapping is updated, `created` is set to false.
|
||||||
|
|
||||||
[[security-api-get-role-mapping]]
|
[[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:
|
`/_xpack/security/role_mapping/<name>` endpoint:
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
|
@ -61,7 +111,7 @@ GET /_xpack/security/role_mapping/administrators
|
||||||
// CONSOLE
|
// CONSOLE
|
||||||
// TEST[continued]
|
// 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
|
names of the request mappings, and the values are
|
||||||
the JSON representation of those mappings.
|
the JSON representation of those mappings.
|
||||||
If there is no mapping with the requested name, the
|
If there is no mapping with the requested name, the
|
||||||
|
@ -107,7 +157,7 @@ GET /_xpack/security/role_mapping
|
||||||
// TEST[continued]
|
// TEST[continued]
|
||||||
|
|
||||||
[[security-api-delete-role-mapping]]
|
[[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:
|
`/_xpack/security/role_mapping/<name>` endpoint:
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
|
|
|
@ -3,10 +3,72 @@
|
||||||
=== Role Management APIs
|
=== Role Management APIs
|
||||||
|
|
||||||
The Roles API enables you to add, remove, and retrieve roles in the `native`
|
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.
|
privilege.
|
||||||
|
|
||||||
NOTE: The Roles API is now the preferred way to manage roles.
|
|
||||||
|
==== Examples
|
||||||
|
|
||||||
[[security-api-put-role]]
|
[[security-api-put-role]]
|
||||||
To add a role, submit a PUT or POST request to the `/_xpack/security/role/<rolename>`
|
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
|
// 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
|
A successful call returns a JSON structure that shows whether the role has been
|
||||||
created or updated.
|
created or updated.
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,54 @@
|
||||||
=== Token Management APIs
|
=== Token Management APIs
|
||||||
|
|
||||||
The `token` API enables you to create and invalidate bearer tokens for access
|
The `token` API enables you to create and invalidate bearer tokens for access
|
||||||
without requiring basic authentication. The get token API takes the same
|
without requiring basic authentication.
|
||||||
parameters as a typical OAuth 2.0 token API except for the use of a JSON
|
|
||||||
request body.
|
|
||||||
|
|
||||||
|
==== 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]]
|
[[security-api-get-token]]
|
||||||
To obtain a token, submit a POST request to the `/_xpack/security/oauth2/token`
|
To obtain a token, submit a POST request to the `/_xpack/security/oauth2/token`
|
||||||
endpoint.
|
endpoint.
|
||||||
|
@ -22,22 +66,8 @@ POST /_xpack/security/oauth2/token
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
// CONSOLE
|
// CONSOLE
|
||||||
|
|
||||||
.Token Request Fields
|
The following example output contains the access token, the amount of time (in
|
||||||
[cols="4,^2,10"]
|
seconds) that the token expires in, and the type:
|
||||||
|=======================
|
|
||||||
| 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.
|
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
@ -49,9 +79,6 @@ available.
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
// TESTRESPONSE[s/dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==/$body.access_token/]
|
// 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
|
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
|
`Authorization` header with a value having the prefix `Bearer ` followed
|
||||||
by the value of the `access_token`.
|
by the value of the `access_token`.
|
||||||
|
@ -62,10 +89,8 @@ curl -H "Authorization: Bearer dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvb
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
[[security-api-invalidate-token]]
|
[[security-api-invalidate-token]]
|
||||||
The tokens returned from this API have a finite period of time for which they
|
If a token must be invalidated immediately, you can do so by submitting a DELETE
|
||||||
are valid and after that time period, they can no longer be used. However, if
|
request to `/_xpack/security/oauth2/token`. For example:
|
||||||
a token must be invalidated immediately, you can do so by submitting a DELETE
|
|
||||||
request to `/_xpack/security/oauth2/token`.
|
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
|
@ -4,18 +4,78 @@
|
||||||
|
|
||||||
The `user` API enables you to create, read, update, and delete users from the
|
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*.
|
`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.
|
To use this API, you must have at least the `manage_security` cluster privilege.
|
||||||
|
|
||||||
|
|
||||||
|
==== Examples
|
||||||
|
|
||||||
[[security-api-put-user]]
|
[[security-api-put-user]]
|
||||||
To add a user, submit a PUT or POST request to the `/_xpack/security/user/<username>`
|
To add a user, submit a PUT or POST request to the `/_xpack/security/user/<username>`
|
||||||
endpoint.
|
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]
|
[source,js]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
POST /_xpack/security/user/jacknich
|
POST /_xpack/security/user/jacknich
|
||||||
|
@ -31,20 +91,6 @@ POST /_xpack/security/user/jacknich
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
// CONSOLE
|
// 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
|
A successful call returns a JSON structure that shows whether the user has been
|
||||||
created or updated.
|
created or updated.
|
||||||
|
|
||||||
|
@ -59,11 +105,7 @@ created or updated.
|
||||||
// TESTRESPONSE
|
// TESTRESPONSE
|
||||||
<1> When an existing user is updated, `created` is set to false.
|
<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
|
After you add a user through the Users API, requests from that user can be
|
||||||
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
|
|
||||||
authenticated.
|
authenticated.
|
||||||
|
|
||||||
[source,shell]
|
[source,shell]
|
||||||
|
|
|
@ -85,6 +85,9 @@ change between releases.
|
||||||
Grants the minimum privileges required for any user of {kib}. This role grants
|
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.
|
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` ::
|
[[built-in-roles-logstash-system]] `logstash_system` ::
|
||||||
Grants access necessary for the Logstash system user to send system-level data
|
Grants access necessary for the Logstash system user to send system-level data
|
||||||
(such as monitoring) to {es}. For more information, see
|
(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.message.ParameterizedMessage;
|
||||||
import org.apache.logging.log4j.util.Supplier;
|
import org.apache.logging.log4j.util.Supplier;
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
|
import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
|
||||||
import org.elasticsearch.cluster.ClusterChangedEvent;
|
import org.elasticsearch.cluster.ClusterChangedEvent;
|
||||||
|
@ -227,8 +228,14 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClusterState execute(ClusterState currentState) throws Exception {
|
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
MetaData currentMetadata = currentState.metaData();
|
||||||
mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(newLicense));
|
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();
|
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);
|
return TimeValue.timeValueHours(days * 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +280,9 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
||||||
final LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
|
final LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
|
||||||
if (currentLicenses.getLicense() != LicensesMetaData.LICENSE_TOMBSTONE) {
|
if (currentLicenses.getLicense() != LicensesMetaData.LICENSE_TOMBSTONE) {
|
||||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
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();
|
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||||
} else {
|
} else {
|
||||||
return currentState;
|
return currentState;
|
||||||
|
@ -287,6 +296,40 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
||||||
return license == LicensesMetaData.LICENSE_TOMBSTONE ? null : license;
|
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.
|
* 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
|
* 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) {
|
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
||||||
LicensesMetaData licensesMetaData = newState.metaData().custom(LicensesMetaData.TYPE);
|
LicensesMetaData licensesMetaData = newState.metaData().custom(LicensesMetaData.TYPE);
|
||||||
if (logger.isDebugEnabled()) {
|
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 {
|
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||||
final MetaData metaData = currentState.metaData();
|
final MetaData metaData = currentState.metaData();
|
||||||
final LicensesMetaData currentLicensesMetaData = metaData.custom(LicensesMetaData.TYPE);
|
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
|
// do not generate a trial license if any license is present
|
||||||
if (currentLicensesMetaData == null) {
|
if (currentLicensesMetaData == null) {
|
||||||
long issueDate = clock.millis();
|
|
||||||
String type = SELF_GENERATED_LICENSE_TYPE.get(settings);
|
String type = SELF_GENERATED_LICENSE_TYPE.get(settings);
|
||||||
if (validSelfGeneratedType(type) == false) {
|
if (validSelfGeneratedType(type) == false) {
|
||||||
throw new IllegalArgumentException("Illegal self generated license type [" + type +
|
throw new IllegalArgumentException("Illegal self generated license type [" + type +
|
||||||
"]. Must be trial or basic.");
|
"]. Must be trial or basic.");
|
||||||
}
|
}
|
||||||
License.Builder specBuilder = License.builder()
|
|
||||||
.uid(UUID.randomUUID().toString())
|
return updateWithLicense(currentState, type);
|
||||||
.issuedTo(clusterService.getClusterName().value())
|
} else {
|
||||||
.maxNodes(selfGeneratedLicenseMaxNodes)
|
return currentState;
|
||||||
.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 currentState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Override
|
||||||
protected void doStart() throws ElasticsearchException {
|
protected void doStart() throws ElasticsearchException {
|
||||||
clusterService.addListener(this);
|
clusterService.addListener(this);
|
||||||
|
@ -436,7 +491,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
||||||
* Additionally schedules license expiry notifications and event callbacks
|
* Additionally schedules license expiry notifications and event callbacks
|
||||||
* relative to the current license's expiry
|
* relative to the current license's expiry
|
||||||
*/
|
*/
|
||||||
void onUpdate(final LicensesMetaData currentLicensesMetaData) {
|
private void onUpdate(final LicensesMetaData currentLicensesMetaData) {
|
||||||
final License license = getLicense(currentLicensesMetaData);
|
final License license = getLicense(currentLicensesMetaData);
|
||||||
// license can be null if the trial license is yet to be auto-generated
|
// license can be null if the trial license is yet to be auto-generated
|
||||||
// in this case, it is a no-op
|
// in this case, it is a no-op
|
||||||
|
|
|
@ -5,15 +5,17 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.license;
|
package org.elasticsearch.license;
|
||||||
|
|
||||||
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.cluster.AbstractNamedDiffable;
|
import org.elasticsearch.cluster.AbstractNamedDiffable;
|
||||||
|
import org.elasticsearch.cluster.MergableCustomMetaData;
|
||||||
import org.elasticsearch.cluster.NamedDiff;
|
import org.elasticsearch.cluster.NamedDiff;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
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.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.license.License.OperationMode;
|
import org.elasticsearch.license.License.OperationMode;
|
||||||
import org.elasticsearch.cluster.MergableCustomMetaData;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
@ -48,33 +50,56 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
||||||
|
|
||||||
private License license;
|
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.license = license;
|
||||||
|
this.trialVersion = trialVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public License getLicense() {
|
public License getLicense() {
|
||||||
return license;
|
return license;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isEligibleForTrial() {
|
||||||
|
if (trialVersion == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Version.CURRENT.major > trialVersion.major;
|
||||||
|
}
|
||||||
|
|
||||||
|
Version getMostRecentTrialVersion() {
|
||||||
|
return trialVersion;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (license != null) {
|
return "LicensesMetaData{" +
|
||||||
return license.toString();
|
"license=" + license +
|
||||||
}
|
", trialVersion=" + trialVersion +
|
||||||
return "";
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
LicensesMetaData that = (LicensesMetaData) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
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
|
@Override
|
||||||
|
@ -89,6 +114,7 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
||||||
|
|
||||||
public static LicensesMetaData fromXContent(XContentParser parser) throws IOException {
|
public static LicensesMetaData fromXContent(XContentParser parser) throws IOException {
|
||||||
License license = LICENSE_TOMBSTONE;
|
License license = LICENSE_TOMBSTONE;
|
||||||
|
Version trialLicense = null;
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
|
@ -101,11 +127,14 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
||||||
} else if (token == XContentParser.Token.VALUE_NULL) {
|
} else if (token == XContentParser.Token.VALUE_NULL) {
|
||||||
license = LICENSE_TOMBSTONE;
|
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
|
@Override
|
||||||
|
@ -117,6 +146,9 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
||||||
license.toInnerXContent(builder, params);
|
license.toInnerXContent(builder, params);
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
}
|
}
|
||||||
|
if (trialVersion != null) {
|
||||||
|
builder.field(Fields.TRIAL_LICENSE, trialVersion.toString());
|
||||||
|
}
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +160,15 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
||||||
streamOutput.writeBoolean(true); // has a license
|
streamOutput.writeBoolean(true); // has a license
|
||||||
license.writeTo(streamOutput);
|
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 {
|
LicensesMetaData(StreamInput streamInput) throws IOException {
|
||||||
|
@ -136,6 +177,13 @@ class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements
|
||||||
} else {
|
} else {
|
||||||
license = LICENSE_TOMBSTONE;
|
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 {
|
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 class Fields {
|
||||||
private static final String LICENSE = "license";
|
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";
|
public static final String NAME = "license";
|
||||||
protected final Settings settings;
|
protected final Settings settings;
|
||||||
protected final boolean isTransportClient;
|
private final boolean isTransportClient;
|
||||||
private final boolean isTribeNode;
|
private final boolean isTribeNode;
|
||||||
|
|
||||||
public List<NamedWriteableRegistry.Entry> getNamedWriteables() {
|
public List<NamedWriteableRegistry.Entry> getNamedWriteables() {
|
||||||
|
@ -53,6 +53,7 @@ public class Licensing implements ActionPlugin {
|
||||||
LicensesMetaData::fromXContent));
|
LicensesMetaData::fromXContent));
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Licensing(Settings settings) {
|
public Licensing(Settings settings) {
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
isTransportClient = transportClientMode(settings);
|
isTransportClient = transportClientMode(settings);
|
||||||
|
@ -66,7 +67,9 @@ public class Licensing implements ActionPlugin {
|
||||||
}
|
}
|
||||||
return Arrays.asList(new ActionHandler<>(PutLicenseAction.INSTANCE, TransportPutLicenseAction.class),
|
return Arrays.asList(new ActionHandler<>(PutLicenseAction.INSTANCE, TransportPutLicenseAction.class),
|
||||||
new ActionHandler<>(GetLicenseAction.INSTANCE, TransportGetLicenseAction.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
|
@Override
|
||||||
|
@ -78,6 +81,8 @@ public class Licensing implements ActionPlugin {
|
||||||
if (false == isTribeNode) {
|
if (false == isTribeNode) {
|
||||||
handlers.add(new RestPutLicenseAction(settings, restController));
|
handlers.add(new RestPutLicenseAction(settings, restController));
|
||||||
handlers.add(new RestDeleteLicenseAction(settings, restController));
|
handlers.add(new RestDeleteLicenseAction(settings, restController));
|
||||||
|
handlers.add(new RestGetTrialStatus(settings, restController));
|
||||||
|
handlers.add(new RestPostStartTrialLicense(settings, restController));
|
||||||
}
|
}
|
||||||
return handlers;
|
return handlers;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,4 +39,16 @@ public class LicensingClient {
|
||||||
public void deleteLicense(DeleteLicenseRequest request, ActionListener<DeleteLicenseResponse> listener) {
|
public void deleteLicense(DeleteLicenseRequest request, ActionListener<DeleteLicenseResponse> listener) {
|
||||||
client.execute(DeleteLicenseAction.INSTANCE, request, 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"),
|
ES("es"),
|
||||||
KIBANA("kibana"),
|
KIBANA("kibana"),
|
||||||
|
// TODO: when "BEATS" is re-added, add it to tests where we randomly select "LOGSTASH"
|
||||||
LOGSTASH("logstash"),
|
LOGSTASH("logstash"),
|
||||||
BEATS("beats"),
|
|
||||||
UNKNOWN("unknown");
|
UNKNOWN("unknown");
|
||||||
|
|
||||||
private final String system;
|
private final String system;
|
||||||
|
@ -35,8 +35,6 @@ public enum MonitoredSystem {
|
||||||
return KIBANA;
|
return KIBANA;
|
||||||
case "logstash":
|
case "logstash":
|
||||||
return LOGSTASH;
|
return LOGSTASH;
|
||||||
case "beats":
|
|
||||||
return BEATS;
|
|
||||||
default:
|
default:
|
||||||
// Return an "unknown" monitored system
|
// Return an "unknown" monitored system
|
||||||
// that can easily be filtered out if
|
// 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}.
|
* 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
|
* 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<>();
|
final Map<MonitoredSystem, List<String>> versionsMap = new HashMap<>();
|
||||||
versionsMap.put(MonitoredSystem.KIBANA, allVersions);
|
versionsMap.put(MonitoredSystem.KIBANA, allVersions);
|
||||||
versionsMap.put(MonitoredSystem.LOGSTASH, allVersions);
|
versionsMap.put(MonitoredSystem.LOGSTASH, allVersions);
|
||||||
// Beats did not report data in the 5.x timeline, so it should never send the original version
|
// Beats did not report data in the 5.x timeline, so it should never send the original version [when we add it!]
|
||||||
versionsMap.put(MonitoredSystem.BEATS, Collections.singletonList(MonitoringTemplateUtils.TEMPLATE_VERSION));
|
|
||||||
supportedApiVersions = Collections.unmodifiableMap(versionsMap);
|
supportedApiVersions = Collections.unmodifiableMap(versionsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,10 @@ import org.elasticsearch.common.Booleans;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.settings.SettingsException;
|
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.HttpClient;
|
||||||
import org.elasticsearch.xpack.common.http.HttpMethod;
|
import org.elasticsearch.xpack.common.http.HttpMethod;
|
||||||
import org.elasticsearch.xpack.common.http.HttpProxy;
|
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 org.elasticsearch.xpack.common.http.auth.basic.BasicAuth;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -68,7 +73,15 @@ public class JiraAccount {
|
||||||
if (Strings.isEmpty(this.password)) {
|
if (Strings.isEmpty(this.password)) {
|
||||||
throw requiredSettingException(name, PASSWORD_SETTING);
|
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() {
|
public String getName() {
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||||
import org.elasticsearch.common.settings.Setting;
|
import org.elasticsearch.common.settings.Setting;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.settings.SettingsException;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.watcher.FileChangesListener;
|
import org.elasticsearch.watcher.FileChangesListener;
|
||||||
import org.elasticsearch.watcher.FileWatcher;
|
import org.elasticsearch.watcher.FileWatcher;
|
||||||
|
@ -127,8 +128,8 @@ public class DnRoleMapper implements UserRoleMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try (InputStream in = Files.newInputStream(path)) {
|
try {
|
||||||
Settings settings = Settings.builder().loadFromStream(path.toString(), in).build();
|
Settings settings = Settings.builder().loadFromPath(path).build();
|
||||||
|
|
||||||
Map<DN, Set<String>> dnToRoles = new HashMap<>();
|
Map<DN, Set<String>> dnToRoles = new HashMap<>();
|
||||||
Set<String> roles = settings.names();
|
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,
|
logger.debug("[{}] role mappings found in file [{}] for realm [{}/{}]", dnToRoles.size(), path.toAbsolutePath(), realmType,
|
||||||
realmName);
|
realmName);
|
||||||
return unmodifiableMap(dnToRoles);
|
return unmodifiableMap(dnToRoles);
|
||||||
} catch (IOException | YAMLException e) {
|
} catch (IOException | SettingsException e) {
|
||||||
throw new ElasticsearchException("could not read realm [" + realmType + "/" + realmName + "] role mappings file [" +
|
throw new ElasticsearchException("could not read realm [" + realmType + "/" + realmName + "] role mappings file [" +
|
||||||
path.toAbsolutePath() + "]", e);
|
path.toAbsolutePath() + "]", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@ public final class SystemPrivilege extends Privilege {
|
||||||
"cluster:admin/reroute", // added for DiskThresholdDecider.DiskListener
|
"cluster:admin/reroute", // added for DiskThresholdDecider.DiskListener
|
||||||
"indices:admin/mapping/put", // needed for recovery and shrink api
|
"indices:admin/mapping/put", // needed for recovery and shrink api
|
||||||
"indices:admin/template/put", // needed for the TemplateUpgradeService
|
"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!
|
), Automatons.patterns("internal:transport/proxy/*"))); // no proxy actions for system user!
|
||||||
|
|
||||||
private SystemPrivilege() {
|
private SystemPrivilege() {
|
||||||
|
|
|
@ -83,10 +83,8 @@ public final class RestrictedTrustConfig extends TrustConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
private CertificateTrustRestrictions readTrustGroup(Path path) throws IOException {
|
private CertificateTrustRestrictions readTrustGroup(Path path) throws IOException {
|
||||||
try (InputStream in = Files.newInputStream(path)) {
|
Settings settings = Settings.builder().loadFromPath(path).build();
|
||||||
Settings settings = Settings.builder().loadFromStream(path.toString(), in).build();
|
final String[] trustNodeNames = settings.getAsArray(RESTRICTIONS_KEY_SUBJECT_NAME);
|
||||||
final String[] trustNodeNames = settings.getAsArray(RESTRICTIONS_KEY_SUBJECT_NAME);
|
return new CertificateTrustRestrictions(Arrays.asList(trustNodeNames));
|
||||||
return new CertificateTrustRestrictions(Arrays.asList(trustNodeNames));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -586,7 +586,7 @@ public class DocumentLevelSecurityTests extends SecurityIntegTestCase {
|
||||||
|
|
||||||
public void testChildrenAggregation() throws Exception {
|
public void testChildrenAggregation() throws Exception {
|
||||||
assertAcked(client().admin().indices().prepareCreate("test")
|
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("type1", "field1", "type=text", "field2", "type=text")
|
||||||
.addMapping("type2", "_parent", "type=type1", "field3", "type=text,fielddata=true")
|
.addMapping("type2", "_parent", "type=type1", "field3", "type=text,fielddata=true")
|
||||||
);
|
);
|
||||||
|
@ -643,7 +643,7 @@ public class DocumentLevelSecurityTests extends SecurityIntegTestCase {
|
||||||
|
|
||||||
public void testParentChild_parentField() {
|
public void testParentChild_parentField() {
|
||||||
assertAcked(prepareCreate("test")
|
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("parent")
|
||||||
.addMapping("child", "_parent", "type=parent", "field1", "type=text", "field2", "type=text", "field3", "type=text"));
|
.addMapping("child", "_parent", "type=parent", "field1", "type=text", "field2", "type=text", "field3", "type=text"));
|
||||||
ensureGreen();
|
ensureGreen();
|
||||||
|
|
|
@ -1221,7 +1221,7 @@ public class FieldLevelSecurityTests extends SecurityIntegTestCase {
|
||||||
|
|
||||||
public void testParentChild_parentField() {
|
public void testParentChild_parentField() {
|
||||||
assertAcked(prepareCreate("test")
|
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("parent")
|
||||||
.addMapping("child", "_parent", "type=parent"));
|
.addMapping("child", "_parent", "type=parent"));
|
||||||
ensureGreen();
|
ensureGreen();
|
||||||
|
|
|
@ -49,16 +49,20 @@ public abstract class AbstractLicenseServiceTestCase extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setInitialState(License license, XPackLicenseState licenseState, Settings settings) {
|
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();
|
Path tempDir = createTempDir();
|
||||||
when(environment.configFile()).thenReturn(tempDir);
|
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();
|
settings = Settings.builder().put(settings).put(LicenseService.SELF_GENERATED_LICENSE_TYPE.getKey(), licenseType).build();
|
||||||
licenseService = new LicenseService(settings, clusterService, clock, environment, resourceWatcherService, licenseState);
|
licenseService = new LicenseService(settings, clusterService, clock, environment, resourceWatcherService, licenseState);
|
||||||
ClusterState state = mock(ClusterState.class);
|
ClusterState state = mock(ClusterState.class);
|
||||||
final ClusterBlocks noBlock = ClusterBlocks.builder().build();
|
final ClusterBlocks noBlock = ClusterBlocks.builder().build();
|
||||||
when(state.blocks()).thenReturn(noBlock);
|
when(state.blocks()).thenReturn(noBlock);
|
||||||
MetaData metaData = mock(MetaData.class);
|
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);
|
when(state.metaData()).thenReturn(metaData);
|
||||||
final DiscoveryNode mockNode = new DiscoveryNode("b", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
final DiscoveryNode mockNode = new DiscoveryNode("b", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
|
||||||
when(discoveryNodes.getMasterNode()).thenReturn(mockNode);
|
when(discoveryNodes.getMasterNode()).thenReturn(mockNode);
|
||||||
|
|
|
@ -65,7 +65,7 @@ public abstract class AbstractLicensesIntegrationTestCase extends ESIntegTestCas
|
||||||
@Override
|
@Override
|
||||||
public ClusterState execute(ClusterState currentState) throws Exception {
|
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
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();
|
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
|
||||||
public void testNotificationOnNewLicense() throws Exception {
|
public void testNotificationOnNewLicense() throws Exception {
|
||||||
ClusterState oldState = ClusterState.builder(new ClusterName("a")).build();
|
ClusterState oldState = ClusterState.builder(new ClusterName("a")).build();
|
||||||
final License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(24));
|
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 newState = ClusterState.builder(new ClusterName("a")).metaData(metaData).build();
|
||||||
licenseService.clusterChanged(new ClusterChangedEvent("simulated", newState, oldState));
|
licenseService.clusterChanged(new ClusterChangedEvent("simulated", newState, oldState));
|
||||||
assertThat(licenseState.activeUpdates.size(), equalTo(1));
|
assertThat(licenseState.activeUpdates.size(), equalTo(1));
|
||||||
|
@ -56,7 +56,7 @@ public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
|
||||||
|
|
||||||
public void testNoNotificationOnExistingLicense() throws Exception {
|
public void testNoNotificationOnExistingLicense() throws Exception {
|
||||||
final License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(24));
|
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 newState = ClusterState.builder(new ClusterName("a")).metaData(metaData).build();
|
||||||
ClusterState oldState = ClusterState.builder(newState).build();
|
ClusterState oldState = ClusterState.builder(newState).build();
|
||||||
licenseService.clusterChanged(new ClusterChangedEvent("simulated", newState, oldState));
|
licenseService.clusterChanged(new ClusterChangedEvent("simulated", newState, oldState));
|
||||||
|
|
|
@ -18,9 +18,9 @@ import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
public class LicenseRegistrationTests extends AbstractLicenseServiceTestCase {
|
public class LicenseRegistrationTests extends AbstractLicenseServiceTestCase {
|
||||||
|
|
||||||
public void testTrialLicenseRequestOnEmptyLicenseState() throws Exception {
|
public void testSelfGeneratedTrialLicense() throws Exception {
|
||||||
XPackLicenseState licenseState = new XPackLicenseState();
|
XPackLicenseState licenseState = new XPackLicenseState();
|
||||||
setInitialState(null, licenseState, Settings.EMPTY);
|
setInitialState(null, licenseState, Settings.EMPTY, "trial");
|
||||||
when(discoveryNodes.isLocalNodeElectedMaster()).thenReturn(true);
|
when(discoveryNodes.isLocalNodeElectedMaster()).thenReturn(true);
|
||||||
licenseService.start();
|
licenseService.start();
|
||||||
|
|
||||||
|
@ -31,6 +31,26 @@ public class LicenseRegistrationTests extends AbstractLicenseServiceTestCase {
|
||||||
LicensesMetaData licenseMetaData = stateWithLicense.metaData().custom(LicensesMetaData.TYPE);
|
LicensesMetaData licenseMetaData = stateWithLicense.metaData().custom(LicensesMetaData.TYPE);
|
||||||
assertNotNull(licenseMetaData);
|
assertNotNull(licenseMetaData);
|
||||||
assertNotNull(licenseMetaData.getLicense());
|
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());
|
assertEquals(clock.millis() + LicenseService.SELF_GENERATED_LICENSE_DURATION.millis(), licenseMetaData.getLicense().expiryDate());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.license;
|
package org.elasticsearch.license;
|
||||||
|
|
||||||
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.cluster.ClusterModule;
|
import org.elasticsearch.cluster.ClusterModule;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.cluster.metadata.RepositoriesMetaData;
|
import org.elasticsearch.cluster.metadata.RepositoriesMetaData;
|
||||||
|
@ -29,9 +30,10 @@ import static org.hamcrest.Matchers.notNullValue;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
|
||||||
public class LicensesMetaDataSerializationTests extends ESTestCase {
|
public class LicensesMetaDataSerializationTests extends ESTestCase {
|
||||||
|
|
||||||
public void testXContentSerializationOneSignedLicense() throws Exception {
|
public void testXContentSerializationOneSignedLicense() throws Exception {
|
||||||
License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2));
|
License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2));
|
||||||
LicensesMetaData licensesMetaData = new LicensesMetaData(license);
|
LicensesMetaData licensesMetaData = new LicensesMetaData(license, null);
|
||||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
builder.startObject("licenses");
|
builder.startObject("licenses");
|
||||||
|
@ -40,12 +42,27 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(createParser(builder));
|
LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(createParser(builder));
|
||||||
assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(license));
|
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 {
|
public void testLicenseMetadataParsingDoesNotSwallowOtherMetaData() throws Exception {
|
||||||
new Licensing(Settings.EMPTY); // makes sure LicensePlugin is registered in Custom MetaData
|
new Licensing(Settings.EMPTY); // makes sure LicensePlugin is registered in Custom MetaData
|
||||||
License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2));
|
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);
|
RepositoryMetaData repositoryMetaData = new RepositoryMetaData("repo", "fs", Settings.EMPTY);
|
||||||
RepositoriesMetaData repositoriesMetaData = new RepositoriesMetaData(repositoryMetaData);
|
RepositoriesMetaData repositoriesMetaData = new RepositoriesMetaData(repositoryMetaData);
|
||||||
final MetaData.Builder metaDataBuilder = MetaData.builder();
|
final MetaData.Builder metaDataBuilder = MetaData.builder();
|
||||||
|
@ -79,7 +96,7 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
|
||||||
.type(randomBoolean() ? "trial" : "basic")
|
.type(randomBoolean() ? "trial" : "basic")
|
||||||
.expiryDate(issueDate + TimeValue.timeValueHours(2).getMillis());
|
.expiryDate(issueDate + TimeValue.timeValueHours(2).getMillis());
|
||||||
final License trialLicense = SelfGeneratedLicense.create(specBuilder);
|
final License trialLicense = SelfGeneratedLicense.create(specBuilder);
|
||||||
LicensesMetaData licensesMetaData = new LicensesMetaData(trialLicense);
|
LicensesMetaData licensesMetaData = new LicensesMetaData(trialLicense, Version.CURRENT);
|
||||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
builder.startObject("licenses");
|
builder.startObject("licenses");
|
||||||
|
@ -88,6 +105,7 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(createParser(builder));
|
LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(createParser(builder));
|
||||||
assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(trialLicense));
|
assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(trialLicense));
|
||||||
|
assertEquals(licensesMetaDataFromXContent.getMostRecentTrialVersion(), Version.CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLicenseTombstoneFromXContext() throws Exception {
|
public void testLicenseTombstoneFromXContext() throws Exception {
|
||||||
|
@ -101,6 +119,19 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
|
||||||
assertThat(metaDataFromXContent.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE));
|
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 {
|
private static LicensesMetaData getLicensesMetaDataFromXContent(XContentParser parser) throws Exception {
|
||||||
parser.nextToken(); // consume null
|
parser.nextToken(); // consume null
|
||||||
parser.nextToken(); // consume "licenses"
|
parser.nextToken(); // consume "licenses"
|
||||||
|
|
|
@ -348,6 +348,6 @@ public class TestUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void putLicense(MetaData.Builder builder, License license) {
|
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
|
// Disable native ML autodetect_process as the c++ controller won't be available
|
||||||
.put(MachineLearning.AUTODETECT_PROCESS.getKey(), false);
|
.put(MachineLearning.AUTODETECT_PROCESS.getKey(), false);
|
||||||
Settings customSettings = customSecuritySettingsSource.nodeSettings(nodeOrdinal);
|
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);
|
Settings.Builder customBuilder = Settings.builder().put(customSettings);
|
||||||
if (customBuilder.getSecureSettings() != null) {
|
if (customBuilder.getSecureSettings() != null) {
|
||||||
SecuritySettingsSource.addSecureSettings(builder, secureSettings ->
|
SecuritySettingsSource.addSecureSettings(builder, secureSettings ->
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class GraphTests extends XPackSingleNodeTestCase {
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
assertAcked(client().admin().indices().prepareCreate("test")
|
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",
|
.addMapping("type",
|
||||||
"decade", "type=keyword",
|
"decade", "type=keyword",
|
||||||
"people", "type=keyword",
|
"people", "type=keyword",
|
||||||
|
|
|
@ -92,16 +92,12 @@ public class MonitoringSettingsIntegTests extends MonitoringIntegTestCase {
|
||||||
MonitoringSettings.JOB_STATS_TIMEOUT};
|
MonitoringSettings.JOB_STATS_TIMEOUT};
|
||||||
for (Setting<?> setting : monitoringSettings) {
|
for (Setting<?> setting : monitoringSettings) {
|
||||||
if (setting.isDynamic()) {
|
if (setting.isDynamic()) {
|
||||||
Object updated = null;
|
|
||||||
if (setting.get(Settings.EMPTY) instanceof TimeValue) {
|
if (setting.get(Settings.EMPTY) instanceof TimeValue) {
|
||||||
updated = newRandomTimeValue();
|
transientSettings.put(setting.getKey(), newRandomTimeValue().toString());
|
||||||
transientSettings.put(setting.getKey(), updated);
|
|
||||||
} else if (setting.get(Settings.EMPTY) instanceof Boolean) {
|
} else if (setting.get(Settings.EMPTY) instanceof Boolean) {
|
||||||
updated = randomBoolean();
|
transientSettings.put(setting.getKey(), randomBoolean());
|
||||||
transientSettings.put(setting.getKey(), updated);
|
|
||||||
} else if (setting.get(Settings.EMPTY) instanceof List) {
|
} else if (setting.get(Settings.EMPTY) instanceof List) {
|
||||||
updated = randomStringArray();
|
transientSettings.putArray(setting.getKey(), randomStringArray());
|
||||||
transientSettings.putArray(setting.getKey(), (String[]) updated);
|
|
||||||
} else {
|
} else {
|
||||||
fail("unknown dynamic setting [" + setting + "]");
|
fail("unknown dynamic setting [" + setting + "]");
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ public class TransportMonitoringBulkActionTests extends ESTestCase {
|
||||||
|
|
||||||
final MonitoringBulkRequest request = new MonitoringBulkRequest();
|
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 type = randomAlphaOfLength(5);
|
||||||
final String id = randomBoolean() ? randomAlphaOfLength(5) : null;
|
final String id = randomBoolean() ? randomAlphaOfLength(5) : null;
|
||||||
final long timestamp = randomNonNegativeLong();
|
final long timestamp = randomNonNegativeLong();
|
||||||
|
@ -198,7 +198,7 @@ public class TransportMonitoringBulkActionTests extends ESTestCase {
|
||||||
public void testAsyncActionCreateMonitoringDocs() throws Exception {
|
public void testAsyncActionCreateMonitoringDocs() throws Exception {
|
||||||
final List<MonitoringBulkDoc> docs = new ArrayList<>();
|
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 type = randomAlphaOfLength(5);
|
||||||
final String id = randomBoolean() ? randomAlphaOfLength(5) : null;
|
final String id = randomBoolean() ? randomAlphaOfLength(5) : null;
|
||||||
final long timestamp = randomBoolean() ? randomNonNegativeLong() : 0L;
|
final long timestamp = randomBoolean() ? randomNonNegativeLong() : 0L;
|
||||||
|
@ -235,7 +235,7 @@ public class TransportMonitoringBulkActionTests extends ESTestCase {
|
||||||
|
|
||||||
public void testAsyncActionCreateMonitoringDocWithNoTimestamp() throws Exception {
|
public void testAsyncActionCreateMonitoringDocWithNoTimestamp() throws Exception {
|
||||||
final MonitoringBulkDoc monitoringBulkDoc =
|
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 =
|
final MonitoringDoc monitoringDoc =
|
||||||
new TransportMonitoringBulkAction.AsyncAction(null, null, null, "", 456L, null).createMonitoringDoc(monitoringBulkDoc);
|
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();
|
DateTimeFormatter formatter = DateTimeFormat.forPattern("YYYY.MM.dd").withZoneUTC();
|
||||||
assertThat(indexName(formatter, MonitoredSystem.ES, timestamp),
|
assertThat(indexName(formatter, MonitoredSystem.ES, timestamp),
|
||||||
equalTo(".monitoring-es-" + TEMPLATE_VERSION + "-2017.08.03"));
|
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),
|
assertThat(indexName(formatter, MonitoredSystem.KIBANA, timestamp),
|
||||||
equalTo(".monitoring-kibana-" + TEMPLATE_VERSION + "-2017.08.03"));
|
equalTo(".monitoring-kibana-" + TEMPLATE_VERSION + "-2017.08.03"));
|
||||||
assertThat(indexName(formatter, MonitoredSystem.LOGSTASH, timestamp),
|
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();
|
formatter = DateTimeFormat.forPattern("YYYY-dd-MM-HH.mm.ss").withZoneUTC();
|
||||||
assertThat(indexName(formatter, MonitoredSystem.ES, timestamp),
|
assertThat(indexName(formatter, MonitoredSystem.ES, timestamp),
|
||||||
equalTo(".monitoring-es-" + TEMPLATE_VERSION + "-2017-03-08-13.47.58"));
|
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),
|
assertThat(indexName(formatter, MonitoredSystem.KIBANA, timestamp),
|
||||||
equalTo(".monitoring-kibana-" + TEMPLATE_VERSION + "-2017-03-08-13.47.58"));
|
equalTo(".monitoring-kibana-" + TEMPLATE_VERSION + "-2017-03-08-13.47.58"));
|
||||||
assertThat(indexName(formatter, MonitoredSystem.LOGSTASH, timestamp),
|
assertThat(indexName(formatter, MonitoredSystem.LOGSTASH, timestamp),
|
||||||
|
|
|
@ -61,9 +61,9 @@ public class HttpExporterResourceTests extends AbstractPublishableHttpResourceTe
|
||||||
private final boolean createOldTemplates = randomBoolean();
|
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_PIPELINES = PIPELINE_IDS.length;
|
||||||
private final int EXPECTED_WATCHES = ClusterAlertsUtil.WATCH_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.OLD_TEMPLATE_IDS;
|
||||||
import static org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils.PIPELINE_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.equalTo;
|
||||||
import static org.hamcrest.Matchers.hasSize;
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
|
@ -347,7 +348,7 @@ public class HttpExporterTests extends ESTestCase {
|
||||||
assertThat(multiResource.getResources().size(),
|
assertThat(multiResource.getResources().size(),
|
||||||
equalTo(version + templates.size() + pipelines.size() + watcherCheck.size()));
|
equalTo(version + templates.size() + pipelines.size() + watcherCheck.size()));
|
||||||
assertThat(version, equalTo(1));
|
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(pipelines, hasSize(useIngest ? PIPELINE_IDS.length : 0));
|
||||||
assertThat(watcherCheck, hasSize(clusterAlertManagement ? 1 : 0));
|
assertThat(watcherCheck, hasSize(clusterAlertManagement ? 1 : 0));
|
||||||
assertThat(watches, hasSize(clusterAlertManagement ? ClusterAlertsUtil.WATCH_IDS.length : 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.max;
|
||||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
|
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
|
||||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
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.KIBANA;
|
||||||
import static org.elasticsearch.xpack.monitoring.MonitoredSystem.LOGSTASH;
|
import static org.elasticsearch.xpack.monitoring.MonitoredSystem.LOGSTASH;
|
||||||
import static org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils.PIPELINE_IDS;
|
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-es");
|
||||||
templates.add(".monitoring-kibana");
|
templates.add(".monitoring-kibana");
|
||||||
templates.add(".monitoring-logstash");
|
templates.add(".monitoring-logstash");
|
||||||
templates.add(".monitoring-beats");
|
|
||||||
|
|
||||||
GetIndexTemplatesResponse response =
|
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates(".monitoring-*").get();
|
||||||
client().admin().indices().prepareGetTemplates(".monitoring-*").get();
|
Set<String> actualTemplates = response.getIndexTemplates().stream().map(IndexTemplateMetaData::getName).collect(Collectors.toSet());
|
||||||
Set<String> actualTemplates = response.getIndexTemplates().stream()
|
|
||||||
.map(IndexTemplateMetaData::getName).collect(Collectors.toSet());
|
|
||||||
assertEquals(templates, actualTemplates);
|
assertEquals(templates, actualTemplates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +326,7 @@ public class LocalExporterIntegTests extends LocalExporterIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MonitoringBulkDoc createMonitoringBulkDoc() throws IOException {
|
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 XContentType xContentType = randomFrom(XContentType.values());
|
||||||
final BytesReference source;
|
final BytesReference source;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.nio.entity.NStringEntity;
|
import org.apache.http.nio.entity.NStringEntity;
|
||||||
import org.apache.lucene.util.Constants;
|
import org.apache.lucene.util.Constants;
|
||||||
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.client.Response;
|
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.notNullValue;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
|
||||||
|
@LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/2609")
|
||||||
public class MonitoringIT extends ESRestTestCase {
|
public class MonitoringIT extends ESRestTestCase {
|
||||||
|
|
||||||
private static final String BASIC_AUTH_VALUE = basicAuthHeaderValue("x_pack_rest_user", TEST_PASSWORD_SECURE_STRING);
|
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());
|
assertEquals(5, source.size());
|
||||||
|
|
||||||
final Map<String, Object> nodeStats = (Map<String, Object>) source.get(NodeStatsMonitoringDoc.TYPE);
|
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 -> {
|
NodeStatsMonitoringDoc.XCONTENT_FILTERS.forEach(filter -> {
|
||||||
if (Constants.WINDOWS && filter.startsWith("node_stats.os.cpu.load_average")) {
|
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
|
* Returns a {@link MonitoredSystem} supported by the Monitoring Bulk API
|
||||||
*/
|
*/
|
||||||
private static MonitoredSystem randomSystem() {
|
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()) {
|
for (Map.Entry<String, Object> setting : defaults.entrySet()) {
|
||||||
String key = "xpack.notification.jira.account." + name + "." + JiraAccount.ISSUE_DEFAULTS_SETTING + "." + setting.getKey();
|
String key = "xpack.notification.jira.account." + name + "." + JiraAccount.ISSUE_DEFAULTS_SETTING + "." + setting.getKey();
|
||||||
if (setting.getValue() instanceof String) {
|
if (setting.getValue() instanceof String) {
|
||||||
builder.put(key, setting.getValue());
|
builder.put(key, setting.getValue().toString());
|
||||||
} else if (setting.getValue() instanceof Map) {
|
} else if (setting.getValue() instanceof Map) {
|
||||||
builder.putProperties((Map) setting.getValue(), s -> key + "." + s);
|
builder.putProperties((Map) setting.getValue(), s -> key + "." + s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,17 +226,19 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
final Settings settingsTemplate = cluster2SettingsSource.nodeSettings(0);
|
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 tribe1Defaults = Settings.builder();
|
||||||
Settings.Builder tribe2Defaults = Settings.builder();
|
Settings.Builder tribe2Defaults = Settings.builder();
|
||||||
for (Map.Entry<String, String> entry : asMap.entrySet()) {
|
Settings tribeSettings = settingsTemplate.filter(k -> {
|
||||||
if (entry.getKey().startsWith("path.")) {
|
if (k.equals(NodeEnvironment.MAX_LOCAL_STORAGE_NODES_SETTING.getKey())) {
|
||||||
continue;
|
return false;
|
||||||
} else if (entry.getKey().equals("transport.tcp.port")) {
|
} if (k.startsWith("path.")) {
|
||||||
continue;
|
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());
|
tribe1Defaults.put("tribe.t1." + entry.getKey(), entry.getValue());
|
||||||
tribe2Defaults.put("tribe.t2." + 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()
|
Settings merged = Settings.builder()
|
||||||
.put(internalCluster().getDefaultSettings())
|
.put(internalCluster().getDefaultSettings())
|
||||||
.put(asMap)
|
.put(tribeSettings, false)
|
||||||
.put("tribe.t1.cluster.name", internalCluster().getClusterName())
|
.put("tribe.t1.cluster.name", internalCluster().getClusterName())
|
||||||
.put("tribe.t2.cluster.name", cluster2.getClusterName())
|
.put("tribe.t2.cluster.name", cluster2.getClusterName())
|
||||||
.put("tribe.blocks.write", false)
|
.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/put"), is(true));
|
||||||
assertThat(predicate.test("indices:admin/mapping/whatever"), is(false));
|
assertThat(predicate.test("indices:admin/mapping/whatever"), is(false));
|
||||||
assertThat(predicate.test("internal:transport/proxy/indices:data/read/query"), 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
|
// test that starting up a node works
|
||||||
Settings.Builder nodeSettings = Settings.builder()
|
Settings.Builder nodeSettings = Settings.builder()
|
||||||
.put()
|
|
||||||
.put("node.name", "my-test-node")
|
.put("node.name", "my-test-node")
|
||||||
.put("network.host", "localhost")
|
.put("network.host", "localhost")
|
||||||
.put("cluster.name", internalCluster().getClusterName())
|
.put("cluster.name", internalCluster().getClusterName())
|
||||||
|
|
|
@ -95,7 +95,7 @@ public class DNSOnlyHostnameVerificationTests extends SecurityIntegTestCase {
|
||||||
public Settings nodeSettings(int nodeOrdinal) {
|
public Settings nodeSettings(int nodeOrdinal) {
|
||||||
Settings defaultSettings = super.nodeSettings(nodeOrdinal);
|
Settings defaultSettings = super.nodeSettings(nodeOrdinal);
|
||||||
Settings.Builder builder = Settings.builder()
|
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);
|
.put("transport.host", hostName);
|
||||||
Path keystorePath = nodeConfigPath(nodeOrdinal).resolve("keystore.jks");
|
Path keystorePath = nodeConfigPath(nodeOrdinal).resolve("keystore.jks");
|
||||||
try (OutputStream os = Files.newOutputStream(keystorePath)) {
|
try (OutputStream os = Files.newOutputStream(keystorePath)) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class IPHostnameVerificationTests extends SecurityIntegTestCase {
|
||||||
protected Settings nodeSettings(int nodeOrdinal) {
|
protected Settings nodeSettings(int nodeOrdinal) {
|
||||||
Settings settings = super.nodeSettings(nodeOrdinal);
|
Settings settings = super.nodeSettings(nodeOrdinal);
|
||||||
Settings.Builder builder = Settings.builder()
|
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();
|
settings = builder.build();
|
||||||
|
|
||||||
// The default Unicast test behavior is to use 'localhost' with the port number. For this test we need to use IP
|
// 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
|
indices:data/write/reindex
|
||||||
cluster:admin/xpack/deprecation/info
|
cluster:admin/xpack/deprecation/info
|
||||||
cluster:admin/xpack/ml/job/forecast
|
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:
|
- do:
|
||||||
xpack.monitoring.bulk:
|
xpack.monitoring.bulk:
|
||||||
system_id: "beats"
|
system_id: "logstash"
|
||||||
system_api_version: "6"
|
system_api_version: "6"
|
||||||
interval: "5s"
|
interval: "5s"
|
||||||
body:
|
body:
|
||||||
|
@ -183,17 +183,17 @@
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
search:
|
search:
|
||||||
index: .monitoring-beats-*
|
index: .monitoring-logstash-*
|
||||||
- match: { hits.total: 2 }
|
- match: { hits.total: 2 }
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
indices.close:
|
indices.close:
|
||||||
index: .monitoring-beats-*
|
index: .monitoring-logstash-*
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
catch: /export_exception/
|
catch: /export_exception/
|
||||||
xpack.monitoring.bulk:
|
xpack.monitoring.bulk:
|
||||||
system_id: "beats"
|
system_id: "logstash"
|
||||||
system_api_version: "6"
|
system_api_version: "6"
|
||||||
interval: "5s"
|
interval: "5s"
|
||||||
body:
|
body:
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
||||||
protected Settings externalClusterClientSettings() {
|
protected Settings externalClusterClientSettings() {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
.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")
|
.put(NetworkModule.TRANSPORT_TYPE_KEY, "security4")
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
||||||
.put("cluster.name", clusterName)
|
.put("cluster.name", clusterName)
|
||||||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toAbsolutePath().toString())
|
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toAbsolutePath().toString())
|
||||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
.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();
|
.build();
|
||||||
try (TransportClient client = new PreBuiltXPackTransportClient(settings)) {
|
try (TransportClient client = new PreBuiltXPackTransportClient(settings)) {
|
||||||
client.addTransportAddress(publishAddress);
|
client.addTransportAddress(publishAddress);
|
||||||
|
@ -98,7 +98,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
||||||
.put("cluster.name", clusterName)
|
.put("cluster.name", clusterName)
|
||||||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toAbsolutePath().toString())
|
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toAbsolutePath().toString())
|
||||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER + randomAlphaOfLength(1))
|
.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();
|
.build();
|
||||||
try (TransportClient client = new PreBuiltXPackTransportClient(settings)) {
|
try (TransportClient client = new PreBuiltXPackTransportClient(settings)) {
|
||||||
client.addTransportAddress(publishAddress);
|
client.addTransportAddress(publishAddress);
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class CustomRolesProviderIT extends ESIntegTestCase {
|
||||||
protected Settings externalClusterClientSettings() {
|
protected Settings externalClusterClientSettings() {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
.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")
|
.put(NetworkModule.TRANSPORT_TYPE_KEY, "security4")
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.test;
|
package org.elasticsearch.test;
|
||||||
|
|
||||||
|
import org.elasticsearch.Build;
|
||||||
import org.elasticsearch.common.bytes.BytesArray;
|
import org.elasticsearch.common.bytes.BytesArray;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.transport.TransportAddress;
|
import org.elasticsearch.common.transport.TransportAddress;
|
||||||
|
@ -101,6 +102,7 @@ public class LicensingTribeIT extends ESIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLicensePropagateToTribeNode() throws Exception {
|
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
|
// test that auto-generated trial license propagates to tribe
|
||||||
assertBusy(() -> {
|
assertBusy(() -> {
|
||||||
GetLicenseResponse getLicenseResponse = new LicensingClient(tribeNode.client()).prepareGetLicense().get();
|
GetLicenseResponse getLicenseResponse = new LicensingClient(tribeNode.client()).prepareGetLicense().get();
|
||||||
|
|
Loading…
Reference in New Issue