From 43ac117b897737af45eefc5cd7344a41a4e47f7e Mon Sep 17 00:00:00 2001 From: f-galland Date: Tue, 17 Dec 2024 09:09:21 -0300 Subject: [PATCH 01/19] Add Orders model --- .../com/wazuh/commandmanager/model/Order.java | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java new file mode 100644 index 00000000..bcbc0834 --- /dev/null +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2024, Wazuh Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wazuh.commandmanager.model; + +import org.opensearch.common.UUIDs; +import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.core.xcontent.XContentParser; +import reactor.util.annotation.NonNull; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class Order implements ToXContentObject { + public static final String COMMAND = "command"; + public static final String SOURCE = "source"; + public static final String USER = "user"; + private final String source; + private final Target target; + private final String user; + private final Action action; + + /** + * Default constructor + * + * @param source origin of the request. + * @param target {@link Target} + * @param user the user that originated the request + * @param action {@link Action} + */ + public Order( + @NonNull String source, + @NonNull Target target, + @NonNull String user, + @NonNull Action action) { + this.source = source; + this.target = target; + this.user = user; + this.action = action; + } + + /** + * Parses the request's payload into the Command model. + * + * @param parser XContentParser from the Rest Request + * @return instance of Command + * @throws IOException error parsing request content + * @throws IllegalArgumentException missing arguments + */ + public static Order parse(XContentParser parser) + throws IOException, IllegalArgumentException { + String source = null; + Target target = null; + String user = null; + Action action = null; + + while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + String fieldName = parser.currentName(); + + parser.nextToken(); + switch (fieldName) { + case SOURCE: + source = parser.text(); + break; + case Target.TARGET: + target = Target.parse(parser); + break; + case USER: + user = parser.text(); + break; + case Action.ACTION: + action = Action.parse(parser); + break; + default: + parser.skipChildren(); + break; + } + } + + ArrayList nullArguments = new ArrayList<>(); + if (source == null) { + nullArguments.add("source"); + } + if (target == null) { + nullArguments.add("target"); + } + if (user == null) { + nullArguments.add("user"); + } + if (action == null) { + nullArguments.add("action"); + } + + if (!nullArguments.isEmpty()) { + throw new IllegalArgumentException("Missing arguments: " + nullArguments); + } else { + return new Order(source, target, user, action); + } + } + + public static List parseToArray(XContentParser parser) + throws IOException, IllegalArgumentException { + List commands = new ArrayList<>(); + while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + Order command = Order.parse(parser); + commands.add(command); + } + return commands; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(COMMAND); + builder.field(SOURCE, this.source); + builder.field(USER, this.user); + this.target.toXContent(builder, ToXContent.EMPTY_PARAMS); + this.action.toXContent(builder, ToXContent.EMPTY_PARAMS); + + return builder.endObject(); + } + + @Override + public String toString() { + return "Order{" + + "action=" + action + + ", source='" + source + '\'' + + ", target=" + target + + ", user='" + user + '\'' + + '}'; + } +} From 8219a03ce6c8c6524ba79dfb6f0dd9b82047d78c Mon Sep 17 00:00:00 2001 From: f-galland Date: Tue, 17 Dec 2024 09:11:25 -0300 Subject: [PATCH 02/19] Apply spotless --- .../com/wazuh/commandmanager/model/Order.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index bcbc0834..6ede00b1 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -16,17 +16,17 @@ */ package com.wazuh.commandmanager.model; -import org.opensearch.common.UUIDs; import org.opensearch.core.xcontent.ToXContent; import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.core.xcontent.XContentParser; -import reactor.util.annotation.NonNull; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import reactor.util.annotation.NonNull; + public class Order implements ToXContentObject { public static final String COMMAND = "command"; public static final String SOURCE = "source"; @@ -63,8 +63,7 @@ public Order( * @throws IOException error parsing request content * @throws IllegalArgumentException missing arguments */ - public static Order parse(XContentParser parser) - throws IOException, IllegalArgumentException { + public static Order parse(XContentParser parser) throws IOException, IllegalArgumentException { String source = null; Target target = null; String user = null; @@ -137,11 +136,17 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws @Override public String toString() { - return "Order{" + - "action=" + action + - ", source='" + source + '\'' + - ", target=" + target + - ", user='" + user + '\'' + - '}'; + return "Order{" + + "action=" + + action + + ", source='" + + source + + '\'' + + ", target=" + + target + + ", user='" + + user + + '\'' + + '}'; } } From 343caca08b9ac3b1393fc0b3d50679b0e1446ff4 Mon Sep 17 00:00:00 2001 From: f-galland Date: Tue, 17 Dec 2024 19:43:06 -0300 Subject: [PATCH 03/19] Add parse() logic to handle a nested Command --- .../jobscheduler/SearchThread.java | 16 ++++++- .../com/wazuh/commandmanager/model/Order.java | 42 ++++++++++++------- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index 3f9585a6..c8313cd2 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -29,9 +29,10 @@ import org.opensearch.common.action.ActionFuture; import org.opensearch.common.unit.TimeValue; import org.opensearch.common.xcontent.XContentFactory; +import org.opensearch.common.xcontent.json.JsonXContent; import org.opensearch.core.action.ActionListener; import org.opensearch.core.rest.RestStatus; -import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.core.xcontent.*; import org.opensearch.index.query.QueryBuilders; import org.opensearch.index.query.TermQueryBuilder; import org.opensearch.search.SearchHit; @@ -53,6 +54,7 @@ import com.wazuh.commandmanager.CommandManagerPlugin; import com.wazuh.commandmanager.model.Command; import com.wazuh.commandmanager.model.Document; +import com.wazuh.commandmanager.model.Order; import com.wazuh.commandmanager.model.Status; import com.wazuh.commandmanager.settings.PluginSettings; import com.wazuh.commandmanager.utils.httpclient.AuthHttpRestClient; @@ -117,6 +119,18 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti SearchHits searchHits = searchResponse.getHits(); ArrayList orders = new ArrayList<>(); for (SearchHit hit : searchHits) { + try { + XContentParser parser = + JsonXContent.jsonXContent.createParser( + NamedXContentRegistry.EMPTY, + DeprecationHandler.IGNORE_DEPRECATIONS, + hit.getSourceRef().streamInput()); + Order order = Order.parse(parser); + + } catch (IOException e) { + throw new RuntimeException(e); + } + Map orderMap = getNestedObject(hit.getSourceAsMap(), Command.COMMAND, Map.class); if (orderMap != null) { diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index 6ede00b1..8cd2bab3 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -28,13 +28,14 @@ import reactor.util.annotation.NonNull; public class Order implements ToXContentObject { - public static final String COMMAND = "command"; public static final String SOURCE = "source"; public static final String USER = "user"; + public static final String DOCUMENT_ID = "document_id"; private final String source; private final Target target; private final String user; private final Action action; + private final String document_id; /** * Default constructor @@ -48,11 +49,13 @@ public Order( @NonNull String source, @NonNull Target target, @NonNull String user, - @NonNull Action action) { + @NonNull Action action, + @NonNull String document_id) { this.source = source; this.target = target; this.user = user; this.action = action; + this.document_id = document_id; } /** @@ -68,12 +71,18 @@ public static Order parse(XContentParser parser) throws IOException, IllegalArgu Target target = null; String user = null; Action action = null; + String document_id = null; while (parser.nextToken() != XContentParser.Token.END_OBJECT) { String fieldName = parser.currentName(); parser.nextToken(); switch (fieldName) { + // If we find an Order nested below + // a Command object, parse the Order recursively + // and return its output + case Command.COMMAND: + return Order.parse(parser); case SOURCE: source = parser.text(); break; @@ -86,6 +95,9 @@ public static Order parse(XContentParser parser) throws IOException, IllegalArgu case Action.ACTION: action = Action.parse(parser); break; + case DOCUMENT_ID: + document_id = parser.text(); + break; default: parser.skipChildren(); break; @@ -105,11 +117,14 @@ public static Order parse(XContentParser parser) throws IOException, IllegalArgu if (action == null) { nullArguments.add("action"); } + if (document_id == null) { + nullArguments.add("document_id"); + } if (!nullArguments.isEmpty()) { throw new IllegalArgumentException("Missing arguments: " + nullArguments); } else { - return new Order(source, target, user, action); + return new Order(source, target, user, action, document_id); } } @@ -125,7 +140,7 @@ public static List parseToArray(XContentParser parser) @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(COMMAND); + builder.startObject(); builder.field(SOURCE, this.source); builder.field(USER, this.user); this.target.toXContent(builder, ToXContent.EMPTY_PARAMS); @@ -136,17 +151,12 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws @Override public String toString() { - return "Order{" - + "action=" - + action - + ", source='" - + source - + '\'' - + ", target=" - + target - + ", user='" - + user - + '\'' - + '}'; + return "Order{" + + "action=" + action + + ", source='" + source + '\'' + + ", target=" + target + + ", user='" + user + '\'' + + ", document_id='" + document_id + '\'' + + '}'; } } From dbccf7b6ff17b88e855577b7e6667af53b52d6fa Mon Sep 17 00:00:00 2001 From: f-galland Date: Tue, 17 Dec 2024 19:46:00 -0300 Subject: [PATCH 04/19] Apply spotless --- .../com/wazuh/commandmanager/model/Order.java | 55 +++++++------------ 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index 8cd2bab3..1049a765 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -16,18 +16,14 @@ */ package com.wazuh.commandmanager.model; -import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.core.xcontent.ToXContentObject; -import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.core.xcontent.XContentParser; import java.io.IOException; import java.util.ArrayList; -import java.util.List; import reactor.util.annotation.NonNull; -public class Order implements ToXContentObject { +public class Order { public static final String SOURCE = "source"; public static final String USER = "user"; public static final String DOCUMENT_ID = "document_id"; @@ -78,9 +74,9 @@ public static Order parse(XContentParser parser) throws IOException, IllegalArgu parser.nextToken(); switch (fieldName) { - // If we find an Order nested below - // a Command object, parse the Order recursively - // and return its output + // If we find an Order nested below + // a Command object, parse the Order recursively + // and return its output case Command.COMMAND: return Order.parse(parser); case SOURCE: @@ -128,35 +124,22 @@ public static Order parse(XContentParser parser) throws IOException, IllegalArgu } } - public static List parseToArray(XContentParser parser) - throws IOException, IllegalArgumentException { - List commands = new ArrayList<>(); - while (parser.nextToken() != XContentParser.Token.END_ARRAY) { - Order command = Order.parse(parser); - commands.add(command); - } - return commands; - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field(SOURCE, this.source); - builder.field(USER, this.user); - this.target.toXContent(builder, ToXContent.EMPTY_PARAMS); - this.action.toXContent(builder, ToXContent.EMPTY_PARAMS); - - return builder.endObject(); - } - @Override public String toString() { - return "Order{" + - "action=" + action + - ", source='" + source + '\'' + - ", target=" + target + - ", user='" + user + '\'' + - ", document_id='" + document_id + '\'' + - '}'; + return "Order{" + + "action=" + + action + + ", source='" + + source + + '\'' + + ", target=" + + target + + ", user='" + + user + + '\'' + + ", document_id='" + + document_id + + '\'' + + '}'; } } From 881a448cc2293344eee521670e42706944d02406 Mon Sep 17 00:00:00 2001 From: f-galland Date: Tue, 17 Dec 2024 20:37:43 -0300 Subject: [PATCH 05/19] Insert documentId into the Order --- .../jobscheduler/SearchThread.java | 14 +++---- .../com/wazuh/commandmanager/model/Order.java | 37 ++++++++++++------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index c8313cd2..ec1cce87 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -126,17 +126,17 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti DeprecationHandler.IGNORE_DEPRECATIONS, hit.getSourceRef().streamInput()); Order order = Order.parse(parser); - + order.setDocumentId(hit.getId()); } catch (IOException e) { throw new RuntimeException(e); } - Map orderMap = - getNestedObject(hit.getSourceAsMap(), Command.COMMAND, Map.class); - if (orderMap != null) { - orderMap.put("document_id", hit.getId()); - orders.add(orderMap); - } + //Map orderMap = + // getNestedObject(hit.getSourceAsMap(), Command.COMMAND, Map.class); + //if (orderMap != null) { + // orderMap.put("document_id", hit.getId()); + // orders.add(orderMap); + //} } String payload = null; try (XContentBuilder builder = XContentFactory.jsonBuilder()) { diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index 1049a765..8241c88a 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -16,6 +16,9 @@ */ package com.wazuh.commandmanager.model; +import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.core.xcontent.XContentParser; import java.io.IOException; @@ -23,7 +26,7 @@ import reactor.util.annotation.NonNull; -public class Order { +public class Order implements ToXContentObject { public static final String SOURCE = "source"; public static final String USER = "user"; public static final String DOCUMENT_ID = "document_id"; @@ -31,7 +34,7 @@ public class Order { private final Target target; private final String user; private final Action action; - private final String document_id; + private String document_id; /** * Default constructor @@ -45,13 +48,15 @@ public Order( @NonNull String source, @NonNull Target target, @NonNull String user, - @NonNull Action action, - @NonNull String document_id) { + @NonNull Action action) { this.source = source; this.target = target; this.user = user; this.action = action; - this.document_id = document_id; + } + + public void setDocumentId(String documentId) { + this.document_id = documentId; } /** @@ -67,7 +72,6 @@ public static Order parse(XContentParser parser) throws IOException, IllegalArgu Target target = null; String user = null; Action action = null; - String document_id = null; while (parser.nextToken() != XContentParser.Token.END_OBJECT) { String fieldName = parser.currentName(); @@ -91,9 +95,6 @@ public static Order parse(XContentParser parser) throws IOException, IllegalArgu case Action.ACTION: action = Action.parse(parser); break; - case DOCUMENT_ID: - document_id = parser.text(); - break; default: parser.skipChildren(); break; @@ -113,17 +114,27 @@ public static Order parse(XContentParser parser) throws IOException, IllegalArgu if (action == null) { nullArguments.add("action"); } - if (document_id == null) { - nullArguments.add("document_id"); - } if (!nullArguments.isEmpty()) { throw new IllegalArgumentException("Missing arguments: " + nullArguments); } else { - return new Order(source, target, user, action, document_id); + return new Order(source, target, user, action); } } + @Override + public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) + throws IOException { + builder.startObject(); + builder.field(SOURCE, this.source); + builder.field(USER, this.user); + this.target.toXContent(builder, ToXContent.EMPTY_PARAMS); + this.action.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.field(DOCUMENT_ID, this.document_id); + + return builder.endObject(); + } + @Override public String toString() { return "Order{" From 23c3926186a7df6106ff6faffd1a7c6c3d282205 Mon Sep 17 00:00:00 2001 From: f-galland Date: Wed, 18 Dec 2024 08:51:10 -0300 Subject: [PATCH 06/19] Refactor handlePage to use XContentBuilder --- .../jobscheduler/SearchThread.java | 31 +++++++++---------- .../com/wazuh/commandmanager/model/Order.java | 3 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index ec1cce87..993f49aa 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -31,8 +31,10 @@ import org.opensearch.common.xcontent.XContentFactory; import org.opensearch.common.xcontent.json.JsonXContent; import org.opensearch.core.action.ActionListener; +import org.opensearch.core.common.bytes.BytesReference; import org.opensearch.core.rest.RestStatus; import org.opensearch.core.xcontent.*; +import org.opensearch.index.query.QueryBuilder; import org.opensearch.index.query.QueryBuilders; import org.opensearch.index.query.TermQueryBuilder; import org.opensearch.search.SearchHit; @@ -117,9 +119,12 @@ public static T getNestedObject(Map map, String key, Class orders = new ArrayList<>(); - for (SearchHit hit : searchHits) { - try { + String payload = null; + try (XContentBuilder builder = XContentFactory.jsonBuilder()) { + // Start an XContentBuilder array named "orders" + builder.startObject(); + builder.startArray(Order.ORDERS); + for (SearchHit hit : searchHits) { XContentParser parser = JsonXContent.jsonXContent.createParser( NamedXContentRegistry.EMPTY, @@ -127,20 +132,14 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti hit.getSourceRef().streamInput()); Order order = Order.parse(parser); order.setDocumentId(hit.getId()); - } catch (IOException e) { - throw new RuntimeException(e); - } - //Map orderMap = - // getNestedObject(hit.getSourceAsMap(), Command.COMMAND, Map.class); - //if (orderMap != null) { - // orderMap.put("document_id", hit.getId()); - // orders.add(orderMap); - //} - } - String payload = null; - try (XContentBuilder builder = XContentFactory.jsonBuilder()) { - payload = builder.map(Collections.singletonMap("orders", orders)).toString(); + // Add the current order to the XContentBuilder array + order.toXContent(builder,ToXContent.EMPTY_PARAMS); + } + // Close the object and prepare it for delivery + builder.endArray(); + builder.endObject(); + payload = builder.toString(); } catch (IOException e) { log.error("Error parsing hit contents: {}", e.getMessage()); } diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index 8241c88a..8bdd8918 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -26,7 +26,8 @@ import reactor.util.annotation.NonNull; -public class Order implements ToXContentObject { +public class Order implements ToXContent { + public static final String ORDERS = "orders"; public static final String SOURCE = "source"; public static final String USER = "user"; public static final String DOCUMENT_ID = "document_id"; From a4ec7de3c56a180e4ea06b908e79d96d3889d74b Mon Sep 17 00:00:00 2001 From: f-galland Date: Wed, 18 Dec 2024 17:15:38 -0300 Subject: [PATCH 07/19] Make Order use nested Command model --- .../jobscheduler/SearchThread.java | 9 +- .../wazuh/commandmanager/model/Command.java | 21 ++++- .../com/wazuh/commandmanager/model/Order.java | 94 ++++++------------- 3 files changed, 58 insertions(+), 66 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index 993f49aa..0816c83b 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -29,6 +29,8 @@ import org.opensearch.common.action.ActionFuture; import org.opensearch.common.unit.TimeValue; import org.opensearch.common.xcontent.XContentFactory; +import org.opensearch.common.xcontent.XContentHelper; +import org.opensearch.common.xcontent.XContentType; import org.opensearch.common.xcontent.json.JsonXContent; import org.opensearch.core.action.ActionListener; import org.opensearch.core.common.bytes.BytesReference; @@ -126,10 +128,12 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti builder.startArray(Order.ORDERS); for (SearchHit hit : searchHits) { XContentParser parser = - JsonXContent.jsonXContent.createParser( + XContentHelper.createParser( NamedXContentRegistry.EMPTY, DeprecationHandler.IGNORE_DEPRECATIONS, - hit.getSourceRef().streamInput()); + hit.getSourceRef(), + XContentType.JSON + ); Order order = Order.parse(parser); order.setDocumentId(hit.getId()); @@ -261,6 +265,7 @@ public void run() { log.error("IllegalStateException retrieving page: {}", e.getMessage()); } catch (Exception e) { log.error("Generic exception retrieving page: {}", e.getMessage()); + e.printStackTrace(); } } diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Command.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Command.java index a3bfa70b..9373bd7f 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Command.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Command.java @@ -64,9 +64,9 @@ public Command( this.orderId = UUIDs.base64UUID(); this.source = source; this.target = target; - this.timeout = timeout; this.user = user; this.action = action; + this.timeout = timeout; this.status = Status.PENDING; } @@ -96,6 +96,9 @@ public static Command parse(XContentParser parser) Action action = null; while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + if (!parser.currentToken().equals(XContentParser.Token.FIELD_NAME)) { + continue; + } String fieldName = parser.currentName(); parser.nextToken(); @@ -170,6 +173,22 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws return builder.endObject(); } + public Action getAction() { + return action; + } + + public String getSource() { + return source; + } + + public Target getTarget() { + return target; + } + + public String getUser() { + return user; + } + @Override public String toString() { return "Command{" diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index 8bdd8918..a4763b8a 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -16,10 +16,10 @@ */ package com.wazuh.commandmanager.model; -import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.core.xcontent.ToXContentObject; -import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.core.xcontent.XContentParser; +import com.wazuh.commandmanager.index.CommandIndex; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.opensearch.core.xcontent.*; import java.io.IOException; import java.util.ArrayList; @@ -37,6 +37,8 @@ public class Order implements ToXContent { private final Action action; private String document_id; + private static final Logger log = LogManager.getLogger(Order.class); + /** * Default constructor * @@ -60,71 +62,37 @@ public void setDocumentId(String documentId) { this.document_id = documentId; } - /** - * Parses the request's payload into the Command model. - * - * @param parser XContentParser from the Rest Request - * @return instance of Command - * @throws IOException error parsing request content - * @throws IllegalArgumentException missing arguments - */ - public static Order parse(XContentParser parser) throws IOException, IllegalArgumentException { - String source = null; - Target target = null; - String user = null; - Action action = null; - - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - String fieldName = parser.currentName(); - - parser.nextToken(); - switch (fieldName) { - // If we find an Order nested below - // a Command object, parse the Order recursively - // and return its output - case Command.COMMAND: - return Order.parse(parser); - case SOURCE: - source = parser.text(); - break; - case Target.TARGET: - target = Target.parse(parser); - break; - case USER: - user = parser.text(); - break; - case Action.ACTION: - action = Action.parse(parser); - break; - default: + public static Order parse(XContentParser parser) + { + try { + Command command = null; + while (parser.nextToken() != null) { + if (!parser.currentToken().equals(XContentParser.Token.FIELD_NAME)) { + continue; + } + String fieldName = parser.currentName(); + if (fieldName.equals(Command.COMMAND)) { + command = Command.parse(parser); + } else { parser.skipChildren(); - break; + } } + log.debug("Creating new Order Object"); + assert command != null; + return new Order( + command.getSource(), + command.getTarget(), + command.getUser(), + command.getAction() + ); + } catch (Exception e) { + e.printStackTrace(); } - - ArrayList nullArguments = new ArrayList<>(); - if (source == null) { - nullArguments.add("source"); - } - if (target == null) { - nullArguments.add("target"); - } - if (user == null) { - nullArguments.add("user"); - } - if (action == null) { - nullArguments.add("action"); - } - - if (!nullArguments.isEmpty()) { - throw new IllegalArgumentException("Missing arguments: " + nullArguments); - } else { - return new Order(source, target, user, action); - } + return null; } @Override - public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); builder.field(SOURCE, this.source); From fda2db0389b5d0a3823ec18de6c01ef66d5056cc Mon Sep 17 00:00:00 2001 From: f-galland Date: Wed, 18 Dec 2024 17:28:09 -0300 Subject: [PATCH 08/19] Improve exception handling in Order --- .../java/com/wazuh/commandmanager/model/Order.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index a4763b8a..68613e5f 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -66,18 +66,22 @@ public static Order parse(XContentParser parser) { try { Command command = null; + // Iterate over the JsonXContentParser's JsonToken until we hit null, + // which corresponds to end of data while (parser.nextToken() != null) { + // Look for FIELD_NAME JsonToken s if (!parser.currentToken().equals(XContentParser.Token.FIELD_NAME)) { continue; } String fieldName = parser.currentName(); if (fieldName.equals(Command.COMMAND)) { + // Parse Command command = Command.parse(parser); } else { parser.skipChildren(); } } - log.debug("Creating new Order Object"); + // Create a new Order object with the Command's fields assert command != null; return new Order( command.getSource(), @@ -85,8 +89,8 @@ public static Order parse(XContentParser parser) command.getUser(), command.getAction() ); - } catch (Exception e) { - e.printStackTrace(); + } catch (IOException e) { + log.error("Order could not be parsed: {}", e.getMessage()); } return null; } From a78fa8489de040df573f17ba304191ed7371002d Mon Sep 17 00:00:00 2001 From: f-galland Date: Wed, 18 Dec 2024 17:38:39 -0300 Subject: [PATCH 09/19] Create Order from single static method --- .../jobscheduler/SearchThread.java | 13 ++++++------ .../com/wazuh/commandmanager/model/Order.java | 21 ++++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index 0816c83b..dca57608 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -31,12 +31,9 @@ import org.opensearch.common.xcontent.XContentFactory; import org.opensearch.common.xcontent.XContentHelper; import org.opensearch.common.xcontent.XContentType; -import org.opensearch.common.xcontent.json.JsonXContent; import org.opensearch.core.action.ActionListener; -import org.opensearch.core.common.bytes.BytesReference; import org.opensearch.core.rest.RestStatus; import org.opensearch.core.xcontent.*; -import org.opensearch.index.query.QueryBuilder; import org.opensearch.index.query.QueryBuilders; import org.opensearch.index.query.TermQueryBuilder; import org.opensearch.search.SearchHit; @@ -126,7 +123,9 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti // Start an XContentBuilder array named "orders" builder.startObject(); builder.startArray(Order.ORDERS); + // Iterate over search results for (SearchHit hit : searchHits) { + // Create a parser for each SearchHit XContentParser parser = XContentHelper.createParser( NamedXContentRegistry.EMPTY, @@ -134,10 +133,10 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti hit.getSourceRef(), XContentType.JSON ); - Order order = Order.parse(parser); - order.setDocumentId(hit.getId()); - + // Parse the hit's order + Order order = Order.parse(parser,hit.getId()); // Add the current order to the XContentBuilder array + assert order != null; order.toXContent(builder,ToXContent.EMPTY_PARAMS); } // Close the object and prepare it for delivery @@ -145,7 +144,7 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti builder.endObject(); payload = builder.toString(); } catch (IOException e) { - log.error("Error parsing hit contents: {}", e.getMessage()); + log.error("Error building payload from hit: {}", e.getMessage()); } if (payload != null) { diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index 68613e5f..90babc76 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -16,13 +16,11 @@ */ package com.wazuh.commandmanager.model; -import com.wazuh.commandmanager.index.CommandIndex; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.opensearch.core.xcontent.*; import java.io.IOException; -import java.util.ArrayList; import reactor.util.annotation.NonNull; @@ -35,7 +33,7 @@ public class Order implements ToXContent { private final Target target; private final String user; private final Action action; - private String document_id; + private final String documentId; private static final Logger log = LogManager.getLogger(Order.class); @@ -51,18 +49,16 @@ public Order( @NonNull String source, @NonNull Target target, @NonNull String user, - @NonNull Action action) { + @NonNull Action action, + @NonNull String documentId) { this.source = source; this.target = target; this.user = user; this.action = action; + this.documentId = documentId; } - public void setDocumentId(String documentId) { - this.document_id = documentId; - } - - public static Order parse(XContentParser parser) + public static Order parse(XContentParser parser, String documentId) { try { Command command = null; @@ -87,7 +83,8 @@ public static Order parse(XContentParser parser) command.getSource(), command.getTarget(), command.getUser(), - command.getAction() + command.getAction(), + documentId ); } catch (IOException e) { log.error("Order could not be parsed: {}", e.getMessage()); @@ -103,7 +100,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) builder.field(USER, this.user); this.target.toXContent(builder, ToXContent.EMPTY_PARAMS); this.action.toXContent(builder, ToXContent.EMPTY_PARAMS); - builder.field(DOCUMENT_ID, this.document_id); + builder.field(DOCUMENT_ID, this.documentId); return builder.endObject(); } @@ -122,7 +119,7 @@ public String toString() { + user + '\'' + ", document_id='" - + document_id + + documentId + '\'' + '}'; } From a629b0c6709736d3349cb1dc52d2686da878231e Mon Sep 17 00:00:00 2001 From: f-galland Date: Wed, 18 Dec 2024 17:50:31 -0300 Subject: [PATCH 10/19] Add JavaDocs --- .../com/wazuh/commandmanager/model/Order.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index 90babc76..2138731e 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -39,11 +39,11 @@ public class Order implements ToXContent { /** * Default constructor - * - * @param source origin of the request. - * @param target {@link Target} - * @param user the user that originated the request - * @param action {@link Action} + * @param source String field representing the origin of the command order + * @param target Object containing the destination's type and id. It is handled by its own model class + * @param user The requester of the command + * @param action An object containing the actual executable plus arguments and version. Handled by its own model class + * @param documentId The document ID from the index that holds commands. Used by the agent to report back the results of the action */ public Order( @NonNull String source, @@ -58,6 +58,12 @@ public Order( this.documentId = documentId; } + /** + * Parses a SearchHit into an order as expected by a Wazuh Agent + * @param parser XContentParser with the "_source" field's contents + * @param documentId The document ID from the index that holds commands. Used by the agent to report back the results of the action + * @return An Order object in accordance to the data model + */ public static Order parse(XContentParser parser, String documentId) { try { @@ -92,6 +98,13 @@ public static Order parse(XContentParser parser, String documentId) return null; } + /** + * Used to serialize the Order's contents. + * @param builder The builder object we will add our Json to + * @param params Not used. Required by the interface. + * @return XContentBuilder with a Json object including this Order's fields + * @throws IOException Rethrown from IOException's XContentBuilder methods + */ @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { From 69b7f9120dbeb418cd8c5725ce214c5ae8a823f9 Mon Sep 17 00:00:00 2001 From: f-galland Date: Wed, 18 Dec 2024 17:55:16 -0300 Subject: [PATCH 11/19] Refactor Order.parse() into Order.parseSearchHit() --- .../jobscheduler/SearchThread.java | 2 +- .../com/wazuh/commandmanager/model/Order.java | 20 ++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index dca57608..d19ed35d 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -134,7 +134,7 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti XContentType.JSON ); // Parse the hit's order - Order order = Order.parse(parser,hit.getId()); + Order order = Order.parseSearchHit(hit); // Add the current order to the XContentBuilder array assert order != null; order.toXContent(builder,ToXContent.EMPTY_PARAMS); diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index 2138731e..d1cdadf7 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -18,10 +18,13 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.opensearch.common.xcontent.XContentHelper; +import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.xcontent.*; import java.io.IOException; +import org.opensearch.search.SearchHit; import reactor.util.annotation.NonNull; public class Order implements ToXContent { @@ -58,15 +61,22 @@ public Order( this.documentId = documentId; } + /** * Parses a SearchHit into an order as expected by a Wazuh Agent - * @param parser XContentParser with the "_source" field's contents - * @param documentId The document ID from the index that holds commands. Used by the agent to report back the results of the action - * @return An Order object in accordance to the data model + * @param hit The SearchHit result of a search + * @return An Order Object in accordance with the data model */ - public static Order parse(XContentParser parser, String documentId) + public static Order parseSearchHit(SearchHit hit) { try { + XContentParser parser = + XContentHelper.createParser( + NamedXContentRegistry.EMPTY, + DeprecationHandler.IGNORE_DEPRECATIONS, + hit.getSourceRef(), + XContentType.JSON + ); Command command = null; // Iterate over the JsonXContentParser's JsonToken until we hit null, // which corresponds to end of data @@ -90,7 +100,7 @@ public static Order parse(XContentParser parser, String documentId) command.getTarget(), command.getUser(), command.getAction(), - documentId + hit.getId() ); } catch (IOException e) { log.error("Order could not be parsed: {}", e.getMessage()); From 2072760b56c6177341364af4efb83eef17f36c44 Mon Sep 17 00:00:00 2001 From: f-galland Date: Thu, 19 Dec 2024 08:03:08 -0300 Subject: [PATCH 12/19] Fix bad merge --- .../com/wazuh/commandmanager/jobscheduler/SearchThread.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index 621c7e22..3dbc549c 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -163,9 +163,6 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti for (SearchHit hit : searchHits) { this.setSentStatus(hit, status); } - } catch (IOException e) { - log.error("Error parsing hit contents: {}", e.getMessage()); - } } /** From 299afe30bb9ff1a3e58877d11f5900210a2efa7c Mon Sep 17 00:00:00 2001 From: f-galland Date: Thu, 19 Dec 2024 08:30:06 -0300 Subject: [PATCH 13/19] Apply spotless --- .../jobscheduler/SearchThread.java | 33 +++++++------- .../com/wazuh/commandmanager/model/Order.java | 45 ++++++++++--------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index 3dbc549c..2bddfea9 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -134,13 +134,12 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti NamedXContentRegistry.EMPTY, DeprecationHandler.IGNORE_DEPRECATIONS, hit.getSourceRef(), - XContentType.JSON - ); + XContentType.JSON); // Parse the hit's order Order order = Order.parseSearchHit(hit); // Add the current order to the XContentBuilder array assert order != null; - order.toXContent(builder,ToXContent.EMPTY_PARAMS); + order.toXContent(builder, ToXContent.EMPTY_PARAMS); } // Close the object and prepare it for delivery builder.endArray(); @@ -149,20 +148,20 @@ public void handlePage(SearchResponse searchResponse) throws IllegalStateExcepti } catch (IOException e) { log.error("Error building payload from hit: {}", e.getMessage()); } - final SimpleHttpResponse response = deliverOrders(payload); - if (response == null) { - log.error("No reply from server."); - return; - } - log.info("Server replied with {}. Updating orders' status.", response.getCode()); - Status status = Status.FAILURE; - if (List.of(RestStatus.CREATED, RestStatus.ACCEPTED, RestStatus.OK) - .contains(RestStatus.fromCode(response.getCode()))) { - status = Status.SENT; - } - for (SearchHit hit : searchHits) { - this.setSentStatus(hit, status); - } + final SimpleHttpResponse response = deliverOrders(payload); + if (response == null) { + log.error("No reply from server."); + return; + } + log.info("Server replied with {}. Updating orders' status.", response.getCode()); + Status status = Status.FAILURE; + if (List.of(RestStatus.CREATED, RestStatus.ACCEPTED, RestStatus.OK) + .contains(RestStatus.fromCode(response.getCode()))) { + status = Status.SENT; + } + for (SearchHit hit : searchHits) { + this.setSentStatus(hit, status); + } } /** diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index d1cdadf7..161a860d 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -21,10 +21,10 @@ import org.opensearch.common.xcontent.XContentHelper; import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.xcontent.*; +import org.opensearch.search.SearchHit; import java.io.IOException; -import org.opensearch.search.SearchHit; import reactor.util.annotation.NonNull; public class Order implements ToXContent { @@ -42,11 +42,15 @@ public class Order implements ToXContent { /** * Default constructor + * * @param source String field representing the origin of the command order - * @param target Object containing the destination's type and id. It is handled by its own model class + * @param target Object containing the destination's type and id. It is handled by its own model + * class * @param user The requester of the command - * @param action An object containing the actual executable plus arguments and version. Handled by its own model class - * @param documentId The document ID from the index that holds commands. Used by the agent to report back the results of the action + * @param action An object containing the actual executable plus arguments and version. Handled + * by its own model class + * @param documentId The document ID from the index that holds commands. Used by the agent to + * report back the results of the action */ public Order( @NonNull String source, @@ -61,29 +65,27 @@ public Order( this.documentId = documentId; } - /** * Parses a SearchHit into an order as expected by a Wazuh Agent + * * @param hit The SearchHit result of a search * @return An Order Object in accordance with the data model */ - public static Order parseSearchHit(SearchHit hit) - { + public static Order parseSearchHit(SearchHit hit) { try { XContentParser parser = - XContentHelper.createParser( - NamedXContentRegistry.EMPTY, - DeprecationHandler.IGNORE_DEPRECATIONS, - hit.getSourceRef(), - XContentType.JSON - ); + XContentHelper.createParser( + NamedXContentRegistry.EMPTY, + DeprecationHandler.IGNORE_DEPRECATIONS, + hit.getSourceRef(), + XContentType.JSON); Command command = null; // Iterate over the JsonXContentParser's JsonToken until we hit null, // which corresponds to end of data while (parser.nextToken() != null) { // Look for FIELD_NAME JsonToken s if (!parser.currentToken().equals(XContentParser.Token.FIELD_NAME)) { - continue; + continue; } String fieldName = parser.currentName(); if (fieldName.equals(Command.COMMAND)) { @@ -96,12 +98,11 @@ public static Order parseSearchHit(SearchHit hit) // Create a new Order object with the Command's fields assert command != null; return new Order( - command.getSource(), - command.getTarget(), - command.getUser(), - command.getAction(), - hit.getId() - ); + command.getSource(), + command.getTarget(), + command.getUser(), + command.getAction(), + hit.getId()); } catch (IOException e) { log.error("Order could not be parsed: {}", e.getMessage()); } @@ -110,14 +111,14 @@ public static Order parseSearchHit(SearchHit hit) /** * Used to serialize the Order's contents. + * * @param builder The builder object we will add our Json to * @param params Not used. Required by the interface. * @return XContentBuilder with a Json object including this Order's fields * @throws IOException Rethrown from IOException's XContentBuilder methods */ @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) - throws IOException { + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); builder.field(SOURCE, this.source); builder.field(USER, this.user); From dbbdaf3a8438e4221ea6769511230b156070fe15 Mon Sep 17 00:00:00 2001 From: f-galland Date: Thu, 19 Dec 2024 10:31:34 -0300 Subject: [PATCH 14/19] Remove printStackTrace deprecated call --- .../java/com/wazuh/commandmanager/jobscheduler/SearchThread.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index 2bddfea9..462b5f3f 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -277,7 +277,6 @@ public void run() { log.error("IllegalStateException retrieving page: {}", e.getMessage()); } catch (Exception e) { log.error("Generic exception retrieving page: {}", e.getMessage()); - e.printStackTrace(); } } From a2f965e6f6a543092609935d3ee6b2e19241eed5 Mon Sep 17 00:00:00 2001 From: f-galland Date: Thu, 19 Dec 2024 13:49:32 -0300 Subject: [PATCH 15/19] Clean up and refactor orders code --- .../jobscheduler/SearchThread.java | 37 +----------- .../wazuh/commandmanager/model/Command.java | 57 +++++++++--------- .../com/wazuh/commandmanager/model/Order.java | 33 ++++++----- .../wazuh/commandmanager/model/Orders.java | 58 +++++++++++++++++++ 4 files changed, 106 insertions(+), 79 deletions(-) create mode 100644 plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Orders.java diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index 462b5f3f..d9a773d4 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -28,9 +28,6 @@ import org.opensearch.client.Client; import org.opensearch.common.action.ActionFuture; import org.opensearch.common.unit.TimeValue; -import org.opensearch.common.xcontent.XContentFactory; -import org.opensearch.common.xcontent.XContentHelper; -import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.action.ActionListener; import org.opensearch.core.rest.RestStatus; import org.opensearch.core.xcontent.*; @@ -42,7 +39,6 @@ import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.search.sort.SortOrder; -import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.security.AccessController; @@ -53,10 +49,7 @@ import java.util.concurrent.ExecutionException; import com.wazuh.commandmanager.CommandManagerPlugin; -import com.wazuh.commandmanager.model.Command; -import com.wazuh.commandmanager.model.Document; -import com.wazuh.commandmanager.model.Order; -import com.wazuh.commandmanager.model.Status; +import com.wazuh.commandmanager.model.*; import com.wazuh.commandmanager.settings.PluginSettings; import com.wazuh.commandmanager.utils.httpclient.AuthHttpRestClient; @@ -121,33 +114,7 @@ public static T getNestedObject(Map map, String key, Class. + */ +package com.wazuh.commandmanager.model; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.opensearch.common.xcontent.XContentFactory; +import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.search.SearchHit; +import org.opensearch.search.SearchHits; + +import java.io.IOException; +import java.util.Objects; + +public class Orders { + + private static final Logger log = LogManager.getLogger(Orders.class); + + public static String getOrders(SearchHits searchHits) { + try (XContentBuilder builder = XContentFactory.jsonBuilder()) { + // Start an XContentBuilder array named "orders" + builder.startObject(); + builder.startArray(Order.ORDERS); + // Iterate over search results + for (SearchHit hit : searchHits) { + // Parse the hit's order + Order order = Order.parseSearchHit(hit); + // Add the current order to the XContentBuilder array + Objects.requireNonNull(order).toXContent(builder, ToXContent.EMPTY_PARAMS); + } + // Close the object and prepare it for delivery + builder.endArray(); + builder.endObject(); + return builder.toString(); + } catch (IOException e) { + log.error("Error building payload from hit: {}", e.getMessage()); + } catch (NullPointerException e) { + log.error( + "Exception found when building order payload. Null Order: {}", e.getMessage()); + } + return null; + } +} From 1a2ac3cef396d75c9de04170d4b50e4d9fbea7b1 Mon Sep 17 00:00:00 2001 From: f-galland Date: Thu, 19 Dec 2024 13:54:54 -0300 Subject: [PATCH 16/19] Add javadocs --- .../main/java/com/wazuh/commandmanager/model/Orders.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Orders.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Orders.java index a2b6b5d5..4e8b8196 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Orders.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Orders.java @@ -27,10 +27,18 @@ import java.io.IOException; import java.util.Objects; +/** Helper class for managing command orders */ public class Orders { private static final Logger log = LogManager.getLogger(Orders.class); + /** + * Helper static method that takes the search results in SearchHits form and parses them into + * Order objects. It then puts together a json string meant for sending over HTTP + * + * @param searchHits the commands search result + * @return A json string payload with an array of orders to be processed + */ public static String getOrders(SearchHits searchHits) { try (XContentBuilder builder = XContentFactory.jsonBuilder()) { // Start an XContentBuilder array named "orders" From 82bb2b80790923402f1cf074bf3cc305f60cd2d1 Mon Sep 17 00:00:00 2001 From: Alex Ruiz Date: Fri, 20 Dec 2024 14:20:44 +0100 Subject: [PATCH 17/19] Refactor Orders model class --- imposter/orders/response.js | 7 ++ imposter/wazuh-server-config.yaml | 5 +- .../jobscheduler/SearchThread.java | 18 +++-- .../wazuh/commandmanager/model/Command.java | 20 ++++++ .../com/wazuh/commandmanager/model/Order.java | 3 +- .../wazuh/commandmanager/model/Orders.java | 70 +++++++++++-------- 6 files changed, 87 insertions(+), 36 deletions(-) create mode 100644 imposter/orders/response.js diff --git a/imposter/orders/response.js b/imposter/orders/response.js new file mode 100644 index 00000000..aee600cb --- /dev/null +++ b/imposter/orders/response.js @@ -0,0 +1,7 @@ +console.log( + JSON.stringify( + JSON.parse(context.request.body), + undefined, + 2 + ) + ) \ No newline at end of file diff --git a/imposter/wazuh-server-config.yaml b/imposter/wazuh-server-config.yaml index 6f2c9cc8..0df80ae5 100644 --- a/imposter/wazuh-server-config.yaml +++ b/imposter/wazuh-server-config.yaml @@ -49,4 +49,7 @@ resources: # Orders - method: POST - path: /orders \ No newline at end of file + path: /orders + response: + scriptFile: + orders/response.js \ No newline at end of file diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java index d9a773d4..8c1b1bf8 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/jobscheduler/SearchThread.java @@ -28,9 +28,10 @@ import org.opensearch.client.Client; import org.opensearch.common.action.ActionFuture; import org.opensearch.common.unit.TimeValue; +import org.opensearch.common.xcontent.XContentFactory; import org.opensearch.core.action.ActionListener; import org.opensearch.core.rest.RestStatus; -import org.opensearch.core.xcontent.*; +import org.opensearch.core.xcontent.ToXContent; import org.opensearch.index.query.QueryBuilders; import org.opensearch.index.query.TermQueryBuilder; import org.opensearch.search.SearchHit; @@ -39,6 +40,7 @@ import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.search.sort.SortOrder; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.security.AccessController; @@ -111,11 +113,19 @@ public static T getNestedObject(Map map, String key, Class orders; + + /** Default constructor. */ + public Orders() { + this.orders = new ArrayList<>(); + } /** * Helper static method that takes the search results in SearchHits form and parses them into @@ -39,28 +42,37 @@ public class Orders { * @param searchHits the commands search result * @return A json string payload with an array of orders to be processed */ - public static String getOrders(SearchHits searchHits) { - try (XContentBuilder builder = XContentFactory.jsonBuilder()) { - // Start an XContentBuilder array named "orders" - builder.startObject(); - builder.startArray(Order.ORDERS); - // Iterate over search results - for (SearchHit hit : searchHits) { - // Parse the hit's order - Order order = Order.parseSearchHit(hit); - // Add the current order to the XContentBuilder array - Objects.requireNonNull(order).toXContent(builder, ToXContent.EMPTY_PARAMS); - } - // Close the object and prepare it for delivery - builder.endArray(); - builder.endObject(); - return builder.toString(); - } catch (IOException e) { - log.error("Error building payload from hit: {}", e.getMessage()); - } catch (NullPointerException e) { - log.error( - "Exception found when building order payload. Null Order: {}", e.getMessage()); + public static Orders fromSearchHits(SearchHits searchHits) { + Orders orders = new Orders(); + + // Iterate over search results + for (SearchHit hit : searchHits) { + // Parse the hit's order + Order order = Order.fromSearchHit(hit); + orders.add(order); + } + + return orders; + } + + /** + * Adds an order to the orders array. + * + * @param order order to add. + */ + private void add(Order order) { + this.orders.add(order); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + // Start an XContentBuilder array named "orders" + builder.startObject(); + builder.startArray(ORDERS); + for (Order order : this.orders) { + order.toXContent(builder, params); } - return null; + builder.endArray(); + return builder.endObject(); } } From 1e467eca37d57ede929dc2c52a5ee4c3b1dbfb49 Mon Sep 17 00:00:00 2001 From: Alex Ruiz Date: Fri, 20 Dec 2024 14:21:32 +0100 Subject: [PATCH 18/19] Add JavaDocs to Order model class --- .../src/main/java/com/wazuh/commandmanager/model/Order.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java index bdebe5b7..f8d9b144 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Order.java @@ -28,6 +28,7 @@ import reactor.util.annotation.NonNull; +/** Order model class. */ public class Order implements ToXContent { public static final String SOURCE = "source"; public static final String USER = "user"; From a3f460a047c414750ccd68195bb0f74d89650a3b Mon Sep 17 00:00:00 2001 From: Alex Ruiz Date: Fri, 20 Dec 2024 14:27:24 +0100 Subject: [PATCH 19/19] Update Orders JavaDocs --- .../main/java/com/wazuh/commandmanager/model/Orders.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Orders.java b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Orders.java index 0d8aec9b..78010bf3 100644 --- a/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Orders.java +++ b/plugins/command-manager/src/main/java/com/wazuh/commandmanager/model/Orders.java @@ -42,6 +42,12 @@ public Orders() { * @param searchHits the commands search result * @return A json string payload with an array of orders to be processed */ + /** + * Static builder method that initializes an instance of Orders from a SearchHits instance. + * + * @param searchHits search hits as returned from the search index query to the commands index. + * @return instance of Orders. + */ public static Orders fromSearchHits(SearchHits searchHits) { Orders orders = new Orders();