From 12a74d2a16df06301bfc87d6ad02baacdfec547c Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 14 Jul 2023 16:59:14 -0400 Subject: [PATCH 1/5] Proof of concept of extension reserved indices Signed-off-by: Craig Perkins --- .../org/opensearch/sdk/ExtensionsRunner.java | 10 ++++ .../java/org/opensearch/sdk/SDKClient.java | 41 +++++++++++++-- .../ExtensionsInitRequestHandler.java | 51 +++++++++++++++++++ .../resources/sample/helloworld-settings.yml | 14 ++--- 4 files changed, 104 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java index 8cdf91b5..62a2a3bb 100644 --- a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java +++ b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java @@ -19,6 +19,7 @@ import org.opensearch.action.support.TransportAction; import org.opensearch.cluster.metadata.IndexNameExpressionResolver; import org.opensearch.core.common.io.stream.NamedWriteableRegistry; +import org.opensearch.discovery.InitializeExtensionSecurityRequest; import org.opensearch.extensions.rest.ExtensionRestRequest; import org.opensearch.common.settings.Setting; import org.opensearch.common.settings.Settings; @@ -403,6 +404,15 @@ public void startTransportService(TransportService transportService) { (request, channel, task) -> channel.sendResponse(extensionsInitRequestHandler.handleExtensionInitRequest(request)) ); + transportService.registerRequestHandler( + ExtensionsManager.REQUEST_EXTENSION_REGISTER_SECURITY_SETTINGS, + ThreadPool.Names.GENERIC, + false, + false, + InitializeExtensionSecurityRequest::new, + (request, channel, task) -> channel.sendResponse(extensionsInitRequestHandler.handleExtensionSecurityInitRequest(request)) + ); + transportService.registerRequestHandler( ExtensionsManager.REQUEST_REST_EXECUTE_ON_EXTENSION_ACTION, ThreadPool.Names.GENERIC, diff --git a/src/main/java/org/opensearch/sdk/SDKClient.java b/src/main/java/org/opensearch/sdk/SDKClient.java index cde35678..3cbb639f 100644 --- a/src/main/java/org/opensearch/sdk/SDKClient.java +++ b/src/main/java/org/opensearch/sdk/SDKClient.java @@ -23,11 +23,13 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.guava.GuavaModule; import org.apache.hc.core5.function.Factory; +import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.nio.ssl.TlsStrategy; import org.apache.hc.core5.reactor.ssl.TlsDetails; import org.apache.hc.core5.ssl.SSLContextBuilder; @@ -165,7 +167,7 @@ public void updateOpenSearchNodeSettings(String address, String httpPort) { * @return An instance of the builder */ private static RestClientBuilder builder(String hostAddress, int port) { - RestClientBuilder builder = RestClient.builder(new HttpHost(hostAddress, port)); + RestClientBuilder builder = RestClient.builder(new HttpHost("https", hostAddress, port)); builder.setStrictDeprecationMode(true); builder.setHttpClientConfigCallback(httpClientBuilder -> { try { @@ -201,8 +203,9 @@ public TlsDetails create(final SSLEngine sslEngine) { * @param port The port of OpenSearch cluster * @return The OpenSearchTransport implementation of RestClientTransport. */ - private OpenSearchTransport initializeTransport(String hostAddress, int port) { + private OpenSearchTransport initializeTransport(String hostAddress, int port, Map headers) { RestClientBuilder builder = builder(hostAddress, port); + builder.setDefaultHeaders(headers.keySet().stream().map(k -> new BasicHeader(k, headers.get(k))).toArray(Header[]::new)); restClient = builder.build(); ObjectMapper mapper = new ObjectMapper(); @@ -227,6 +230,20 @@ public OpenSearchClient initializeJavaClient() { return initializeJavaClient(extensionSettings.getOpensearchAddress(), Integer.parseInt(extensionSettings.getOpensearchPort())); } + /** + * Initializes an OpenSearchClient using OpenSearch JavaClient + * + * @return The SDKClient implementation of OpenSearchClient. The user is responsible for calling + * {@link #doCloseJavaClients()} when finished with the client + */ + public OpenSearchClient initializeJavaClientWithHeaders(Map headers) { + return initializeJavaClientWithHeaders( + extensionSettings.getOpensearchAddress(), + Integer.parseInt(extensionSettings.getOpensearchPort()), + headers + ); + } + /** * Initializes an OpenSearchClient using OpenSearch JavaClient * @@ -236,7 +253,21 @@ public OpenSearchClient initializeJavaClient() { * {@link #doCloseJavaClients()} when finished with the client */ public OpenSearchClient initializeJavaClient(String hostAddress, int port) { - OpenSearchTransport transport = initializeTransport(hostAddress, port); + OpenSearchTransport transport = initializeTransport(hostAddress, port, Map.of()); + javaClient = new OpenSearchClient(transport); + return javaClient; + } + + /** + * Initializes an OpenSearchClient using OpenSearch JavaClient + * + * @param hostAddress The address of OpenSearch cluster, client can connect to + * @param port The port of OpenSearch cluster + * @return The SDKClient implementation of OpenSearchClient. The user is responsible for calling + * {@link #doCloseJavaClients()} when finished with the client + */ + public OpenSearchClient initializeJavaClientWithHeaders(String hostAddress, int port, Map headers) { + OpenSearchTransport transport = initializeTransport(hostAddress, port, headers); javaClient = new OpenSearchClient(transport); return javaClient; } @@ -260,7 +291,7 @@ public OpenSearchAsyncClient initializeJavaAsyncClient() { * {@link #doCloseJavaClients()} when finished with the client */ public OpenSearchAsyncClient initalizeJavaAsyncClient(String hostAddress, int port) { - OpenSearchTransport transport = initializeTransport(hostAddress, port); + OpenSearchTransport transport = initializeTransport(hostAddress, port, Map.of()); javaAsyncClient = new OpenSearchAsyncClient(transport); return javaAsyncClient; } @@ -556,7 +587,7 @@ public void bulk(BulkRequest request, ActionListener listener) { * @return the response returned by OpenSearch * @throws IOException in case of a problem or the connection was aborted */ - public Response performRequest(Request request) throws IOException { + public Response uest(Request request) throws IOException { return restHighLevelClient.getLowLevelClient().performRequest(request); } diff --git a/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java b/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java index fc4eb87a..ec85bffe 100644 --- a/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java +++ b/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java @@ -12,13 +12,24 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.opensearch.client.WarningFailureException; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch.indices.CreateIndexRequest; +import org.opensearch.client.opensearch.indices.DeleteIndexRequest; import org.opensearch.common.settings.Settings; import org.opensearch.discovery.InitializeExtensionRequest; import org.opensearch.discovery.InitializeExtensionResponse; +import org.opensearch.discovery.InitializeExtensionSecurityRequest; +import org.opensearch.discovery.InitializeExtensionSecurityResponse; import org.opensearch.sdk.ExtensionsRunner; import org.opensearch.sdk.SDKTransportService; import org.opensearch.transport.TransportService; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Map; + import static org.opensearch.sdk.ExtensionsRunner.NODE_NAME_SETTING; /** @@ -94,4 +105,44 @@ public InitializeExtensionResponse handleExtensionInitRequest(InitializeExtensio extensionsRunner.getSdkClusterService().getClusterSettings().sendPendingSettingsUpdateConsumers(); } } + + /** + * Handles a extension request from OpenSearch. This is the first request for the transport communication and will initialize the extension and will be a part of OpenSearch bootstrap. + * + * @param extensionInitSecurityRequest The request to handle. + * @return A response to OpenSearch validating that this is an extension. + */ + public InitializeExtensionSecurityResponse handleExtensionSecurityInitRequest( + InitializeExtensionSecurityRequest extensionInitSecurityRequest + ) { + logger.info("Registering Extension Request received from OpenSearch"); + + System.out.println("Service Account Token: " + extensionInitSecurityRequest.getServiceAccountToken()); + + OpenSearchClient restClient1 = extensionsRunner.getSdkClient() + .initializeJavaClientWithHeaders( + Map.of("Authorization", "Basic " + Base64.getEncoder().encodeToString("admin:admin".getBytes(StandardCharsets.UTF_8))) + ); + + try { + restClient1.indices().create(new CreateIndexRequest.Builder().index(".hello-world-jobs").build()); + } catch (IOException e) { + System.out.println(e.getMessage()); + } catch (WarningFailureException e2) { + System.out.println(e2.getMessage()); + } + + OpenSearchClient restClient2 = extensionsRunner.getSdkClient() + .initializeJavaClientWithHeaders(Map.of("Authorization", "Bearer " + extensionInitSecurityRequest.getServiceAccountToken())); + + try { + restClient2.indices().delete(new DeleteIndexRequest.Builder().index(".hello-world-jobs").build()); + } catch (IOException e) { + System.out.println(e.getMessage()); + } catch (WarningFailureException e2) { + System.out.println(e2.getMessage()); + } + + return new InitializeExtensionSecurityResponse(extensionsRunner.getExtensionNode().getId()); + } } diff --git a/src/main/resources/sample/helloworld-settings.yml b/src/main/resources/sample/helloworld-settings.yml index 15cdbdcf..2441b480 100644 --- a/src/main/resources/sample/helloworld-settings.yml +++ b/src/main/resources/sample/helloworld-settings.yml @@ -1,11 +1,11 @@ extensionName: hello-world hostAddress: 127.0.0.1 -hostPort: 4500 +hostPort: 4532 opensearchAddress: 127.0.0.1 opensearchPort: 9200 -#ssl.transport.enabled: true -#ssl.transport.pemcert_filepath: certs/extension-01.pem -#ssl.transport.pemkey_filepath: certs/extension-01-key.pem -#ssl.transport.pemtrustedcas_filepath: certs/root-ca.pem -#ssl.transport.enforce_hostname_verification: false -#path.home: +ssl.transport.enabled: true +ssl.transport.pemcert_filepath: certs/extension-01.pem +ssl.transport.pemkey_filepath: certs/extension-01-key.pem +ssl.transport.pemtrustedcas_filepath: certs/root-ca.pem +ssl.transport.enforce_hostname_verification: false +path.home: /Users/cwperx/Projects/opensearch/opensearch-sdk-java From ab837b6f2d7c65f562e2bd4957a60ca46f783f95 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 19 Jul 2023 15:32:42 -0400 Subject: [PATCH 2/5] Handle obo token Signed-off-by: Craig Perkins --- .../ExtensionsRestRequestHandler.java | 15 ++++++- .../helloworld/rest/RestHelloAction.java | 4 +- .../rest/RestRemoteHelloAction.java | 41 ++++++++++++++++++- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/opensearch/sdk/handlers/ExtensionsRestRequestHandler.java b/src/main/java/org/opensearch/sdk/handlers/ExtensionsRestRequestHandler.java index 88f60b56..7c4a4b02 100644 --- a/src/main/java/org/opensearch/sdk/handlers/ExtensionsRestRequestHandler.java +++ b/src/main/java/org/opensearch/sdk/handlers/ExtensionsRestRequestHandler.java @@ -9,6 +9,7 @@ package org.opensearch.sdk.handlers; +import joptsimple.internal.Strings; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.opensearch.core.common.bytes.BytesReference; @@ -22,6 +23,10 @@ import org.opensearch.sdk.rest.SDKHttpRequest; import org.opensearch.sdk.rest.SDKRestRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.emptyMap; import static java.util.Collections.emptyList; @@ -68,11 +73,19 @@ public RestExecuteOnExtensionResponse handleRestExecuteOnExtensionRequest(Extens ); } + String oboToken = request.getRequestIssuerIdentity(); + Map> headers = new HashMap<>(); + headers.putAll(request.headers()); + System.out.println("oboToken: " + oboToken); + if (!Strings.isNullOrEmpty(oboToken)) { + headers.put("Authorization", List.of("Bearer " + oboToken)); + } + SDKRestRequest sdkRestRequest = new SDKRestRequest( sdkNamedXContentRegistry.getRegistry(), request.params(), request.path(), - request.headers(), + headers, new SDKHttpRequest(request), null ); diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java index 46722bc5..974d9829 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java @@ -10,6 +10,8 @@ package org.opensearch.sdk.sample.helloworld.rest; import org.opensearch.OpenSearchParseException; +import org.opensearch.client.WarningFailureException; +import org.opensearch.client.opensearch.indices.CreateIndexRequest; import org.opensearch.core.common.bytes.BytesReference; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.common.xcontent.XContentType; @@ -48,7 +50,7 @@ public class RestHelloAction extends BaseExtensionRestHandler { private static final String TEXT_CONTENT_TYPE = "text/plain; charset=UTF-8"; - private static final String GREETING = "Hello, %s!"; + public static final String GREETING = "Hello, %s!"; private static final String DEFAULT_NAME = "World"; private String worldName = DEFAULT_NAME; diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java index 7bda7ff1..e3c5ebd5 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java @@ -10,6 +10,9 @@ package org.opensearch.sdk.sample.helloworld.rest; import org.opensearch.action.ActionListener; +import org.opensearch.client.WarningFailureException; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch.indices.CreateIndexRequest; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.extensions.ExtensionsManager; import org.opensearch.extensions.action.RemoteExtensionActionResponse; @@ -22,18 +25,25 @@ import org.opensearch.sdk.action.RemoteExtensionAction; import org.opensearch.sdk.action.RemoteExtensionActionRequest; import org.opensearch.sdk.rest.BaseExtensionRestHandler; +import org.opensearch.sdk.rest.SDKRestRequest; import org.opensearch.sdk.sample.helloworld.transport.SampleAction; import org.opensearch.sdk.sample.helloworld.transport.SampleRequest; import org.opensearch.sdk.sample.helloworld.transport.SampleResponse; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.function.Function; import static org.opensearch.rest.RestRequest.Method.GET; import static org.opensearch.core.rest.RestStatus.OK; +import static org.opensearch.sdk.sample.helloworld.rest.RestHelloAction.GREETING; /** * Sample REST Handler demonstrating proxy actions to another extension @@ -60,7 +70,13 @@ public List routes() { .handler(handleRemoteGetRequest) .uniqueName(addRouteNamePrefix("remote_greet_with_name")) .legacyActionNames(Collections.emptySet()) - .build() + .build(), + new NamedRoute.Builder().method(GET) + .path("/greet/{name}") + .handler(handleLocalGetRequest) + .uniqueName(addRouteNamePrefix("local_greet_with_name")) + .legacyActionNames(Collections.emptySet()) + .build() ); } @@ -101,4 +117,27 @@ public List routes() { } }; + private Function handleLocalGetRequest = (request) -> { + SDKRestRequest sdkRestRequest = (SDKRestRequest) request; + List authorizationHeaders = sdkRestRequest.getHeaders().get("Authorization"); + Map headers = new HashMap<>(); + if (!authorizationHeaders.isEmpty()) { + headers.put("Authorization", authorizationHeaders.get(0)); + } + OpenSearchClient restClient1 = extensionsRunner.getSdkClient() + .initializeJavaClientWithHeaders(headers); + + try { + restClient1.indices().create(new CreateIndexRequest.Builder().index(".my-index").build()); + } catch (IOException e) { + System.out.println(e.getMessage()); + } catch (WarningFailureException e2) { + System.out.println(e2.getMessage()); + } + + String name = request.param("name"); + + return new ExtensionRestResponse(request, OK, String.format(GREETING, name)); + }; + } From 3f2ee2a2184430f9df8cdd6a91eef0ef88ffe0dd Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 20 Jul 2023 10:23:24 -0400 Subject: [PATCH 3/5] WIP on user and extension client in the SDK Signed-off-by: Craig Perkins --- .../ExtensionsInitRequestHandler.java | 108 +++++++++++++++--- .../helloworld/rest/RestHelloAction.java | 2 - .../rest/RestRemoteHelloAction.java | 15 +-- 3 files changed, 95 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java b/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java index ec85bffe..9285f237 100644 --- a/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java +++ b/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java @@ -9,11 +9,16 @@ package org.opensearch.sdk.handlers; +import com.fasterxml.jackson.databind.JsonNode; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.opensearch.client.RequestOptions; import org.opensearch.client.WarningFailureException; import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch.core.IndexRequest; +import org.opensearch.client.opensearch.core.SearchRequest; +import org.opensearch.client.opensearch.core.SearchResponse; import org.opensearch.client.opensearch.indices.CreateIndexRequest; import org.opensearch.client.opensearch.indices.DeleteIndexRequest; import org.opensearch.common.settings.Settings; @@ -119,30 +124,95 @@ public InitializeExtensionSecurityResponse handleExtensionSecurityInitRequest( System.out.println("Service Account Token: " + extensionInitSecurityRequest.getServiceAccountToken()); - OpenSearchClient restClient1 = extensionsRunner.getSdkClient() - .initializeJavaClientWithHeaders( - Map.of("Authorization", "Basic " + Base64.getEncoder().encodeToString("admin:admin".getBytes(StandardCharsets.UTF_8))) - ); + // Uncomment the lines below to try out different actions utilizing the service account token + +// OpenSearchClient restClient1 = extensionsRunner.getSdkClient() +// .initializeJavaClientWithHeaders( +// Map.of("Authorization", "Basic " + Base64.getEncoder().encodeToString("admin:admin".getBytes(StandardCharsets.UTF_8))) +// ); +// +// try { +// restClient1.indices().create(new CreateIndexRequest.Builder().index(".hello-world-jobs").build()); +// } catch (IOException e) { +// System.out.println(e.getMessage()); +// } catch (WarningFailureException e2) { +// System.out.println(e2.getMessage()); +// } +// +// OpenSearchClient restClient2 = extensionsRunner.getSdkClient() +// .initializeJavaClientWithHeaders(Map.of("Authorization", "Bearer " + extensionInitSecurityRequest.getServiceAccountToken())); +// +// try { +// restClient2.indices().delete(new DeleteIndexRequest.Builder().index(".hello-world-jobs").build()); +// } catch (IOException e) { +// System.out.println(e.getMessage()); +// } catch (WarningFailureException e2) { +// System.out.println(e2.getMessage()); +// } +// +// // Try reading from index with service account token +// +// try { +// restClient1.indices().create(new CreateIndexRequest.Builder().index("logs-123").build()); +// } catch (IOException e) { +// System.out.println(e.getMessage()); +// } catch (WarningFailureException e2) { +// System.out.println(e2.getMessage()); +// } +// +// try { +// SearchRequest searchRequest = new SearchRequest.Builder() +// .index("logs-123") +// .build(); +// SearchResponse searchResponse = restClient2.search(searchRequest, JsonNode.class); +// System.out.println("SearchResponse: " + searchResponse); +// } catch (IOException e) { +// System.out.println(e.getMessage()); +// } catch (WarningFailureException e2) { +// System.out.println(e2.getMessage()); +// } +// +// try { +// IndexData indexData = new IndexData("John", "Doe"); +// IndexRequest indexRequest = new IndexRequest.Builder().index("logs-123").id("1").document(indexData).build(); +// restClient2.index(indexRequest); +// } catch (IOException e) { +// System.out.println(e.getMessage()); +// } catch (WarningFailureException e2) { +// System.out.println(e2.getMessage()); +// } - try { - restClient1.indices().create(new CreateIndexRequest.Builder().index(".hello-world-jobs").build()); - } catch (IOException e) { - System.out.println(e.getMessage()); - } catch (WarningFailureException e2) { - System.out.println(e2.getMessage()); + return new InitializeExtensionSecurityResponse(extensionsRunner.getExtensionNode().getId()); + } + + static class IndexData { + private String firstName; + private String lastName; + + public IndexData(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; } - OpenSearchClient restClient2 = extensionsRunner.getSdkClient() - .initializeJavaClientWithHeaders(Map.of("Authorization", "Bearer " + extensionInitSecurityRequest.getServiceAccountToken())); + public void setFirstName(String firstName) { + this.firstName = firstName; + } - try { - restClient2.indices().delete(new DeleteIndexRequest.Builder().index(".hello-world-jobs").build()); - } catch (IOException e) { - System.out.println(e.getMessage()); - } catch (WarningFailureException e2) { - System.out.println(e2.getMessage()); + public String getLastName() { + return lastName; } - return new InitializeExtensionSecurityResponse(extensionsRunner.getExtensionNode().getId()); + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public String toString() { + return String.format("IndexData{first name='%s', last name='%s'}", firstName, lastName); + } } } diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java index 974d9829..406ff503 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java @@ -10,8 +10,6 @@ package org.opensearch.sdk.sample.helloworld.rest; import org.opensearch.OpenSearchParseException; -import org.opensearch.client.WarningFailureException; -import org.opensearch.client.opensearch.indices.CreateIndexRequest; import org.opensearch.core.common.bytes.BytesReference; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.common.xcontent.XContentType; diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java index e3c5ebd5..1848e187 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java @@ -31,8 +31,6 @@ import org.opensearch.sdk.sample.helloworld.transport.SampleResponse; import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Base64; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -72,11 +70,11 @@ public List routes() { .legacyActionNames(Collections.emptySet()) .build(), new NamedRoute.Builder().method(GET) - .path("/greet/{name}") - .handler(handleLocalGetRequest) - .uniqueName(addRouteNamePrefix("local_greet_with_name")) - .legacyActionNames(Collections.emptySet()) - .build() + .path("/greet/{name}") + .handler(handleLocalGetRequest) + .uniqueName(addRouteNamePrefix("local_greet_with_name")) + .legacyActionNames(Collections.emptySet()) + .build() ); } @@ -124,8 +122,7 @@ public List routes() { if (!authorizationHeaders.isEmpty()) { headers.put("Authorization", authorizationHeaders.get(0)); } - OpenSearchClient restClient1 = extensionsRunner.getSdkClient() - .initializeJavaClientWithHeaders(headers); + OpenSearchClient restClient1 = extensionsRunner.getSdkClient().initializeJavaClientWithHeaders(headers); try { restClient1.indices().create(new CreateIndexRequest.Builder().index(".my-index").build()); From 27f0100c87737d47292fb36c53770f1b0656885f Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 21 Jul 2023 14:17:51 -0400 Subject: [PATCH 4/5] Use auth tokens passed frmo core and introduce extension and user REST clients Signed-off-by: Craig Perkins --- .../org/opensearch/sdk/ExtensionSettings.java | 2 + .../org/opensearch/sdk/ExtensionsRunner.java | 24 ++++ .../java/org/opensearch/sdk/SDKClient.java | 14 ++- .../ExtensionsInitRequestHandler.java | 91 +------------- .../sdk/rest/BaseExtensionRestHandler.java | 21 ++++ .../helloworld/HelloWorldExtension.java | 2 +- .../helloworld/rest/RestHelloAction.java | 5 +- .../rest/RestRemoteHelloAction.java | 112 ++++++++++++++++-- .../sdk/ssl/SSLConfigConstants.java | 1 + .../resources/sample/helloworld-settings.yml | 13 +- .../rest/TestBaseExtensionRestHandler.java | 10 +- .../rest/TestExtensionRestPathRegistry.java | 6 +- .../helloworld/rest/TestRestHelloAction.java | 7 +- 13 files changed, 192 insertions(+), 116 deletions(-) diff --git a/src/main/java/org/opensearch/sdk/ExtensionSettings.java b/src/main/java/org/opensearch/sdk/ExtensionSettings.java index 52f08ce6..5372cdc5 100644 --- a/src/main/java/org/opensearch/sdk/ExtensionSettings.java +++ b/src/main/java/org/opensearch/sdk/ExtensionSettings.java @@ -21,6 +21,7 @@ import org.yaml.snakeyaml.Yaml; +import static org.opensearch.sdk.ssl.SSLConfigConstants.SSL_HTTP_ENABLED; import static org.opensearch.sdk.ssl.SSLConfigConstants.SSL_TRANSPORT_CLIENT_PEMCERT_FILEPATH; import static org.opensearch.sdk.ssl.SSLConfigConstants.SSL_TRANSPORT_CLIENT_PEMKEY_FILEPATH; import static org.opensearch.sdk.ssl.SSLConfigConstants.SSL_TRANSPORT_CLIENT_PEMTRUSTEDCAS_FILEPATH; @@ -62,6 +63,7 @@ public class ExtensionSettings { */ public static final Set SECURITY_SETTINGS_KEYS = Set.of( "path.home", // TODO Find the right place to put this setting + SSL_HTTP_ENABLED, SSL_TRANSPORT_CLIENT_PEMCERT_FILEPATH, SSL_TRANSPORT_CLIENT_PEMKEY_FILEPATH, SSL_TRANSPORT_CLIENT_PEMTRUSTEDCAS_FILEPATH, diff --git a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java index 62a2a3bb..aeb44b48 100644 --- a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java +++ b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java @@ -17,6 +17,7 @@ import org.apache.logging.log4j.Logger; import org.opensearch.action.ActionType; import org.opensearch.action.support.TransportAction; +import org.opensearch.client.opensearch.OpenSearchClient; import org.opensearch.cluster.metadata.IndexNameExpressionResolver; import org.opensearch.core.common.io.stream.NamedWriteableRegistry; import org.opensearch.discovery.InitializeExtensionSecurityRequest; @@ -126,6 +127,7 @@ public class ExtensionsRunner { private final SDKNamedXContentRegistry sdkNamedXContentRegistry; private final SDKNamedWriteableRegistry sdkNamedWriteableRegistry; private final SDKClient sdkClient; + private OpenSearchClient extensionRestClient; private final SDKClusterService sdkClusterService; private final SDKTransportService sdkTransportService; private final SDKActionModule sdkActionModule; @@ -345,6 +347,19 @@ public void setExtensionNode(DiscoveryExtensionNode extensionNode) { this.extensionNode = extensionNode; } + /** + * Initializes a REST Client for this extension to interact with an OpenSearch cluster on its own behalf + * + * @param serviceAccountToken Access token that permits an extension to make requests on its own behalf. + * Common examples of usages of service account tokens include interacting with + * an extension's reserved indices. + */ + public void initializeExtensionRestClient(String serviceAccountToken) { + OpenSearchClient restClient = getSdkClient() + .initializeJavaClientWithHeaders(Map.of("Authorization", "Bearer " + serviceAccountToken)); + this.extensionRestClient = restClient; + } + /** * Returns the discovery extension node set during extension initialization * @@ -538,6 +553,15 @@ public SDKClient getSdkClient() { return sdkClient; } + /** + * Returns the Extension rest client instance used by this extension. + * + * @return The Extension rest client instance. + */ + public OpenSearchClient getExtensionRestClient() { + return extensionRestClient; + } + /** * @return The SDKClusterService instance associated with this object. */ diff --git a/src/main/java/org/opensearch/sdk/SDKClient.java b/src/main/java/org/opensearch/sdk/SDKClient.java index 3cbb639f..6a5efd77 100644 --- a/src/main/java/org/opensearch/sdk/SDKClient.java +++ b/src/main/java/org/opensearch/sdk/SDKClient.java @@ -97,6 +97,9 @@ import javax.net.ssl.SSLEngine; +import static org.opensearch.sdk.ssl.SSLConfigConstants.SSL_HTTP_ENABLED; +import static org.opensearch.sdk.ssl.SSLConfigConstants.SSL_TRANSPORT_ENABLED; + /** * This class creates SDKClient for an extension to make requests to OpenSearch */ @@ -166,8 +169,11 @@ public void updateOpenSearchNodeSettings(String address, String httpPort) { * @param port The port the client should connect to * @return An instance of the builder */ - private static RestClientBuilder builder(String hostAddress, int port) { - RestClientBuilder builder = RestClient.builder(new HttpHost("https", hostAddress, port)); + private static RestClientBuilder builder(String hostAddress, int port, ExtensionSettings extensionSettings) { + boolean httpsEnabled = extensionSettings.getSecuritySettings().containsKey(SSL_HTTP_ENABLED) + && "true".equals(extensionSettings.getSecuritySettings().get(SSL_HTTP_ENABLED)); + String scheme = httpsEnabled ? "https" : "http"; + RestClientBuilder builder = RestClient.builder(new HttpHost(scheme, hostAddress, port)); builder.setStrictDeprecationMode(true); builder.setHttpClientConfigCallback(httpClientBuilder -> { try { @@ -204,7 +210,7 @@ public TlsDetails create(final SSLEngine sslEngine) { * @return The OpenSearchTransport implementation of RestClientTransport. */ private OpenSearchTransport initializeTransport(String hostAddress, int port, Map headers) { - RestClientBuilder builder = builder(hostAddress, port); + RestClientBuilder builder = builder(hostAddress, port, extensionSettings); builder.setDefaultHeaders(headers.keySet().stream().map(k -> new BasicHeader(k, headers.get(k))).toArray(Header[]::new)); restClient = builder.build(); @@ -331,7 +337,7 @@ public SDKRestClient initializeRestClient() { */ @Deprecated public SDKRestClient initializeRestClient(String hostAddress, int port) { - this.sdkRestClient = new SDKRestClient(this, new RestHighLevelClient(builder(hostAddress, port))); + this.sdkRestClient = new SDKRestClient(this, new RestHighLevelClient(builder(hostAddress, port, extensionSettings))); return this.sdkRestClient; } diff --git a/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java b/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java index 9285f237..b20bf765 100644 --- a/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java +++ b/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java @@ -122,97 +122,8 @@ public InitializeExtensionSecurityResponse handleExtensionSecurityInitRequest( ) { logger.info("Registering Extension Request received from OpenSearch"); - System.out.println("Service Account Token: " + extensionInitSecurityRequest.getServiceAccountToken()); - - // Uncomment the lines below to try out different actions utilizing the service account token - -// OpenSearchClient restClient1 = extensionsRunner.getSdkClient() -// .initializeJavaClientWithHeaders( -// Map.of("Authorization", "Basic " + Base64.getEncoder().encodeToString("admin:admin".getBytes(StandardCharsets.UTF_8))) -// ); -// -// try { -// restClient1.indices().create(new CreateIndexRequest.Builder().index(".hello-world-jobs").build()); -// } catch (IOException e) { -// System.out.println(e.getMessage()); -// } catch (WarningFailureException e2) { -// System.out.println(e2.getMessage()); -// } -// -// OpenSearchClient restClient2 = extensionsRunner.getSdkClient() -// .initializeJavaClientWithHeaders(Map.of("Authorization", "Bearer " + extensionInitSecurityRequest.getServiceAccountToken())); -// -// try { -// restClient2.indices().delete(new DeleteIndexRequest.Builder().index(".hello-world-jobs").build()); -// } catch (IOException e) { -// System.out.println(e.getMessage()); -// } catch (WarningFailureException e2) { -// System.out.println(e2.getMessage()); -// } -// -// // Try reading from index with service account token -// -// try { -// restClient1.indices().create(new CreateIndexRequest.Builder().index("logs-123").build()); -// } catch (IOException e) { -// System.out.println(e.getMessage()); -// } catch (WarningFailureException e2) { -// System.out.println(e2.getMessage()); -// } -// -// try { -// SearchRequest searchRequest = new SearchRequest.Builder() -// .index("logs-123") -// .build(); -// SearchResponse searchResponse = restClient2.search(searchRequest, JsonNode.class); -// System.out.println("SearchResponse: " + searchResponse); -// } catch (IOException e) { -// System.out.println(e.getMessage()); -// } catch (WarningFailureException e2) { -// System.out.println(e2.getMessage()); -// } -// -// try { -// IndexData indexData = new IndexData("John", "Doe"); -// IndexRequest indexRequest = new IndexRequest.Builder().index("logs-123").id("1").document(indexData).build(); -// restClient2.index(indexRequest); -// } catch (IOException e) { -// System.out.println(e.getMessage()); -// } catch (WarningFailureException e2) { -// System.out.println(e2.getMessage()); -// } + extensionsRunner.initializeExtensionRestClient(extensionInitSecurityRequest.getServiceAccountToken()); return new InitializeExtensionSecurityResponse(extensionsRunner.getExtensionNode().getId()); } - - static class IndexData { - private String firstName; - private String lastName; - - public IndexData(String firstName, String lastName) { - this.firstName = firstName; - this.lastName = lastName; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - @Override - public String toString() { - return String.format("IndexData{first name='%s', last name='%s'}", firstName, lastName); - } - } } diff --git a/src/main/java/org/opensearch/sdk/rest/BaseExtensionRestHandler.java b/src/main/java/org/opensearch/sdk/rest/BaseExtensionRestHandler.java index dc39eab2..3473c33a 100644 --- a/src/main/java/org/opensearch/sdk/rest/BaseExtensionRestHandler.java +++ b/src/main/java/org/opensearch/sdk/rest/BaseExtensionRestHandler.java @@ -11,7 +11,9 @@ import java.nio.charset.StandardCharsets; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; @@ -25,6 +27,7 @@ import static org.apache.hc.core5.http.ContentType.APPLICATION_JSON; import org.opensearch.OpenSearchException; +import org.opensearch.client.opensearch.OpenSearchClient; import org.opensearch.common.logging.DeprecationLogger; import org.opensearch.common.xcontent.json.JsonXContent; import org.opensearch.core.common.Strings; @@ -38,6 +41,7 @@ import org.opensearch.rest.RestRequest.Method; import org.opensearch.rest.RestResponse; import org.opensearch.core.rest.RestStatus; +import org.opensearch.sdk.SDKClient; /** * Provides convenience methods to reduce boilerplate code in an {@link ExtensionRestHandler} implementation. @@ -48,6 +52,14 @@ public abstract class BaseExtensionRestHandler implements ExtensionRestHandler { private String routeNamePrefix; + private SDKClient sdkClient; + + protected OpenSearchClient userRestClient; + + public BaseExtensionRestHandler(SDKClient sdkClient) { + this.sdkClient = sdkClient; + } + /** * Constant for JSON content type */ @@ -114,6 +126,15 @@ public List replacedRoutes() { @Override public ExtensionRestResponse handleRequest(RestRequest request) { + if (request instanceof SDKRestRequest) { + SDKRestRequest sdkRestRequest = (SDKRestRequest) request; + List authorizationHeaders = sdkRestRequest.getHeaders().get("Authorization"); + Map headers = new HashMap<>(); + if (!authorizationHeaders.isEmpty()) { + headers.put("Authorization", authorizationHeaders.get(0)); + } + this.userRestClient = sdkClient.initializeJavaClientWithHeaders(headers); + } Optional route = routes().stream() .filter(rh -> rh.getMethod().equals(request.method())) .filter(rh -> restPathMatches(request.path(), rh.getPath())) diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/HelloWorldExtension.java b/src/main/java/org/opensearch/sdk/sample/helloworld/HelloWorldExtension.java index f4b8566d..5ac9a58a 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/HelloWorldExtension.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/HelloWorldExtension.java @@ -56,7 +56,7 @@ public HelloWorldExtension() { @Override public List getExtensionRestHandlers() { - return List.of(new RestHelloAction(), new RestRemoteHelloAction(extensionsRunner())); + return List.of(new RestHelloAction(extensionsRunner().getSdkClient()), new RestRemoteHelloAction(extensionsRunner())); } @Override diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java index 406ff503..cdb26593 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java @@ -18,6 +18,7 @@ import org.opensearch.rest.NamedRoute; import org.opensearch.rest.RestRequest; import org.opensearch.rest.RestResponse; +import org.opensearch.sdk.SDKClient; import org.opensearch.sdk.rest.BaseExtensionRestHandler; import org.opensearch.sdk.rest.ExtensionRestHandler; @@ -58,7 +59,9 @@ public class RestHelloAction extends BaseExtensionRestHandler { /** * Instantiate this action */ - public RestHelloAction() {} + public RestHelloAction(SDKClient sdkClient) { + super(sdkClient); + } @Override public List routes() { diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java index 1848e187..c613aa09 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java @@ -13,6 +13,7 @@ import org.opensearch.client.WarningFailureException; import org.opensearch.client.opensearch.OpenSearchClient; import org.opensearch.client.opensearch.indices.CreateIndexRequest; +import org.opensearch.client.opensearch.indices.DeleteIndexRequest; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.extensions.ExtensionsManager; import org.opensearch.extensions.action.RemoteExtensionActionResponse; @@ -31,6 +32,8 @@ import org.opensearch.sdk.sample.helloworld.transport.SampleResponse; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -56,6 +59,7 @@ public class RestRemoteHelloAction extends BaseExtensionRestHandler { * @param runner The ExtensionsRunner instance */ public RestRemoteHelloAction(ExtensionsRunner runner) { + super(runner.getSdkClient()); this.extensionsRunner = runner; } @@ -74,6 +78,12 @@ public List routes() { .handler(handleLocalGetRequest) .uniqueName(addRouteNamePrefix("local_greet_with_name")) .legacyActionNames(Collections.emptySet()) + .build(), + new NamedRoute.Builder().method(GET) + .path("/service_account_token_example") + .handler(handleServiceAccountTokenExampleRequest) + .uniqueName(addRouteNamePrefix("service_account_token_example")) + .legacyActionNames(Collections.emptySet()) .build() ); } @@ -116,16 +126,9 @@ public List routes() { }; private Function handleLocalGetRequest = (request) -> { - SDKRestRequest sdkRestRequest = (SDKRestRequest) request; - List authorizationHeaders = sdkRestRequest.getHeaders().get("Authorization"); - Map headers = new HashMap<>(); - if (!authorizationHeaders.isEmpty()) { - headers.put("Authorization", authorizationHeaders.get(0)); - } - OpenSearchClient restClient1 = extensionsRunner.getSdkClient().initializeJavaClientWithHeaders(headers); - + // Example usage of userRestClient try { - restClient1.indices().create(new CreateIndexRequest.Builder().index(".my-index").build()); + userRestClient.indices().create(new CreateIndexRequest.Builder().index(".my-index").build()); } catch (IOException e) { System.out.println(e.getMessage()); } catch (WarningFailureException e2) { @@ -137,4 +140,95 @@ public List routes() { return new ExtensionRestResponse(request, OK, String.format(GREETING, name)); }; + private Function handleServiceAccountTokenExampleRequest = (request) -> { + // Uncomment the lines below to try out different actions utilizing the service account token + + OpenSearchClient adminRestClient = extensionsRunner.getSdkClient() + .initializeJavaClientWithHeaders( + Map.of("Authorization", "Basic " + Base64.getEncoder().encodeToString("admin:admin".getBytes(StandardCharsets.UTF_8))) + ); + + try { + adminRestClient.indices().create(new CreateIndexRequest.Builder().index(".hello-world-jobs").build()); + } catch (IOException e) { + System.out.println(e.getMessage()); + } catch (WarningFailureException e2) { + System.out.println(e2.getMessage()); + } + + // Example usage of extension rest client - utilizing service account token + try { + extensionsRunner.getExtensionRestClient().indices().delete(new DeleteIndexRequest.Builder().index(".hello-world-jobs").build()); + } catch (IOException e) { + System.out.println(e.getMessage()); + } catch (WarningFailureException e2) { + System.out.println(e2.getMessage()); + } + + // Try reading from index with service account token + +// try { +// adminRestClient.indices().create(new CreateIndexRequest.Builder().index("logs-123").build()); +// } catch (IOException e) { +// System.out.println(e.getMessage()); +// } catch (WarningFailureException e2) { +// System.out.println(e2.getMessage()); +// } +// +// try { +// SearchRequest searchRequest = new SearchRequest.Builder() +// .index("logs-123") +// .build(); +// SearchResponse searchResponse = userRestClient.search(searchRequest, JsonNode.class); +// System.out.println("SearchResponse: " + searchResponse); +// } catch (IOException e) { +// System.out.println(e.getMessage()); +// } catch (WarningFailureException e2) { +// System.out.println(e2.getMessage()); +// } +// +// try { +// IndexData indexData = new IndexData("John", "Doe"); +// IndexRequest indexRequest = new IndexRequest.Builder().index("logs-123").id("1").document(indexData).build(); +// userRestClient.index(indexRequest); +// } catch (IOException e) { +// System.out.println(e.getMessage()); +// } catch (WarningFailureException e2) { +// System.out.println(e2.getMessage()); +// } + + return new ExtensionRestResponse(request, OK, String.format(GREETING, "World")); + }; + + static class IndexData { + private String firstName; + private String lastName; + + public IndexData(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public String toString() { + return String.format("IndexData{first name='%s', last name='%s'}", firstName, lastName); + } + } + } diff --git a/src/main/java/org/opensearch/sdk/ssl/SSLConfigConstants.java b/src/main/java/org/opensearch/sdk/ssl/SSLConfigConstants.java index c5735761..3122b643 100644 --- a/src/main/java/org/opensearch/sdk/ssl/SSLConfigConstants.java +++ b/src/main/java/org/opensearch/sdk/ssl/SSLConfigConstants.java @@ -19,6 +19,7 @@ * Class containing constants for SSL */ public final class SSLConfigConstants { + public static final String SSL_HTTP_ENABLED = "ssl.http.enabled"; public static final String SSL_TRANSPORT_ENABLED = "ssl.transport.enabled"; // TODO Replace this with true when security changes are complete public static final boolean SSL_TRANSPORT_ENABLED_DEFAULT = false; diff --git a/src/main/resources/sample/helloworld-settings.yml b/src/main/resources/sample/helloworld-settings.yml index 2441b480..6b8a4836 100644 --- a/src/main/resources/sample/helloworld-settings.yml +++ b/src/main/resources/sample/helloworld-settings.yml @@ -3,9 +3,10 @@ hostAddress: 127.0.0.1 hostPort: 4532 opensearchAddress: 127.0.0.1 opensearchPort: 9200 -ssl.transport.enabled: true -ssl.transport.pemcert_filepath: certs/extension-01.pem -ssl.transport.pemkey_filepath: certs/extension-01-key.pem -ssl.transport.pemtrustedcas_filepath: certs/root-ca.pem -ssl.transport.enforce_hostname_verification: false -path.home: /Users/cwperx/Projects/opensearch/opensearch-sdk-java +#ssl.http.enabled: true +#ssl.transport.enabled: true +#ssl.transport.pemcert_filepath: certs/extension-01.pem +#ssl.transport.pemkey_filepath: certs/extension-01-key.pem +#ssl.transport.pemtrustedcas_filepath: certs/root-ca.pem +#ssl.transport.enforce_hostname_verification: false +#path.home: /Users/cwperx/Projects/opensearch/opensearch-sdk-java diff --git a/src/test/java/org/opensearch/sdk/rest/TestBaseExtensionRestHandler.java b/src/test/java/org/opensearch/sdk/rest/TestBaseExtensionRestHandler.java index cd0e24bf..772b84cc 100644 --- a/src/test/java/org/opensearch/sdk/rest/TestBaseExtensionRestHandler.java +++ b/src/test/java/org/opensearch/sdk/rest/TestBaseExtensionRestHandler.java @@ -23,13 +23,17 @@ import org.opensearch.rest.RestRequest.Method; import org.opensearch.rest.RestResponse; import org.opensearch.core.rest.RestStatus; +import org.opensearch.sdk.ExtensionSettings; +import org.opensearch.sdk.SDKClient; import org.opensearch.test.OpenSearchTestCase; import static org.opensearch.rest.RestRequest.Method.GET; public class TestBaseExtensionRestHandler extends OpenSearchTestCase { - private final BaseExtensionRestHandler handler = new BaseExtensionRestHandler() { + private final ExtensionSettings extensionSettings = new ExtensionSettings("", "", "", "localhost", "9200"); + private final SDKClient sdkClient = new SDKClient(extensionSettings); + private final BaseExtensionRestHandler handler = new BaseExtensionRestHandler(sdkClient) { @Override public List routes() { return List.of( @@ -80,7 +84,7 @@ public List replacedRouteHandlers() { @Test public void testHandlerDefaultRoutes() { - BaseExtensionRestHandler defaultHandler = new BaseExtensionRestHandler() { + BaseExtensionRestHandler defaultHandler = new BaseExtensionRestHandler(sdkClient) { }; assertTrue(defaultHandler.routes().isEmpty()); } @@ -287,7 +291,7 @@ public void testErrorResponseOnUnhandled() { @Test public void testCreateEmptyJsonResponse() { - BaseExtensionRestHandler handlerWithEmptyJsonResponse = new BaseExtensionRestHandler() { + BaseExtensionRestHandler handlerWithEmptyJsonResponse = new BaseExtensionRestHandler(sdkClient) { @Override public List routes() { return List.of( diff --git a/src/test/java/org/opensearch/sdk/rest/TestExtensionRestPathRegistry.java b/src/test/java/org/opensearch/sdk/rest/TestExtensionRestPathRegistry.java index 008214d0..da7c9f94 100644 --- a/src/test/java/org/opensearch/sdk/rest/TestExtensionRestPathRegistry.java +++ b/src/test/java/org/opensearch/sdk/rest/TestExtensionRestPathRegistry.java @@ -21,6 +21,8 @@ import org.opensearch.rest.RestHandler.ReplacedRoute; import org.opensearch.rest.RestRequest; import org.opensearch.rest.RestRequest.Method; +import org.opensearch.sdk.ExtensionSettings; +import org.opensearch.sdk.SDKClient; import org.opensearch.sdk.rest.BaseExtensionRestHandler.ExtensionDeprecationRestHandler; import org.opensearch.test.OpenSearchTestCase; @@ -44,7 +46,9 @@ public ExtensionRestResponse handleRequest(RestRequest request) { return null; } }; - private BaseExtensionRestHandler replacedFooHandler = new BaseExtensionRestHandler() { + + private final ExtensionSettings extensionSettings = new ExtensionSettings("", "", "", "localhost", "9200"); + private BaseExtensionRestHandler replacedFooHandler = new BaseExtensionRestHandler(new SDKClient(extensionSettings)) { @Override public List replacedRoutes() { return List.of( diff --git a/src/test/java/org/opensearch/sdk/sample/helloworld/rest/TestRestHelloAction.java b/src/test/java/org/opensearch/sdk/sample/helloworld/rest/TestRestHelloAction.java index 09c5c96f..0ccb6606 100644 --- a/src/test/java/org/opensearch/sdk/sample/helloworld/rest/TestRestHelloAction.java +++ b/src/test/java/org/opensearch/sdk/sample/helloworld/rest/TestRestHelloAction.java @@ -25,6 +25,8 @@ import org.opensearch.http.HttpRequest.HttpVersion; import org.opensearch.rest.RestResponse; import org.opensearch.core.rest.RestStatus; +import org.opensearch.sdk.ExtensionSettings; +import org.opensearch.sdk.SDKClient; import org.opensearch.sdk.rest.ExtensionRestHandler; import org.opensearch.sdk.rest.TestSDKRestRequest; import org.opensearch.test.OpenSearchTestCase; @@ -34,6 +36,9 @@ public class TestRestHelloAction extends OpenSearchTestCase { private static final String TEXT_CONTENT_TYPE = "text/plain; charset=UTF-8"; private static final String JSON_CONTENT_TYPE = "application/json; charset=UTF-8"; + private final ExtensionSettings extensionSettings = new ExtensionSettings("", "", "", "localhost", "9200"); + private final SDKClient sdkClient = new SDKClient(extensionSettings); + private ExtensionRestHandler restHelloAction; // Temporarily removed pending integration of feature/identity branch // private static final String EXTENSION_NAME = "hello-world"; @@ -42,7 +47,7 @@ public class TestRestHelloAction extends OpenSearchTestCase { @BeforeEach public void setUp() throws Exception { super.setUp(); - restHelloAction = new RestHelloAction(); + restHelloAction = new RestHelloAction(sdkClient); } @Test From 19fff3e270e5a7b1cdacda245aefeace2eaf3c91 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 18 Aug 2023 11:53:03 -0400 Subject: [PATCH 5/5] Update ActionListener Signed-off-by: Craig Perkins --- .../org/opensearch/sdk/ExtensionsRunner.java | 5 +- .../java/org/opensearch/sdk/SDKClient.java | 9 ++- .../opensearch/sdk/SDKTransportService.java | 2 +- .../action/RemoteExtensionActionRequest.java | 2 +- .../RemoteExtensionTransportAction.java | 2 +- .../opensearch/sdk/api/ActionExtension.java | 2 +- .../ExtensionActionRequestHandler.java | 4 +- .../ExtensionsInitRequestHandler.java | 14 ---- .../handlers/OpensearchRequestHandler.java | 2 +- .../helloworld/HelloWorldExtension.java | 2 +- .../rest/RestRemoteHelloAction.java | 69 +++++++++---------- .../helloworld/transport/SampleResponse.java | 2 +- .../transport/SampleTransportAction.java | 2 +- .../org/opensearch/sdk/TestSDKClient.java | 2 +- 14 files changed, 52 insertions(+), 67 deletions(-) diff --git a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java index aeb44b48..ce789b51 100644 --- a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java +++ b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java @@ -355,8 +355,9 @@ public void setExtensionNode(DiscoveryExtensionNode extensionNode) { * an extension's reserved indices. */ public void initializeExtensionRestClient(String serviceAccountToken) { - OpenSearchClient restClient = getSdkClient() - .initializeJavaClientWithHeaders(Map.of("Authorization", "Bearer " + serviceAccountToken)); + OpenSearchClient restClient = getSdkClient().initializeJavaClientWithHeaders( + Map.of("Authorization", "Bearer " + serviceAccountToken) + ); this.extensionRestClient = restClient; } diff --git a/src/main/java/org/opensearch/sdk/SDKClient.java b/src/main/java/org/opensearch/sdk/SDKClient.java index 6a5efd77..19f61559 100644 --- a/src/main/java/org/opensearch/sdk/SDKClient.java +++ b/src/main/java/org/opensearch/sdk/SDKClient.java @@ -33,9 +33,9 @@ import org.apache.hc.core5.http.nio.ssl.TlsStrategy; import org.apache.hc.core5.reactor.ssl.TlsDetails; import org.apache.hc.core5.ssl.SSLContextBuilder; -import org.opensearch.action.ActionListener; +import org.opensearch.core.action.ActionListener; import org.opensearch.action.ActionRequest; -import org.opensearch.action.ActionResponse; +import org.opensearch.core.action.ActionResponse; import org.opensearch.action.ActionType; import org.opensearch.action.admin.cluster.health.ClusterHealthRequest; import org.opensearch.action.admin.cluster.health.ClusterHealthResponse; @@ -98,7 +98,6 @@ import javax.net.ssl.SSLEngine; import static org.opensearch.sdk.ssl.SSLConfigConstants.SSL_HTTP_ENABLED; -import static org.opensearch.sdk.ssl.SSLConfigConstants.SSL_TRANSPORT_ENABLED; /** * This class creates SDKClient for an extension to make requests to OpenSearch @@ -171,7 +170,7 @@ public void updateOpenSearchNodeSettings(String address, String httpPort) { */ private static RestClientBuilder builder(String hostAddress, int port, ExtensionSettings extensionSettings) { boolean httpsEnabled = extensionSettings.getSecuritySettings().containsKey(SSL_HTTP_ENABLED) - && "true".equals(extensionSettings.getSecuritySettings().get(SSL_HTTP_ENABLED)); + && "true".equals(extensionSettings.getSecuritySettings().get(SSL_HTTP_ENABLED)); String scheme = httpsEnabled ? "https" : "http"; RestClientBuilder builder = RestClient.builder(new HttpHost(scheme, hostAddress, port)); builder.setStrictDeprecationMode(true); @@ -593,7 +592,7 @@ public void bulk(BulkRequest request, ActionListener listener) { * @return the response returned by OpenSearch * @throws IOException in case of a problem or the connection was aborted */ - public Response uest(Request request) throws IOException { + public Response performRequest(Request request) throws IOException { return restHighLevelClient.getLowLevelClient().performRequest(request); } diff --git a/src/main/java/org/opensearch/sdk/SDKTransportService.java b/src/main/java/org/opensearch/sdk/SDKTransportService.java index ac873c73..056e8a7e 100644 --- a/src/main/java/org/opensearch/sdk/SDKTransportService.java +++ b/src/main/java/org/opensearch/sdk/SDKTransportService.java @@ -26,6 +26,7 @@ import org.opensearch.cluster.node.DiscoveryNode; import org.opensearch.common.settings.Setting; import org.opensearch.common.settings.Settings; +import org.opensearch.core.transport.TransportResponse; import org.opensearch.extensions.AddSettingsUpdateConsumerRequest; import org.opensearch.extensions.DiscoveryExtensionNode; import org.opensearch.extensions.ExtensionRequest; @@ -47,7 +48,6 @@ import org.opensearch.sdk.handlers.ExtensionDependencyResponseHandler; import org.opensearch.sdk.handlers.UpdateSettingsRequestHandler; import org.opensearch.sdk.rest.ExtensionRestPathRegistry; -import org.opensearch.transport.TransportResponse; import org.opensearch.transport.TransportResponseHandler; import org.opensearch.transport.TransportService; diff --git a/src/main/java/org/opensearch/sdk/action/RemoteExtensionActionRequest.java b/src/main/java/org/opensearch/sdk/action/RemoteExtensionActionRequest.java index 85c7108f..abf53a23 100644 --- a/src/main/java/org/opensearch/sdk/action/RemoteExtensionActionRequest.java +++ b/src/main/java/org/opensearch/sdk/action/RemoteExtensionActionRequest.java @@ -14,7 +14,7 @@ import org.opensearch.action.ActionRequest; import org.opensearch.action.ActionRequestValidationException; -import org.opensearch.action.ActionResponse; +import org.opensearch.core.action.ActionResponse; import org.opensearch.action.ActionType; import org.opensearch.core.common.bytes.BytesReference; import org.opensearch.common.io.stream.BytesStreamOutput; diff --git a/src/main/java/org/opensearch/sdk/action/RemoteExtensionTransportAction.java b/src/main/java/org/opensearch/sdk/action/RemoteExtensionTransportAction.java index fa9ce8ed..d6948dbf 100644 --- a/src/main/java/org/opensearch/sdk/action/RemoteExtensionTransportAction.java +++ b/src/main/java/org/opensearch/sdk/action/RemoteExtensionTransportAction.java @@ -9,7 +9,7 @@ package org.opensearch.sdk.action; -import org.opensearch.action.ActionListener; +import org.opensearch.core.action.ActionListener; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.TransportAction; import org.opensearch.extensions.action.RemoteExtensionActionResponse; diff --git a/src/main/java/org/opensearch/sdk/api/ActionExtension.java b/src/main/java/org/opensearch/sdk/api/ActionExtension.java index 0c807f01..cd6cb915 100644 --- a/src/main/java/org/opensearch/sdk/api/ActionExtension.java +++ b/src/main/java/org/opensearch/sdk/api/ActionExtension.java @@ -11,7 +11,7 @@ import org.opensearch.action.ActionType; import org.opensearch.action.ActionRequest; -import org.opensearch.action.ActionResponse; +import org.opensearch.core.action.ActionResponse; import org.opensearch.action.RequestValidators; import org.opensearch.action.admin.indices.alias.IndicesAliasesRequest; import org.opensearch.action.admin.indices.mapping.put.PutMappingRequest; diff --git a/src/main/java/org/opensearch/sdk/handlers/ExtensionActionRequestHandler.java b/src/main/java/org/opensearch/sdk/handlers/ExtensionActionRequestHandler.java index 54e53b2e..b3b1734d 100644 --- a/src/main/java/org/opensearch/sdk/handlers/ExtensionActionRequestHandler.java +++ b/src/main/java/org/opensearch/sdk/handlers/ExtensionActionRequestHandler.java @@ -18,9 +18,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.opensearch.action.ActionListener; +import org.opensearch.core.action.ActionListener; import org.opensearch.action.ActionRequest; -import org.opensearch.action.ActionResponse; +import org.opensearch.core.action.ActionResponse; import org.opensearch.action.ActionType; import org.opensearch.core.common.bytes.BytesReference; import org.opensearch.common.io.stream.BytesStreamOutput; diff --git a/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java b/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java index b20bf765..482ffabc 100644 --- a/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java +++ b/src/main/java/org/opensearch/sdk/handlers/ExtensionsInitRequestHandler.java @@ -9,18 +9,9 @@ package org.opensearch.sdk.handlers; -import com.fasterxml.jackson.databind.JsonNode; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.opensearch.client.RequestOptions; -import org.opensearch.client.WarningFailureException; -import org.opensearch.client.opensearch.OpenSearchClient; -import org.opensearch.client.opensearch.core.IndexRequest; -import org.opensearch.client.opensearch.core.SearchRequest; -import org.opensearch.client.opensearch.core.SearchResponse; -import org.opensearch.client.opensearch.indices.CreateIndexRequest; -import org.opensearch.client.opensearch.indices.DeleteIndexRequest; import org.opensearch.common.settings.Settings; import org.opensearch.discovery.InitializeExtensionRequest; import org.opensearch.discovery.InitializeExtensionResponse; @@ -30,11 +21,6 @@ import org.opensearch.sdk.SDKTransportService; import org.opensearch.transport.TransportService; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Map; - import static org.opensearch.sdk.ExtensionsRunner.NODE_NAME_SETTING; /** diff --git a/src/main/java/org/opensearch/sdk/handlers/OpensearchRequestHandler.java b/src/main/java/org/opensearch/sdk/handlers/OpensearchRequestHandler.java index 53da0420..64d145e7 100644 --- a/src/main/java/org/opensearch/sdk/handlers/OpensearchRequestHandler.java +++ b/src/main/java/org/opensearch/sdk/handlers/OpensearchRequestHandler.java @@ -9,9 +9,9 @@ package org.opensearch.sdk.handlers; +import org.opensearch.core.transport.TransportResponse; import org.opensearch.extensions.OpenSearchRequest; import org.opensearch.sdk.ExtensionsRunner; -import org.opensearch.transport.TransportResponse; /** * This class handles the request from OpenSearch to a {@link ExtensionsRunner#startTransportService(TransportService transportService)} call. diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/HelloWorldExtension.java b/src/main/java/org/opensearch/sdk/sample/helloworld/HelloWorldExtension.java index 5ac9a58a..5f74d8a5 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/HelloWorldExtension.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/HelloWorldExtension.java @@ -14,7 +14,7 @@ import java.util.List; import org.opensearch.action.ActionRequest; -import org.opensearch.action.ActionResponse; +import org.opensearch.core.action.ActionResponse; import org.opensearch.common.settings.Setting; import org.opensearch.sdk.BaseExtension; import org.opensearch.sdk.Extension; diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java index c613aa09..1f52601f 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java @@ -9,7 +9,7 @@ package org.opensearch.sdk.sample.helloworld.rest; -import org.opensearch.action.ActionListener; +import org.opensearch.core.action.ActionListener; import org.opensearch.client.WarningFailureException; import org.opensearch.client.opensearch.OpenSearchClient; import org.opensearch.client.opensearch.indices.CreateIndexRequest; @@ -26,7 +26,6 @@ import org.opensearch.sdk.action.RemoteExtensionAction; import org.opensearch.sdk.action.RemoteExtensionActionRequest; import org.opensearch.sdk.rest.BaseExtensionRestHandler; -import org.opensearch.sdk.rest.SDKRestRequest; import org.opensearch.sdk.sample.helloworld.transport.SampleAction; import org.opensearch.sdk.sample.helloworld.transport.SampleRequest; import org.opensearch.sdk.sample.helloworld.transport.SampleResponse; @@ -35,7 +34,6 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -144,9 +142,9 @@ public List routes() { // Uncomment the lines below to try out different actions utilizing the service account token OpenSearchClient adminRestClient = extensionsRunner.getSdkClient() - .initializeJavaClientWithHeaders( - Map.of("Authorization", "Basic " + Base64.getEncoder().encodeToString("admin:admin".getBytes(StandardCharsets.UTF_8))) - ); + .initializeJavaClientWithHeaders( + Map.of("Authorization", "Basic " + Base64.getEncoder().encodeToString("admin:admin".getBytes(StandardCharsets.UTF_8))) + ); try { adminRestClient.indices().create(new CreateIndexRequest.Builder().index(".hello-world-jobs").build()); @@ -167,35 +165,36 @@ public List routes() { // Try reading from index with service account token -// try { -// adminRestClient.indices().create(new CreateIndexRequest.Builder().index("logs-123").build()); -// } catch (IOException e) { -// System.out.println(e.getMessage()); -// } catch (WarningFailureException e2) { -// System.out.println(e2.getMessage()); -// } -// -// try { -// SearchRequest searchRequest = new SearchRequest.Builder() -// .index("logs-123") -// .build(); -// SearchResponse searchResponse = userRestClient.search(searchRequest, JsonNode.class); -// System.out.println("SearchResponse: " + searchResponse); -// } catch (IOException e) { -// System.out.println(e.getMessage()); -// } catch (WarningFailureException e2) { -// System.out.println(e2.getMessage()); -// } -// -// try { -// IndexData indexData = new IndexData("John", "Doe"); -// IndexRequest indexRequest = new IndexRequest.Builder().index("logs-123").id("1").document(indexData).build(); -// userRestClient.index(indexRequest); -// } catch (IOException e) { -// System.out.println(e.getMessage()); -// } catch (WarningFailureException e2) { -// System.out.println(e2.getMessage()); -// } + // try { + // adminRestClient.indices().create(new CreateIndexRequest.Builder().index("logs-123").build()); + // } catch (IOException e) { + // System.out.println(e.getMessage()); + // } catch (WarningFailureException e2) { + // System.out.println(e2.getMessage()); + // } + // + // try { + // SearchRequest searchRequest = new SearchRequest.Builder() + // .index("logs-123") + // .build(); + // SearchResponse searchResponse = userRestClient.search(searchRequest, JsonNode.class); + // System.out.println("SearchResponse: " + searchResponse); + // } catch (IOException e) { + // System.out.println(e.getMessage()); + // } catch (WarningFailureException e2) { + // System.out.println(e2.getMessage()); + // } + // + // try { + // IndexData indexData = new IndexData("John", "Doe"); + // IndexRequest indexRequest = new + // IndexRequest.Builder().index("logs-123").id("1").document(indexData).build(); + // userRestClient.index(indexRequest); + // } catch (IOException e) { + // System.out.println(e.getMessage()); + // } catch (WarningFailureException e2) { + // System.out.println(e2.getMessage()); + // } return new ExtensionRestResponse(request, OK, String.format(GREETING, "World")); }; diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/transport/SampleResponse.java b/src/main/java/org/opensearch/sdk/sample/helloworld/transport/SampleResponse.java index 8d3f9b1e..f6be89f1 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/transport/SampleResponse.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/transport/SampleResponse.java @@ -11,7 +11,7 @@ import java.io.IOException; -import org.opensearch.action.ActionResponse; +import org.opensearch.core.action.ActionResponse; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/transport/SampleTransportAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/transport/SampleTransportAction.java index 2c80f1cf..894dd3c6 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/transport/SampleTransportAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/transport/SampleTransportAction.java @@ -9,7 +9,7 @@ package org.opensearch.sdk.sample.helloworld.transport; -import org.opensearch.action.ActionListener; +import org.opensearch.core.action.ActionListener; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.TransportAction; import org.opensearch.tasks.Task; diff --git a/src/test/java/org/opensearch/sdk/TestSDKClient.java b/src/test/java/org/opensearch/sdk/TestSDKClient.java index 0be408f6..778a9b40 100644 --- a/src/test/java/org/opensearch/sdk/TestSDKClient.java +++ b/src/test/java/org/opensearch/sdk/TestSDKClient.java @@ -10,7 +10,7 @@ package org.opensearch.sdk; import org.junit.jupiter.api.Test; -import org.opensearch.action.ActionListener; +import org.opensearch.core.action.ActionListener; import org.opensearch.action.admin.cluster.health.ClusterHealthRequest; import org.opensearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.opensearch.action.admin.indices.alias.get.GetAliasesRequest;