Projects STRLCPY LoggerPlusPlus Commits c35cdfe4
🤬
  • Update Elastic exporter to ElasticSearch 8.7

  • Loading...
  • Corey committed 11 months ago
    c35cdfe4
    1 parent b624552e
  • ■ ■ ■ ■ ■
    build.gradle
    skipped 16 lines
    17 17   implementation 'net.portswigger.burp.extensions:montoya-api:2023.3'
    18 18   implementation 'org.swinglabs:swingx:1.6.1'
    19 19   implementation 'com.github.CoreyD97:Burp-Montoya-Utilities:07e3e02b'
    20  - implementation 'org.elasticsearch.client:elasticsearch-rest-high-level-client:7.15.2'
     20 +// implementation 'org.elasticsearch.client:elasticsearch-rest-high-level-client:7.17.9'
     21 + implementation 'co.elastic.clients:elasticsearch-java:8.6.2'
    21 22   implementation 'org.apache.httpcomponents:httpclient:4.5.13'
    22 23   implementation 'org.apache.commons:commons-text:1.10.0'
    23 24   implementation 'org.apache.logging.log4j:log4j-core:2.19.0'
    skipped 21 lines
  • ■ ■ ■ ■ ■ ■
    src/main/java/com/nccgroup/loggerplusplus/exports/ElasticExporter.java
    1 1  package com.nccgroup.loggerplusplus.exports;
    2 2   
     3 +import co.elastic.clients.elasticsearch.ElasticsearchClient;
     4 +import co.elastic.clients.elasticsearch.core.BulkRequest;
     5 +import co.elastic.clients.elasticsearch.core.BulkResponse;
     6 +import co.elastic.clients.elasticsearch.core.IndexRequest;
     7 +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
     8 +import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
     9 +import co.elastic.clients.elasticsearch.indices.ExistsRequest;
     10 +import co.elastic.clients.elasticsearch.indices.GetIndexRequest;
     11 +import co.elastic.clients.json.JsonData;
     12 +import co.elastic.clients.json.jackson.JacksonJsonpGenerator;
     13 +import co.elastic.clients.json.jackson.JacksonJsonpMapper;
     14 +import co.elastic.clients.transport.ElasticsearchTransport;
     15 +import co.elastic.clients.transport.endpoints.BooleanResponse;
     16 +import co.elastic.clients.transport.rest_client.RestClientTransport;
    3 17  import com.coreyd97.BurpExtenderUtilities.Preferences;
     18 +import com.google.gson.Gson;
     19 +import com.google.gson.JsonObject;
    4 20  import com.nccgroup.loggerplusplus.LoggerPlusPlus;
    5 21  import com.nccgroup.loggerplusplus.filter.logfilter.LogTableFilter;
    6 22  import com.nccgroup.loggerplusplus.filter.parser.ParseException;
    skipped 8 lines
    15 31  import org.apache.http.message.BasicHeader;
    16 32  import org.apache.logging.log4j.LogManager;
    17 33  import org.apache.logging.log4j.Logger;
    18  -import org.elasticsearch.action.bulk.BulkItemResponse;
    19  -import org.elasticsearch.action.bulk.BulkRequest;
    20  -import org.elasticsearch.action.bulk.BulkResponse;
    21  -import org.elasticsearch.action.index.IndexRequest;
    22  -import org.elasticsearch.client.RequestOptions;
    23 34  import org.elasticsearch.client.RestClient;
    24 35  import org.elasticsearch.client.RestClientBuilder;
    25  -import org.elasticsearch.client.RestHighLevelClient;
    26  -import org.elasticsearch.client.indices.CreateIndexRequest;
    27  -import org.elasticsearch.client.indices.GetIndexRequest;
    28  -import org.elasticsearch.common.xcontent.XContentBuilder;
    29  -import org.elasticsearch.common.xcontent.XContentElasticsearchExtension;
     36 + 
    30 37   
    31 38  import javax.swing.*;
    32 39  import java.io.IOException;
    skipped 6 lines
    39 46  import java.util.concurrent.ScheduledFuture;
    40 47  import java.util.concurrent.TimeUnit;
    41 48   
    42  -import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
    43  - 
    44 49  @Log4j2
    45 50  public class ElasticExporter extends AutomaticLogExporter implements ExportPanelProvider, ContextMenuExportProvider {
    46 51   
    47  - RestHighLevelClient httpClient;
     52 + ElasticsearchClient elasticClient;
    48 53   ArrayList<LogEntry> pendingEntries;
    49 54   LogTableFilter logFilter;
    50 55   private List<LogEntryField> fields;
    skipped 3 lines
    54 59   
    55 60   private final ScheduledExecutorService executorService;
    56 61   private final ElasticExporterControlPanel controlPanel;
     62 + private final Gson gson;
    57 63   
    58 64   private Logger logger = LogManager.getLogger(this);
    59 65   
    60 66   protected ElasticExporter(ExportController exportController, Preferences preferences) {
    61 67   super(exportController, preferences);
    62 68   this.fields = new ArrayList<>(preferences.getSetting(Globals.PREF_PREVIOUS_ELASTIC_FIELDS));
     69 + this.gson = LoggerPlusPlus.gsonProvider.getGson();
    63 70   executorService = Executors.newScheduledThreadPool(1);
    64 71   
    65 72   if ((boolean) preferences.getSetting(Globals.PREF_ELASTIC_AUTOSTART_GLOBAL)
    skipped 41 lines
    107 114   int port = preferences.getSetting(Globals.PREF_ELASTIC_PORT);
    108 115   indexName = preferences.getSetting(Globals.PREF_ELASTIC_INDEX);
    109 116   String protocol = preferences.getSetting(Globals.PREF_ELASTIC_PROTOCOL).toString();
    110  - RestClientBuilder builder = RestClient.builder(new HttpHost(address, port, protocol));
     117 + RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(address, port, protocol));
    111 118   logger.info(String.format("Starting ElasticSearch exporter. %s://%s:%s/%s", protocol, address, port, indexName));
    112 119   
    113 120   Globals.ElasticAuthType authType = preferences.getSetting(Globals.PREF_ELASTIC_AUTH);
    skipped 15 lines
    129 136   if (!"".equals(user) && !"".equalsIgnoreCase(pass)) {
    130 137   logger.info(String.format("ElasticSearch using %s, Username: %s", authType, user));
    131 138   String authValue = Base64.getEncoder().encodeToString((user + ":" + pass).getBytes(StandardCharsets.UTF_8));
    132  - builder.setDefaultHeaders(new Header[]{new BasicHeader("Authorization", String.format("%s %s", authType, authValue))});
     139 + restClientBuilder.setDefaultHeaders(new Header[]{new BasicHeader("Authorization", String.format("%s %s", authType, authValue))});
    133 140   }
    134 141   
    135  - httpClient = new RestHighLevelClient(builder);
     142 + 
     143 + ElasticsearchTransport transport = new RestClientTransport(restClientBuilder.build(), new JacksonJsonpMapper());
     144 + 
     145 + elasticClient = new ElasticsearchClient(transport);
    136 146   
    137 147   createIndices();
    138 148   pendingEntries = new ArrayList<>();
    skipped 36 lines
    175 185   }
    176 186   
    177 187   private void createIndices() throws IOException {
    178  - GetIndexRequest request = new GetIndexRequest(this.indexName);
     188 + ExistsRequest existsRequest = new ExistsRequest.Builder().index(this.indexName).build();
    179 189   
    180  - boolean exists = httpClient.indices().exists(request, RequestOptions.DEFAULT);
     190 + BooleanResponse exists = elasticClient.indices().exists(existsRequest);
    181 191   
    182  - if(!exists) {
    183  - CreateIndexRequest _request = new CreateIndexRequest(this.indexName);
    184  - httpClient.indices().create(_request, RequestOptions.DEFAULT);
     192 + if(!exists.value()) {
     193 + CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder().index(this.indexName).build();
     194 + elasticClient.indices().create(createIndexRequest);
    185 195   }
    186 196   }
    187 197   
    188  - public IndexRequest buildIndexRequest(LogEntry logEntry) throws IOException {
    189  - XContentBuilder builder = jsonBuilder().startObject();
     198 + public JsonObject serializeLogEntry(LogEntry logEntry) {
     199 + //Todo Better serialization of entries
     200 + JsonObject jsonObject = new JsonObject();
    190 201   for (LogEntryField field : this.fields) {
    191 202   Object value = formatValue(logEntry.getValueByKey(field));
    192 203   try {
    193  - //For some reason, the XContentElasticsearchExtension service cannot be loaded
    194  - //when in burp, so we must format dates manually ourselves :(
    195  - //TODO investigate further
    196  - if (value instanceof Date) {
    197  - builder.field(field.getFullLabel(), XContentElasticsearchExtension.DEFAULT_DATE_PRINTER.print(((Date) value).getTime()));
    198  - } else {
    199  - builder.field(field.getFullLabel(), value);
    200  - }
     204 + jsonObject.addProperty(field.getFullLabel(), gson.toJson(value));
    201 205   }catch (Exception e){
    202 206   log.error("ElasticExporter: " + value);
    203 207   log.error("ElasticExporter: " + e.getMessage());
    204 208   throw e;
    205 209   }
    206 210   }
    207  - builder.endObject();
    208  - 
    209  - return new IndexRequest(this.indexName, "doc").source(builder); //TODO Remove deprecated ES6 methods.
     211 + return jsonObject;
    210 212   }
    211 213   
    212 214   private void indexPendingEntries(){
    213 215   try {
    214 216   if (this.pendingEntries.size() == 0) return;
    215 217   
    216  - BulkRequest httpBulkBuilder = new BulkRequest();
     218 + BulkRequest.Builder bulkBuilder = new BulkRequest.Builder();
    217 219   
    218 220   ArrayList<LogEntry> entriesInBulk;
    219 221   synchronized (pendingEntries) {
    skipped 3 lines
    223 225   
    224 226   for (LogEntry logEntry : entriesInBulk) {
    225 227   try {
    226  - IndexRequest request = buildIndexRequest(logEntry);
    227  - httpBulkBuilder.add(request);
     228 + bulkBuilder.operations(op -> op
     229 + .index(idx -> idx
     230 + .index(this.indexName)
     231 + .document(serializeLogEntry(logEntry))
     232 + )
     233 + );
     234 + 
    228 235   } catch (Exception e) {
    229 236   log.error("Could not build elastic export request for entry: " + e.getMessage());
    230 237   //Could not build index request. Ignore it?
    skipped 1 lines
    232 239   }
    233 240   
    234 241   try {
    235  - BulkResponse bulkResponse = httpClient.bulk(httpBulkBuilder, RequestOptions.DEFAULT);
    236  - if (bulkResponse.hasFailures()) {
    237  - for (BulkItemResponse bulkItemResponse : bulkResponse.getItems()) {
    238  - log.error(bulkItemResponse.getFailureMessage());
     242 + BulkResponse bulkResponse = elasticClient.bulk(bulkBuilder.build());
     243 + if (bulkResponse.errors()) {
     244 + for (BulkResponseItem bulkResponseItem : bulkResponse.items()) {
     245 + log.error(bulkResponseItem.error().reason());
    239 246   }
    240 247   }
    241 248   connectFailedCounter = 0;
    skipped 35 lines
Please wait...
Page is in error, reload to recover