3
3
import co .elastic .clients .elasticsearch .ElasticsearchClient ;
4
4
import co .elastic .clients .elasticsearch .core .BulkRequest ;
5
5
import co .elastic .clients .elasticsearch .core .BulkResponse ;
6
- import co .elastic .clients .elasticsearch .core .IndexRequest ;
7
6
import co .elastic .clients .elasticsearch .core .bulk .BulkResponseItem ;
8
7
import co .elastic .clients .elasticsearch .indices .CreateIndexRequest ;
9
8
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
9
import co .elastic .clients .json .jackson .JacksonJsonpMapper ;
14
10
import co .elastic .clients .transport .ElasticsearchTransport ;
15
11
import co .elastic .clients .transport .endpoints .BooleanResponse ;
16
12
import co .elastic .clients .transport .rest_client .RestClientTransport ;
17
13
import com .coreyd97 .BurpExtenderUtilities .Preferences ;
18
- import com .google .gson .Gson ;
19
- import com .google .gson .JsonObject ;
14
+ import com .fasterxml .jackson .core .JsonGenerator ;
15
+ import com .fasterxml .jackson .core .Version ;
16
+ import com .fasterxml .jackson .databind .ObjectMapper ;
17
+ import com .fasterxml .jackson .databind .SerializerProvider ;
18
+ import com .fasterxml .jackson .databind .module .SimpleModule ;
19
+ import com .fasterxml .jackson .databind .ser .std .StdSerializer ;
20
20
import com .nccgroup .loggerplusplus .LoggerPlusPlus ;
21
21
import com .nccgroup .loggerplusplus .filter .logfilter .LogTableFilter ;
22
22
import com .nccgroup .loggerplusplus .filter .parser .ParseException ;
@@ -59,16 +59,20 @@ public class ElasticExporter extends AutomaticLogExporter implements ExportPanel
59
59
60
60
private final ScheduledExecutorService executorService ;
61
61
private final ElasticExporterControlPanel controlPanel ;
62
- private final Gson gson ;
62
+ private final ObjectMapper mapper ;
63
63
64
64
private Logger logger = LogManager .getLogger (this );
65
65
66
66
protected ElasticExporter (ExportController exportController , Preferences preferences ) {
67
67
super (exportController , preferences );
68
68
this .fields = new ArrayList <>(preferences .getSetting (Globals .PREF_PREVIOUS_ELASTIC_FIELDS ));
69
- this .gson = LoggerPlusPlus .gsonProvider .getGson ();
70
69
executorService = Executors .newScheduledThreadPool (1 );
71
70
71
+ this .mapper = new ObjectMapper ();
72
+ SimpleModule module = new SimpleModule ("LogEntry Serializer" , new Version (0 ,1 ,0 ,"" ,null , null ));
73
+ module .addSerializer (LogEntry .class , new ElasticExporter .EntrySerializer (LogEntry .class ));
74
+ mapper .registerModule (module );
75
+
72
76
if ((boolean ) preferences .getSetting (Globals .PREF_ELASTIC_AUTOSTART_GLOBAL )
73
77
|| (boolean ) preferences .getSetting (Globals .PREF_ELASTIC_AUTOSTART_PROJECT )) {
74
78
//Autostart exporter.
@@ -91,22 +95,23 @@ void setup() throws Exception {
91
95
String projectPreviousFilterString = preferences .getSetting (Globals .PREF_ELASTIC_FILTER_PROJECT_PREVIOUS );
92
96
String filterString = preferences .getSetting (Globals .PREF_ELASTIC_FILTER );
93
97
94
- if (!Objects .equals (projectPreviousFilterString , filterString )) {
95
- //The current filter isn't what we used to export last time.
96
- int res = JOptionPane .showConfirmDialog (LoggerPlusPlus .instance .getLoggerFrame (),
97
- "Heads up! Looks like the filter being used to select which logs to export to " +
98
- "ElasticSearch has changed since you last ran the exporter for this project.\n " +
99
- "Do you want to continue?" , "ElasticSearch Export Log Filter" , JOptionPane .YES_NO_OPTION , JOptionPane .WARNING_MESSAGE );
100
- if (res == JOptionPane .NO_OPTION ) {
101
- throw new Exception ("Export cancelled." );
102
- }
103
- }
98
+ // if (!Objects.equals(projectPreviousFilterString, filterString)) {
99
+ // //The current filter isn't what we used to export last time.
100
+ // int res = JOptionPane.showConfirmDialog(LoggerPlusPlus.instance.getLoggerFrame(),
101
+ // "Heads up! Looks like the filter being used to select which logs to export to " +
102
+ // "ElasticSearch has changed since you last ran the exporter for this project.\n" +
103
+ // "Do you want to continue?", "ElasticSearch Export Log Filter", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
104
+ // if (res == JOptionPane.NO_OPTION) {
105
+ // throw new Exception("Export cancelled.");
106
+ // }
107
+ // }
104
108
105
109
if (!StringUtils .isBlank (filterString )) {
106
110
try {
107
111
logFilter = new LogTableFilter (filterString );
108
112
} catch (ParseException ex ) {
109
113
logger .error ("The log filter configured for the Elastic exporter is invalid!" , ex );
114
+ throw new Exception ("The log filter configured for the Elastic exporter is invalid!" , ex );
110
115
}
111
116
}
112
117
@@ -140,7 +145,7 @@ void setup() throws Exception {
140
145
}
141
146
142
147
143
- ElasticsearchTransport transport = new RestClientTransport (restClientBuilder .build (), new JacksonJsonpMapper ());
148
+ ElasticsearchTransport transport = new RestClientTransport (restClientBuilder .build (), new JacksonJsonpMapper (this . mapper ));
144
149
145
150
elasticClient = new ElasticsearchClient (transport );
146
151
@@ -195,21 +200,21 @@ private void createIndices() throws IOException {
195
200
}
196
201
}
197
202
198
- public JsonObject serializeLogEntry (LogEntry logEntry ) {
199
- //Todo Better serialization of entries
200
- JsonObject jsonObject = new JsonObject ();
201
- for (LogEntryField field : this .fields ) {
202
- Object value = formatValue (logEntry .getValueByKey (field ));
203
- try {
204
- jsonObject .addProperty (field .getFullLabel (), gson .toJson (value ));
205
- }catch (Exception e ){
206
- log .error ("ElasticExporter: " + value );
207
- log .error ("ElasticExporter: " + e .getMessage ());
208
- throw e ;
209
- }
210
- }
211
- return jsonObject ;
212
- }
203
+ // public JsonObject serializeLogEntry(LogEntry logEntry) {
204
+ // //Todo Better serialization of entries
205
+ // JsonObject jsonObject = new JsonObject();
206
+ // for (LogEntryField field : this.fields) {
207
+ // Object value = formatValue(logEntry.getValueByKey(field));
208
+ // try {
209
+ // jsonObject.addProperty(field.getFullLabel(), gson.toJson(value));
210
+ // }catch (Exception e){
211
+ // log.error("ElasticExporter: " + value);
212
+ // log.error("ElasticExporter: " + e.getMessage());
213
+ // throw e;
214
+ // }
215
+ // }
216
+ // return jsonObject;
217
+ // }
213
218
214
219
private void indexPendingEntries (){
215
220
try {
@@ -228,7 +233,7 @@ private void indexPendingEntries(){
228
233
bulkBuilder .operations (op -> op
229
234
.index (idx -> idx
230
235
.index (this .indexName )
231
- .document (serializeLogEntry ( logEntry ) )
236
+ .document (logEntry )
232
237
)
233
238
);
234
239
@@ -255,18 +260,13 @@ private void indexPendingEntries(){
255
260
shutdown ();
256
261
}
257
262
}catch (IOException e ) {
258
- e . printStackTrace ( );
263
+ log . error ( e );
259
264
}
260
265
}catch (Exception e ){
261
- e . printStackTrace ( );
266
+ log . error ( e );
262
267
}
263
268
}
264
269
265
- private Object formatValue (Object value ){
266
- if (value instanceof java .net .URL ) return String .valueOf ((java .net .URL ) value );
267
- else return value ;
268
- }
269
-
270
270
public ExportController getExportController () {
271
271
return this .exportController ;
272
272
}
@@ -279,4 +279,34 @@ public void setFields(List<LogEntryField> fields) {
279
279
preferences .setSetting (Globals .PREF_PREVIOUS_ELASTIC_FIELDS , fields );
280
280
this .fields = fields ;
281
281
}
282
+
283
+ private class EntrySerializer extends StdSerializer <LogEntry > {
284
+
285
+ public EntrySerializer (Class <LogEntry > t ) {
286
+ super (t );
287
+ }
288
+
289
+ @ Override
290
+ public void serialize (LogEntry logEntry , JsonGenerator gen , SerializerProvider provider ) throws IOException {
291
+ gen .writeStartObject ();
292
+ for (LogEntryField field : ElasticExporter .this .fields ) {
293
+ Object value = logEntry .getValueByKey (field );
294
+ if (value == null ) continue ;
295
+ try {
296
+ switch (field .getType ().getSimpleName ()){
297
+ case "Integer" : gen .writeNumberField (field .getFullLabel (), (Integer ) value ); break ;
298
+ case "Short" : gen .writeNumberField (field .getFullLabel (), (Short ) value ); break ;
299
+ case "Double" : gen .writeNumberField (field .getFullLabel (), (Double ) value ); break ;
300
+ case "String" : gen .writeStringField (field .getFullLabel (), value .toString ()); break ;
301
+ case "Boolean" : gen .writeBooleanField (field .getFullLabel (), (Boolean ) value ); break ;
302
+ case "Date" : gen .writeNumberField (field .getFullLabel (), ((Date ) value ).getTime ()); break ;
303
+ default : log .error ("Unhandled field type: " + field .getType ().getSimpleName ());
304
+ }
305
+ }catch (Exception e ){
306
+ log .error ("ElasticExporter: Couldn't serialize field. The field was ommitted from the export." );
307
+ }
308
+ }
309
+ gen .writeEndObject ();
310
+ }
311
+ }
282
312
}
0 commit comments