From 69b8c680aad4a3f0b10590686c76b0747e3a06df Mon Sep 17 00:00:00 2001 From: Melike Celen <144365465+celenmelike@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:51:46 +0100 Subject: [PATCH] Enterprise REST API doc updates [DEX-146] (#1136) - Section name updated to `Enterprise Edition REST API` in the ref manual navigation. - Added programmatic configs. - Added more details for enabling REST API. - Added more details on configuring port. - Added information about the REST client. --------- Co-authored-by: ihsan Co-authored-by: ihsan demir Co-authored-by: Oliver Howell --- docs/modules/ROOT/nav.adoc | 3 + .../clients/partials/rest-deprecation.adoc | 2 +- .../get-started-rest-api-with-docker.adoc | 201 ++++++++++++ .../pages/get-started-rest-api-with-java.adoc | 192 +++++++++++ .../pages/enterprise-rest-api.adoc | 302 +++++++++++------- .../maintain-cluster/partials/nav.adoc | 1 - 6 files changed, 589 insertions(+), 112 deletions(-) create mode 100644 docs/modules/getting-started/pages/get-started-rest-api-with-docker.adoc create mode 100644 docs/modules/getting-started/pages/get-started-rest-api-with-java.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 2d8222081..8165cbb32 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -210,6 +210,9 @@ include::wan:partial$nav.adoc[] * xref:clients:cplusplus.adoc[] * xref:clients:dotnet.adoc[] * xref:maintain-cluster:enterprise-rest-api.adoc[] +** xref:getting-started:get-started-rest-api-with-docker.adoc[] +** xref:getting-started:get-started-rest-api-with-java.adoc[] +** xref:maintain-cluster:rest-api-swagger.adoc[] * xref:clients:memcache.adoc[] * xref:clients:python.adoc[] * xref:clients:nodejs.adoc[] diff --git a/docs/modules/clients/partials/rest-deprecation.adoc b/docs/modules/clients/partials/rest-deprecation.adoc index 34dcdd81f..4eb0fe209 100644 --- a/docs/modules/clients/partials/rest-deprecation.adoc +++ b/docs/modules/clients/partials/rest-deprecation.adoc @@ -1,5 +1,5 @@ [CAUTION] .Deprecation Notice for the Community Edition REST API ==== -The Community Edition REST API has been deprecated and will be removed as of Hazelcast version 7.0. An improved version of this feature is under development. For more info, see xref:maintain-cluster:enterprise-rest-api.adoc[REST API] +The Community Edition REST API has been deprecated and will be removed as of Hazelcast version 7.0. An improved Enterprise version of this feature is available and actively being developed. For more info, see xref:maintain-cluster:enterprise-rest-api.adoc[Enterprise REST API] ==== \ No newline at end of file diff --git a/docs/modules/getting-started/pages/get-started-rest-api-with-docker.adoc b/docs/modules/getting-started/pages/get-started-rest-api-with-docker.adoc new file mode 100644 index 000000000..36ba9dfd5 --- /dev/null +++ b/docs/modules/getting-started/pages/get-started-rest-api-with-docker.adoc @@ -0,0 +1,201 @@ += Get started with REST API using Docker +:description: This tutorial provides a step-by-step guide to help you enable, run and use the REST API with minimal configuration using Docker. +:page-enterprise: true + +{description} + +== Before You Begin + +To complete this tutorial, you need the following: + +[cols="1a,1a"] +|=== +|Prerequisites|Useful resources + +|Docker image for Hazelcast {enterprise-product-name} full distribution and an {enterprise-product-name} license +|xref:getting-started:enterprise-overview.adoc[] + +|=== + +== Step 1. Prepare configuration file + +Create a hazelcast.yaml (or xml) configuration file with the following content and place it in the ~/config directory on your local machine. + +[tabs] +==== +XML:: ++ +-- +[source,xml] +---- + + your license key <1> + + restRealm + + + + + + + + admin + + + + + com.hazelcast.internal.rest.access.DefaultAccessControlServiceFactory + + + + + +---- +-- + +YAML:: ++ +[source,yaml] +---- +hazelcast: + license-key: <1> + rest: + enabled: true + security-realm: restRealm + security: + enabled: true + realms: + - name: restRealm + authentication: + simple: + users: + - username: 'restuser' + password: 'restpassword' + roles: + - admin + access-control-service: + factory-class-name: com.hazelcast.internal.rest.access.DefaultAccessControlServiceFactory +---- +==== +<1> Replace `` with your Hazelcast {enterprise-product-name} license key. + +== Step 2. Start Hazelcast {enterprise-product-name} server + +To start the Hazelcast {enterprise-product-name} server, run the following command: + +[tabs] +==== +Using XML Config:: ++ +-- +[source,shell,subs="attributes+"] +---- +docker run \ + -p 5701:5701 -p 8443:8443\ + -e JAVA_OPTS="-Dhazelcast.config=/opt/hazelcast/config_ext/hazelcast.xml" -v ~/config:/opt/hazelcast/config_ext hazelcast/hazelcast-enterprise:{full-version} +---- +-- + +Using YAML Config:: ++ +[source,shell,subs="attributes+"] +---- +docker run \ + -p 5701:5701 -p 8443:8443\ + -e JAVA_OPTS="-Dhazelcast.config=/opt/hazelcast/config_ext/hazelcast.yaml" -v ~/config:/opt/hazelcast/config_ext hazelcast/hazelcast-enterprise:{full-version} +---- +==== + +This command starts the member and configures it using your configuration file. +In these examples, `~/config` is the path to the directory containing your configuration file. + +You should see a message in the console indicating that the REST service is enabled, similar to the following: + +[source,shell,subs="attributes+"] +---- +com.hazelcast.internal.rest.init.RestServiceImpl +INFO: [192.168.0.24]:5701 [dev] [5.5.0-SNAPSHOT] Hazelcast REST Service is enabled on port: 8443 with security realm: restRealm and access control service: com.hazelcast.internal.rest.access.DefaultAccessControlService +---- + +== Step 3. Access the REST API and Swagger UI + +The REST API is running on port 8443. +You can access the https://swagger.io/tools/swagger-ui/[Swagger UI] at: http://localhost:8443/swagger-ui/index.html. This user interface displays detailed documentation for the Hazelcast REST API, and enables you to interact with the API within the cluster. + +TIP: You can also xref:maintain-cluster:rest-api-swagger.adoc[view this Swagger UI] within this documentation. + +== Step 4. Obtain a token to access all endpoints +To obtain a token, send a POST request to the endpoint at `/hazelcast/rest/api/v1/token`. + +[tabs] +===== +Using Swagger UI:: ++ +- Open the Swagger UI at http://localhost:8443/swagger-ui/index.html +- Navigate to the token endpoint under the *JWT Token Controller* section +- Click **Try it out** +- Set the request body as follows: ++ +[source,json] +---- +{ + "username": "restuser", + "password": "restpassword" +} +---- ++ +- Click **Execute** + +Using cURL:: +- Run the following command in your terminal: ++ +[source,shell] +---- +curl -X 'POST' \ + 'http://localhost:8443/hazelcast/rest/api/v1/token' \ + -H 'Content-Type: application/json' \ + -d '{ + "username": "restuser", + "password": "restpassword" +}' +---- +===== + +== Step 5. Execute a Hazelcast REST call + +You need to add the token as the Authorization header in all requests, or you will get an `access denied` response. + +[tabs] +==== +Using Swagger UI:: ++ +Click **Authorize** and enter the token in the provided field. After a successful authorization, any subsequent requests made using the Swagger UI will add the token into the proper request header automatically. ++ +*Example request with Swagger UI:* ++ +- Navigate to the `/hazelcast/rest/api/v1/cluster` endpoint under the *Cluster Controller* section +- Click **Try it out** +- Click **Execute** + +Using cURL:: ++ +When you want to access a Hazelcast REST endpoint, you need to add the token to your requests as follows, replacing `` with your actual token: ++ +[source,shell] +---- +-H 'Authorization: Bearer ' +---- ++ +*Example request with cURL:* ++ +[source,shell] +---- +curl -X 'GET' \ +'http://localhost:8443/hazelcast/rest/api/v1/cluster' \ +-H 'Authorization: Bearer ' +---- +==== + +== Next Steps + +If you're interested in learning more about the topics introduced in this tutorial, see xref:maintain-cluster:enterprise-rest-api.adoc[Enterprise REST API]. diff --git a/docs/modules/getting-started/pages/get-started-rest-api-with-java.adoc b/docs/modules/getting-started/pages/get-started-rest-api-with-java.adoc new file mode 100644 index 000000000..e041cc7a6 --- /dev/null +++ b/docs/modules/getting-started/pages/get-started-rest-api-with-java.adoc @@ -0,0 +1,192 @@ += Get Started with REST API using Java +:description: This tutorial provides a step-by-step guide to help you enable, run and use the REST API with minimal configuration using Java. + +:page-enterprise: true + +{description} + +== Before You Begin + +To complete this tutorial, you need the following: + +[cols="1a,1a"] +|=== +|Prerequisites|Useful resources + +|Any supported JDK +| +xref:deploy:versioning-compatibility.adoc#supported-java-virtual-machines[Supported Java Virtual Machines] + +|Maven +|link:https://maven.apache.org/download.cgi[Download Maven] + +|=== + +== Set up the Java Maven project + +You need to set up a Java project that you can use later to start a Hazelcast member with REST API. Add the following dependencies to your `pom.xml` file: + +[source,xml,subs="attributes+"] +---- + + + com.hazelcast + hazelcast-enterprise-rest + {full-version} + + + com.hazelcast + hazelcast-enterprise + {full-version} + + +---- + +== Step 1. Prepare your Java code + +Add the following code to your `RestApi.java` file: + +[source,java] +---- +package org.example; + +import com.hazelcast.config.Config; +import com.hazelcast.config.SecurityConfig; +import com.hazelcast.config.rest.RestConfig; +import com.hazelcast.config.security.AccessControlServiceConfig; +import com.hazelcast.config.security.RealmConfig; +import com.hazelcast.config.security.SimpleAuthenticationConfig; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.internal.rest.access.DefaultAccessControlServiceFactory; + +public class RestApi { + public static void main(String[] args) { + // Configure your member to enable REST. + Config config = new Config() + .setLicenseKey("") + .setRestConfig(new RestConfig() + .setEnabled(true) + .setSecurityRealm("restRealm") + ) + .setSecurityConfig(new SecurityConfig() + .setEnabled(true) + .addRealmConfig("restRealm", new RealmConfig() + .setSimpleAuthenticationConfig( + new SimpleAuthenticationConfig() + .addUser("restuser", "restpassword", "admin") + ) + .setAccessControlServiceConfig( + new AccessControlServiceConfig() + .setFactoryClassName(DefaultAccessControlServiceFactory.class.getName()) + ) + ) + ); + + // Start a member in your JVM by creating a instance of Hazelcast. + Hazelcast.newHazelcastInstance(config); + } +} +---- + +Replace the `` with your Hazelcast {enterprise-product-name} license key. + +== Step 2. Execute the program + +Use Maven to compile and execute your Java project: + +[source,bash] +---- +mvn compile exec:java -Dexec.mainClass="org.example.RestApi" +---- + +You should see a message in the console indicating that the REST service is enabled, similar to the following: + +[source,shell,subs="attributes+"] +---- +com.hazelcast.internal.rest.init.RestServiceImpl +INFO: [192.168.0.24]:5701 [dev] [5.5.0-SNAPSHOT] Hazelcast REST Service is enabled on port: 8443 with security realm: restRealm and access control service: com.hazelcast.internal.rest.access.DefaultAccessControlService +---- + +== Step 3. Access the REST API and Swagger UI + +The REST API is running on port 8443. +You can access the https://swagger.io/tools/swagger-ui/[Swagger UI] at: http://localhost:8443/swagger-ui/index.html. This user interface displays detailed documentation for the Hazelcast REST API, and enables you to interact with the API within the cluster. + +TIP: You can also xref:maintain-cluster:rest-api-swagger.adoc[view this Swagger UI] within this documentation. + +== Step 4. Obtain a token to access all endpoints +To obtain a token, send a POST request to the endpoint at `/hazelcast/rest/api/v1/token`. + +[tabs] +===== +Using Swagger UI:: ++ +- Open the Swagger UI at http://localhost:8443/swagger-ui/index.html +- Navigate to the token endpoint under the *JWT Token Controller* section +- Click **Try it out** +- Set the request body as follows: ++ +[source,json] +---- +{ + "username": "restuser", + "password": "restpassword" +} +---- ++ +- Click **Execute** + +Using cURL:: +- Run the following command in your terminal: ++ +[source,shell] +---- +curl -X 'POST' \ + 'http://localhost:8443/hazelcast/rest/api/v1/token' \ + -H 'Content-Type: application/json' \ + -d '{ + "username": "restuser", + "password": "restpassword" +}' +---- +===== + +== Step 5. Execute a Hazelcast REST call + +You need to add the token as the Authorization header in all requests, or you will get an `access denied` response. + +[tabs] +==== +Using Swagger UI:: ++ +Click **Authorize** and enter the token in the provided field. After a successful authorization, any subsequent requests made using the Swagger UI will add the token into the proper request header automatically. ++ +*Example request with Swagger UI:* ++ +- Navigate to the `/hazelcast/rest/api/v1/cluster` endpoint under the *Cluster Controller* section. +- Click **Try it out** +- Click **Execute** + +Using cURL:: ++ +When you want to access a Hazelcast REST endpoint, you need to add the token to your requests as follows, replacing with your actual token: ++ +[source,shell] +---- +-H 'Authorization: Bearer ' +---- ++ +*Example request with cURL:* ++ +[source,shell] +---- +curl -X 'GET' \ +'http://localhost:8443/hazelcast/rest/api/v1/cluster' \ +-H 'Authorization: Bearer ' +---- +==== + +== Next steps + +If you're interested in learning more about the topics introduced in this tutorial, see xref:maintain-cluster:enterprise-rest-api.adoc[Enterprise REST API]. + diff --git a/docs/modules/maintain-cluster/pages/enterprise-rest-api.adoc b/docs/modules/maintain-cluster/pages/enterprise-rest-api.adoc index beb5b8961..138525eed 100644 --- a/docs/modules/maintain-cluster/pages/enterprise-rest-api.adoc +++ b/docs/modules/maintain-cluster/pages/enterprise-rest-api.adoc @@ -2,32 +2,36 @@ [[enterprise-rest-api]] :page-enterprise: true -Hazelcast provides a REST API that allows you to access your data -structures and cluster using the HTTP/HTTPS protocols. +TIP: To get started with the REST API using Docker or Java, see xref:getting-started:get-started-rest-api-with-docker.adoc[] or xref:getting-started:get-started-rest-api-with-java.adoc[] tutorials. -You can interact with the API using various tools and platforms such as cURL, REST clients (like Postman and Insomnia), or programming languages with HTTP request libraries or built-in support. The REST API also comes with a Swagger UI that offers an easy navigation and testing the API calls. See <>. +== Introduction -In this section, we use cURL to provide the request examples. +Hazelcast provides a REST API that allows you to access your data structures and cluster using HTTP/HTTPS protocols. -NOTE: REST API is only available in the {enterprise-product-name}. -Hazelcast also offered a Community Edition REST API, but this has been deprecated and will be removed as of Hazelcast version 7.0. For more info, see xref:rest-api.adoc[Community Edition REST API]. +The REST API comes with an integrated Swagger UI for learning about the API and trying out API calls. For more info, see <>. -== Enabling REST API +include::clients:partial$rest-deprecation.adoc[] -REST service is **disabled** in the configuration by default; enable it as shown in the following configuration. +== Enable REST API -NOTE: If you are using Hazelcast's xref:getting-started:editions.adoc#slim-distribution[slim distribution], you must add `hazelcast-enterprise-rest-{full-version}.jar` to your member's classpath to use the REST API. If you are working with the full distribution, this additional step is not needed. +To use the REST API, you must have at least one running server instance with REST enabled. Enabling the REST API provides access to various endpoints, which means you can perform data retrieval, cluster and member actions, CP operations, configuration updates and more, by calling the appropriate endpoint. + +You must configure security when you enable REST. You need to set up a security realm for the REST API. For more info, see <>. + +NOTE: After enabling the REST API, you must ensure the port for the API is not occupied, or the REST web server will not be able to start. + +REST service is disabled by default; to enable the REST service you must change the configuration as follows: [tabs] ==== XML:: -+ --- ++ +-- [source,xml] ---- - ... + # Several lines of code are omitted here. ---- @@ -41,11 +45,22 @@ hazelcast: rest: enabled: true ---- + +Java:: ++ +[source,java] +---- +Config config = new Config().setRestConfig( + new RestConfig().setEnabled(true); +); +---- ==== -== Changing Default Port +== Change default port + +The default port for the REST API is `8443`. To change it to another port, update the `rest` configuration as shown in the following example. -`8443` is the default port for REST API. To change it to another port, update the `rest` configuration as shown in the following example. +NOTE: If the port is occupied, the server instance will fail to start. To run multiple server instances with REST on the same machine, each instance should have a separate configuration file with a unique port assigned to it. [tabs] ==== @@ -71,35 +86,47 @@ hazelcast: enabled: true port: 8080 ---- + +Java:: ++ +[source,java] +---- +Config config = new Config().setRestConfig( + new RestConfig() + .setEnabled(true) + .setPort(8080); +); +---- ==== -== Authentication +== Enable authentication -You must secure the communication with REST API by configuring its authentication and access control. +You must secure REST API communication by configuring authentication and access control. -=== Configuring Authentication +[#configure-authentication] +=== Configure Authentication -REST supports simple authentication based on username, password and user roles; see xref:security:simple-authentication.adoc[Simple Authentication]. To configure the simple authentication in the REST API, complete the following steps: +The REST API supports simple authentication based on username, password and user roles. For more info, see xref:security:simple-authentication.adoc[Simple Authentication]. To configure simple authentication for the REST API, complete the following steps: -* **#Enable REST API:#** +. **Enable REST API:** You need to enable the REST API. -* **#Define A Security Realm:#** -You need to define the security realm within the rest configuration. +. **Define A Security Realm:** +You need to define the security realm within the REST configuration. -* **#Enable Security:#** -You need to enable the security to use REST API. +. **Enable Security:** +You need to enable security to use REST API. -* **#Configure Rest Realm:#** +. **Configure Rest Realm:** You need to introduce a REST realm as the authentication mechanism. This realm will handle user authentication using a simple method based on username and password. -* **#Setup Users and Roles:#** +. **Setup Users and Roles:** You should identify users and their roles within the REST realm. -* **#Configure AccessControlService:#** -To configure `AccessControlService`, you should provide a factory class that creates an instance of the service. `AccessControlService` delegates authentication to the configured security realm. You can either create a custom factory class, or use the default implementation. For the default implementation, you can use `DefaultAccessControlServiceFactory`, to produce `DefaultAccessControlService`. Authorization decisions in this service are based on three predefined roles: `reader`, who can make requests via GET endpoints only; `writer`, who can make requests including GET, POST, and DELETE; and `admin`, who can make all requests and access admin-specific endpoints. +* **Configure AccessControlService:** +To configure `AccessControlService`, you should provide a factory class that creates an instance of the service. `AccessControlService` delegates authentication to the configured security realm. You can either create a custom factory class, or use the default implementation. For the default implementation, you can use `DefaultAccessControlServiceFactory` to produce `DefaultAccessControlService`. Authorization decisions in this service are based on three predefined roles: `reader`: can make requests via GET endpoints only; `writer`: can make requests including GET, POST, and DELETE; and `admin`: can make all requests and access admin-specific endpoints. -The following configuration example includes all the steps listed above. +The following configuration example includes all the steps listed above: [tabs] ==== @@ -117,12 +144,12 @@ XML:: - + admin - <1> + com.hazelcast.internal.rest.access.DefaultAccessControlServiceFactory @@ -151,25 +178,45 @@ hazelcast: password: 'restpassword' roles: - admin - access-control-service: <1> + access-control-service: factory-class-name: com.hazelcast.internal.rest.access.DefaultAccessControlServiceFactory ---- -==== -<1> To configure `AccessControlService`, you should provide a factory class that creates an instance of the service. `AccessControlService` delegates authentication to the configured security realm. You can either create a custom factory class, or use the default implementation. For the default implementation, you can use `DefaultAccessControlServiceFactory`, to produce `DefaultAccessControlService`. Authorization decisions in this service are based on three predefined roles: `reader`, who can make requests via GET endpoints only; `writer`, who can make requests including GET, POST, and DELETE; and `admin`, who can make all requests and access admin-specific endpoints. -NOTE: Besides the simple authentication, you can also use other authentication types such as LDAP. See xref:security:security-realms.adoc#authentication-configuration[Authentication Configuration] on how to configure different types within a security realm. +Java:: ++ +[source,java] +---- +Config config = new Config() + .setRestConfig(new RestConfig() + .setEnabled(true) + .setSecurityRealm("restRealm") + ) + .setSecurityConfig(new SecurityConfig() + .setEnabled(true) + .addRealmConfig("restRealm", new RealmConfig() + .setSimpleAuthenticationConfig( + new SimpleAuthenticationConfig() + .addUser("restuser", "restpassword", "admin") + ) + .setAccessControlServiceConfig( + new AccessControlServiceConfig() + .setFactoryClassName(DefaultAccessControlServiceFactory.class.getName()) + ) + ) + ); +---- +==== -=== Authentication Process +=== Authentication process -To authenticate to the REST API, the REST client must obtain a token. See the <> for details. The token request requires a username and password and the role(s) assigned to the user are included in the token as claims. You can use the token until it expires. You use the token at the `Authorization` header for each subsequent REST API call so that the call is authorized appropriately. If a valid token is not included in the header, the API will respond with a `401 Unauthorized` error. +You must obtain a token to authenticate against the REST server. For more info, see <>. The token request requires a username and password, and the role(s) assigned to the user are included in the token as claims. You can use the token until it expires. You need to use the token in the `Authorization` header for each subsequent REST API call to ensure the call is authorized appropriately. If a valid token is not included in the header, the API will respond with a `401 Unauthorized` error. == HTTPS Support -You can configure TLS/SSL in the REST API. We use Spring Boot underneath to enable Spring web services, and all the TLS/SSL related options correspond to the underlying Spring Boot TLS/SSL support capabilities. +You can configure TLS/SSL in the REST API. We use Spring Boot underneath to enable Spring web services, and the TLS/SSL related options correspond to the underlying Spring Boot TLS/SSL support capabilities. -The TLS/SSL configuration of the REST server is completely different from Hazelcast TLS/SSL configuration which has different configuration settings. -The configuration settings are available to set up TLS/SSL as shown in -the below declarative example: +The TLS/SSL configuration for the REST server is configured differently to the normal Hazelcast TLS/SSL configuration. +For an example of the TLS/SSL configuration settings for REST, see the following code sample: [tabs] ==== @@ -233,15 +280,48 @@ hazelcast: trust-certificate: /path/to/trust-certificate trust-certificate-key: /path/to/trust-certificate-key ---- + +Java:: ++ +[source,java] +---- +Config config = new Config() + .setRestConfig( + new RestConfig() + .setEnabled(true) + .setSsl(new RestConfig.Ssl() + .setEnabled(true) + .setClientAuth(RestConfig.Ssl.ClientAuth.NEED) + .setCiphers("TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256") + .setEnabledProtocols("TLSv1.2, TLSv1.3") + .setKeyAlias("myKeyAlias") + .setKeyPassword("myKeyPassword") + .setKeyStore("/path/to/keystore") + .setKeyPassword("myKeyStorePassword") + .setKeyStoreType("JKS") + .setKeyStoreProvider("SUN") + .setTrustStore("/path/to/truststore") + .setTrustStorePassword("myTrustStorePassword") + .setTrustStoreType("JKS") + .setTrustStoreProvider("SUN") + .setProtocol("TLS") + .setCertificate("/path/to/certificate") + .setCertificatePrivateKey("/path/to/certificate-key") + .setTrustCertificate("/path/to/trust-certificate") + .setTrustCertificatePrivateKey("/path/to/trust-certificate-key") + ) + + ); +---- ==== -== JWT Based Authorization +== JWT-based authorization -After a successful authentication by making request to the token endpoint (see <>), you will receive a short-living JWT token with assigned role names as a claim for authorization checks in subsequent REST calls. +After successfully authenticating by making a request to the token endpoint (see <>), you will receive a short-lived JWT token with assigned role names as a claim for authorization checks in subsequent REST calls. -Token issued by one member is not trusted by other members. +NOTE: A token issued by one member is not trusted by other members. -Tokens are valid for 15 minutes by default. You can update the expiry duration using the `token-validity-seconds` configuration element as shown in the following example. +Tokens are valid for 15 minutes by default. You can update this duration using the `token-validity-seconds` configuration element as shown in the following example: [tabs] ==== @@ -267,14 +347,23 @@ hazelcast: enabled: true token-validity-seconds: 300 ---- + +Java:: ++ +[source,java] +---- +Config config = new Config().setRestConfig( + new RestConfig() + .setEnabled(true) + .setTokenValidityDuration(Duration.of(300, ChronoUnit.SECONDS)); +); +---- ==== [#obtaining-a-token] -== Obtaining a Token +== Obtain a Token -To obtain a token, you send a `POST` request to the token endpoint at `/hazelcast/rest/api/v1/token`. The request must include JSON-formatted `username` and `password` which you <>. If the authentication is successful, you get a response which contains a valid token for the expiry duration. - -Example request using cURL: +To obtain a token, you must send a `POST` request to the token endpoint at `/hazelcast/rest/api/v1/token`. The request must include JSON-formatted `username` and `password` which you <>. If the authentication request is successful, you will get a response which contains a valid token for the duration period. For an example, see the following cURL request and response: [source,shell] ---- @@ -287,7 +376,7 @@ curl -X 'POST' \ }' ---- -It returns the following response if successful: +If successful, the following response is returned: [source,json] ---- @@ -296,7 +385,7 @@ It returns the following response if successful: } ---- -It returns the following response if the provided credentials are incorrect: +If unsuccessful, the following response is returned: [source,json] ---- @@ -306,33 +395,33 @@ It returns the following response if the provided credentials are incorrect: } ---- -== Accessing the Swagger UI +== Access the Swagger UI -Hazelcast REST API's Swagger UI provides information about each endpoint, including required parameters, request and response structures and types, potential response codes, and example responses. You can use this UI to easily navigate and test different API calls directly from the interface. To access it: +The REST API's Swagger UI provides information about each endpoint, including required parameters, request and response structures and types, potential response codes, and example responses. You can use this UI to easily navigate and test different API calls directly from the interface. To access the Swagger UI: -. Enable the REST API. -. Start a Hazelcast member. -. Go to `http://:/swagger-ui/index.html` where and are the running member's IP address/hostname and port, respectively. +. Enable the REST API +. Start a Hazelcast member +. Go to `http://:/swagger-ui/index.html`, replacing and with the running member's IP address/hostname and port. -The following is an example view: +On successfully opening the UI, you will see a view such as the following: -image::rest-api-swagger-listed-endpoints.png[] +image::rest-api-swagger-listed-endpoints.png[Example Swagger UI view] -On the Swagger page, each endpoint is listed with a caret icon on the right side. Click the caret icon to expand the details for an endpoint. For this example, let's expand the `GET /hazelcast/rest/api/v1/cluster` endpoint. +On the Swagger page, each endpoint is listed with a caret icon on the right side. Click the caret icon to expand the details for an endpoint. For this example, let's expand the `GET /hazelcast/rest/api/v1/cluster` endpoint: -image::rest-api-swagger-expanding-an-endpoint.png[] +image::rest-api-swagger-expanding-an-endpoint.png[Example Swagger UI showing cluster endpoint] -After expanding the endpoint, let's proceed to send a request. Click the `Try it out` button, enter the parameters (if any). There are no parameters for this example. +After expanding the endpoint, let's send a request. Click **Try it out**. There are no parameters for this example but if there were you could enter these here. Click **Execute** to send the request. image::rest-api-swagger-clicking-execute-button.png[] -Click the `Execute` button to send the request. You can see the response in the **Server response** section as shown below. You can also see the executed cURL command in the **Curl** section. +You can see the response in the **Server response** section shown below. You can also see the executed cURL command in the **Curl** section. image::rest-api-swagger-clicking-try-it-out-button.png[] == GET/POST/DELETE HTTP Request Examples -All the requests in the REST API can return one of the following response types. +All REST API requests return one of the following response types: * Successful void/boolean response which does not have a body. @@ -357,11 +446,9 @@ All the requests in the REST API can return one of the following response types. } ---- -=== Retrieving Cluster Status +=== Retrieve cluster status -You can send a `GET` request to the endpoint at `/hazelcast/rest/api/v1/cluster` to retrieve the status of your cluster. - -Example request using cURL: +You can send a `GET` request to the endpoint at `/hazelcast/rest/api/v1/cluster` to retrieve the cluster status. For example, using cURL: [source,shell] ---- @@ -370,7 +457,7 @@ curl -X 'GET' \ -H 'Authorization: Bearer ' ---- -It returns the following response if successful: +If successful the following response is returned: [source,json] ---- @@ -391,11 +478,9 @@ It returns the following response if successful: } ---- -=== Retrieving Cluster State - -You can send a `GET` request to the endpoint at `/hazelcast/rest/api/v1/cluster/state` to retrieve the state of your cluster. +=== Retrieve cluster state -Example request using cURL: +You can send a `GET` request to the endpoint at `/hazelcast/rest/api/v1/cluster/state` to retrieve the cluster state. For example, using cURL: [source,shell] ---- @@ -404,7 +489,7 @@ curl -X 'GET' \ -H 'Authorization: Bearer ' ---- -It returns the following response if successful: +If successful the following response is returned: [source,json] ---- @@ -413,9 +498,9 @@ It returns the following response if successful: } ---- -=== Changing Cluster State +=== Change cluster state -You can send a `POST` request to the endpoint at `/hazelcast/rest/api/v1/cluster/state` to change the state of your cluster. You must provide the new state within the request body in the JSON format. Valid states are `ACTIVE`, `NO_MIGRATION`, `FROZEN`, `PASSIVE`. +You can send a `POST` request to the endpoint at `/hazelcast/rest/api/v1/cluster/state` to change the cluster state. You must provide the new state within the request body in JSON format; valid states are `ACTIVE`, `NO_MIGRATION`, `FROZEN`, `PASSIVE`. Example request using cURL: @@ -430,8 +515,8 @@ curl -X 'POST' \ }' ---- -* It returns 200 response without body if successful. -* It returns 400 response if provided state is not a valid cluster state. For example: +* If successful, it will return a `200` response without body. +* If the provided state is not a valid cluster state, it will return a `400` response with a message. For example: [source,json] ---- @@ -441,11 +526,9 @@ curl -X 'POST' \ } ---- -=== Destroying a CP Group +=== Destroy a CP Group -You can send a `DELETE` request to the endpoint at `/hazelcast/rest/api/v1/cp/groups/{group-name}` to unconditionally destroy the given active CP group. - -Example request using cURL: +You can send a `DELETE` request to the endpoint at `/hazelcast/rest/api/v1/cp/groups/{group-name}` to unconditionally destroy the given active CP group. For example, using cURL: [source,shell] ---- @@ -454,8 +537,8 @@ curl -X 'DELETE' \ -H 'Authorization: Bearer Bearer ' ---- -* It returns 200 response without body if successful. -* It returns 400 response if you try to destroy METADATA group. For example: +* If successful, it will return a `200` response without body. +* If you try to destroy METADATA group, it will return a `400` response: [source,json] ---- @@ -465,7 +548,7 @@ curl -X 'DELETE' \ } ---- -* It returns 500 response if CP subsystem is not enabled: +* If CP subsystem is not enabled, it will return a `500` response: [source,json] ---- @@ -475,16 +558,19 @@ curl -X 'DELETE' \ } ---- -== Dynamic Configuration Update REST Endpoint -You can use the `/hazelcast/rest/api/v1/config/update` REST endpoint to change dynamic server configurations (for more info, see xref:configuration:dynamic-config.adoc[Dynamic Configuration for Members]). With dynamic configuration you can change existing configurations dynamically, as well as add new configurations for Hazelcast data structures. +== Update dynamic configuration using REST +You can use the `/hazelcast/rest/api/v1/config/update` REST endpoint to change dynamic server configurations (for more info, see xref:configuration:dynamic-config.adoc[Dynamic Configuration for Members]). With dynamic configuration you can dynamically change existing configurations, or add new configurations for Hazelcast data structures. -The endpoint requires that you send a XML/YAML server configuration file with the changes required. The response will be two lists in JSON format. The first list includes the newly added configuration among the configurations sent to the server. The second list includes ignored configurations which were in the sent configuration list but could not be applied at the server (examples of these could include static rather than dynamic configurations, which can not therefore be applied dynamically, or duplicate configurations already added). +The endpoint requires that you send a XML/YAML server configuration file with the required changes. The response will be two lists in JSON format: -Whether a dynamic configuration can be applied or not depends on the request. For some updates, it is allowed to change configuration parameters of an existing configuration while for some others you are not allowed to change the configuration. Please see the xref:configuration:dynamic-config.adoc[Dynamic Configuration for Members] section on details about which configuration parameters can be changed dynamically and which can not be changed. +- The first `addedConfigs` list includes the newly added configuration among the configurations sent to the server. +- The second `ignoredConfigs` list includes ignored configurations which were in the sent configuration list but could not be applied by the server. These could include duplicates, or static configurations (which cannot be applied dynamically). + +Whether a dynamic configuration can be applied or not depends on the type of request. For some updates, you can change configuration parameters for an existing configuration; for other updates, you cannot change the configuration dynamically. For more detail on which configuration parameters can be changed dynamically and which cannot, see xref:configuration:dynamic-config.adoc[Dynamic Configuration for Members]. Let's walk through some example requests and responses. -=== Add New MapConfig Using XML Configuration +=== Add new MapConfig using XML configuration Here is an example POST request for adding a new `MapConfig` for my-map: [source,shell] @@ -503,7 +589,7 @@ curl -X 'POST' \ ' ---- -This request creates a configuration for a new map named `my-map`. The in-memory format is set to `BINARY`, while statistics are enabled and the backup count is set to `2`. +This request creates a configuration for a new map named `my-map`. The in-memory format is set to `BINARY`, statistics are enabled, and the backup count is set to `2`. In response to this request we should receive a response body such as: @@ -521,8 +607,8 @@ In response to this request we should receive a response body such as: ---- As the response indicates, a new map config is added to the `map` section with the name `my-map` and the requested dynamic configurations are applied. -=== Add New MapConfig Using YAML Configuration -Here is an example POST request for adding a new `MapConfig` for my-map-yaml using the YAML configuration: +=== Add new MapConfig using YAML configuration +Here is an example POST request for adding a new `MapConfig` for `my-map-yaml` using YAML configuration: [source,shell] ---- @@ -539,9 +625,9 @@ curl -X 'POST' \ backup-count: 2' ---- -We send a request to create a new config for the new map to be created named `my-map-yaml`. The in-memory format is set to BINARY while the statistics is enabled and the backup count is set to 2. +This request creates a new map config named `my-map-yaml`. The in-memory format is set to `BINARY`, statistics are enabled, and the backup count is set to `2`. -When we send this request we receive the response body similar to this: +In response to this request we should receive a response body such as: [source,json] ---- @@ -555,10 +641,10 @@ When we send this request we receive the response body similar to this: "ignoredConfigs": [] } ---- -As you can observe from the response, a new map config is added for map with name my-map-yaml and all the requested dynamic configurations are applied. +As the response shows, a new map config is added for map with name `my-map-yaml` and all the requested dynamic configurations are applied. -=== Add New Conflicting MapConfig For An Existing Map -If you like to add the config with the same map name and a different configuration, then you get response code 400 meaning an invalid configuration is provided since you can not change an existing map configuration. Let's try this: +=== Add new conflicting MapConfig for an existing map +If you try to add a config with the same map name and a different configuration, then you get a `400` response code indicating an invalid configuration, because you cannot change an existing map configuration. This example would look like the following: [source,shell] ---- curl -X 'POST' \ @@ -572,7 +658,7 @@ curl -X 'POST' \ ' ---- -The response has a `statusCode` of 400, and the error message adds further detail: +The response has a `statusCode` of `400`, and the response body adds further detail. including the explanation `as there is already a conflicting configuration 'MapConfig{name='my-map', ...`: [source,json] ---- { @@ -580,10 +666,9 @@ The response has a `statusCode` of 400, and the error message adds further detai "message": "Cannot add a dynamic configuration 'MapConfig{name='my-map', inMemoryFormat='BINARY', metadataPolicy=CREATE_ON_UPDATE, backupCount=1, asyncBackupCount=0, timeToLiveSeconds=0, maxIdleSeconds=0, readBackupData=false, evictionConfig=EvictionConfig{size=2147483647, maxSizePolicy=PER_NODE, evictionPolicy=NONE, comparatorClassName=null, comparator=null}, merkleTree=MerkleTreeConfig{enabled=null, depth=10}, eventJournal=EventJournalConfig{enabled=false, capacity=10000, timeToLiveSeconds=0}, hotRestart=HotRestartConfig{enabled=false, fsync=false}, dataPersistenceConfig=DataPersistenceConfig{enabled=false, fsync=false}, nearCacheConfig=null, mapStoreConfig=MapStoreConfig{enabled=false, className='null', factoryClassName='null', writeDelaySeconds=0, writeBatchSize=1, implementation=null, factoryImplementation=null, properties={}, initialLoadMode=LAZY, writeCoalescing=true, offload=true}, mergePolicyConfig=MergePolicyConfig{policy='com.hazelcast.spi.merge.PutIfAbsentMergePolicy', batchSize=100}, wanReplicationRef=null, entryListenerConfigs=null, indexConfigs=null, attributeConfigs=null, splitBrainProtectionName=null, queryCacheConfigs=null, cacheDeserializedValues=INDEX_ONLY, statisticsEnabled=false, entryStatsEnabled=false, tieredStoreConfig=TieredStoreConfig{enabled=false, memoryTierConfig=MemoryTierConfig{capacity=256 MEGABYTES}, diskTierConfig=DiskTierConfig{enabled=false, deviceName='default-tiered-store-device'}}, partitioningAttributeConfigs=null, userCodeNamespace=null}' as there is already a conflicting configuration 'MapConfig{name='my-map', inMemoryFormat='BINARY', metadataPolicy=CREATE_ON_UPDATE, backupCount=2, asyncBackupCount=0, timeToLiveSeconds=0, maxIdleSeconds=0, readBackupData=false, evictionConfig=EvictionConfig{size=2147483647, maxSizePolicy=PER_NODE, evictionPolicy=NONE, comparatorClassName=null, comparator=null}, merkleTree=MerkleTreeConfig{enabled=null, depth=10}, eventJournal=EventJournalConfig{enabled=false, capacity=10000, timeToLiveSeconds=0}, hotRestart=HotRestartConfig{enabled=false, fsync=false}, dataPersistenceConfig=DataPersistenceConfig{enabled=false, fsync=false}, nearCacheConfig=null, mapStoreConfig=MapStoreConfig{enabled=false, className='null', factoryClassName='null', writeDelaySeconds=0, writeBatchSize=1, implementation=null, factoryImplementation=null, properties={}, initialLoadMode=LAZY, writeCoalescing=true, offload=true}, mergePolicyConfig=MergePolicyConfig{policy='com.hazelcast.spi.merge.PutIfAbsentMergePolicy', batchSize=100}, wanReplicationRef=null, entryListenerConfigs=null, indexConfigs=null, attributeConfigs=null, splitBrainProtectionName=null, queryCacheConfigs=null, cacheDeserializedValues=INDEX_ONLY, statisticsEnabled=true, entryStatsEnabled=false, tieredStoreConfig=TieredStoreConfig{enabled=false, memoryTierConfig=MemoryTierConfig{capacity=256 MEGABYTES}, diskTierConfig=DiskTierConfig{enabled=false, deviceName='default-tiered-store-device'}}, partitioningAttributeConfigs=null, userCodeNamespace=null}'" } ---- -Within the response body you can see the explanation "as there is already a conflicting configuration 'MapConfig{name='my-map'". -=== Add New MapConfig For An Existing Map But With No Configuration Change -As detailed above, you cannot add a map configuration with the same map name. If you send an update request with the same configuration and map name, this request will be ignored as there is no change. Let's look at this as an example: +=== Add new MapConfig without configuration change for an existing map +As detailed above, you cannot add a map configuration with the same map name. If you send an update request with the same configuration and map name, this request will be ignored as there is no change. This example would look like the following: [source,shell] ---- curl -X 'POST' \ @@ -614,8 +699,8 @@ This request receives an `OK (200)` response code and the following body: ---- As the response confirms, no configs are added and the provided config is ignored. -=== Add New MapConfig With Duplicate Configs -As you can see, you can not try adding a map config with the same map name. You can send an update request with the same configuration and map name, and you will observe that this update will be ignored since there is no change. Let's try the request again: +=== Add new MapConfig with duplicate config +You can send an update request with the same configuration and map name, but this update will be ignored because there is no change. This example would look like the following: [source,shell] ---- curl -X 'POST' \ @@ -632,7 +717,7 @@ curl -X 'POST' \ ' ---- -We receive a response code OK (200) and the following body: +This request receives an `OK (200)` response code and the following body: [source,json] ---- { @@ -645,11 +730,10 @@ We receive a response code OK (200) and the following body: "ignoredConfigs": [] } ---- -As you see from the response, only one MapConfig is added since the duplicate one has exactly the same configuration. +As you can see from the response, only one MapConfig is added because the duplicate has exactly the same configuration. -=== Try Adding Non-dynamic Static Configuration -You can try to change a static config, for example the `cluster-name` and observe that it is ignored silently. Since it is not a dynamic configuration, it is neither in ignored nor in the added configs list. -An example request: +=== Try adding non-dynamic static configuration +You can try to change a static configuration and you will observe that it is ignored silently. An example using `cluster-name` would look like the following: [source,shell] ---- curl -X 'POST' \ @@ -661,7 +745,7 @@ curl -X 'POST' \ ' ---- -We receive a response code OK (200) and the following body: +This request receives an `OK (200)` response code and the following body, with no entries under either the added or ignored section: [source,json] ---- { @@ -669,5 +753,3 @@ We receive a response code OK (200) and the following body: "ignoredConfigs": [] } ---- - -As you can see from the response, the static configuration is ignored but not listed in the ignored configurations list. diff --git a/docs/modules/maintain-cluster/partials/nav.adoc b/docs/modules/maintain-cluster/partials/nav.adoc index d58d89c42..7b47dd110 100644 --- a/docs/modules/maintain-cluster/partials/nav.adoc +++ b/docs/modules/maintain-cluster/partials/nav.adoc @@ -6,4 +6,3 @@ ** xref:maintain-cluster:lite-members.adoc[Lite Members] ** xref:maintain-cluster:shutdown.adoc[Shutting Down] ** xref:management:cluster-utilities.adoc[Cluster Utilities] -** xref:maintain-cluster:rest-api-swagger.adoc[REST API]