5
5
6
6
package org .opensearch .securityanalytics .mapper ;
7
7
8
- import java .io .IOException ;
9
- import java .util .ArrayList ;
10
- import java .util .Collection ;
11
- import java .util .HashMap ;
12
- import java .util .HashSet ;
13
- import java .util .List ;
14
- import java .util .Map ;
15
- import java .util .Optional ;
16
- import java .util .Set ;
17
- import java .util .stream .Collectors ;
18
8
import org .apache .commons .lang3 .tuple .Pair ;
19
9
import org .apache .logging .log4j .LogManager ;
20
10
import org .apache .logging .log4j .Logger ;
21
- import org .opensearch .OpenSearchStatusException ;
22
11
import org .opensearch .action .ActionListener ;
23
12
import org .opensearch .action .admin .indices .get .GetIndexRequest ;
24
13
import org .opensearch .action .admin .indices .get .GetIndexResponse ;
44
33
import org .opensearch .securityanalytics .util .IndexUtils ;
45
34
import org .opensearch .securityanalytics .util .SecurityAnalyticsException ;
46
35
36
+ import java .io .IOException ;
37
+ import java .util .ArrayList ;
38
+ import java .util .Collection ;
39
+ import java .util .HashMap ;
40
+ import java .util .HashSet ;
41
+ import java .util .List ;
42
+ import java .util .Map ;
43
+ import java .util .Optional ;
44
+ import java .util .Set ;
45
+ import java .util .stream .Collectors ;
47
46
48
47
import static org .opensearch .securityanalytics .mapper .MapperUtils .PATH ;
49
48
import static org .opensearch .securityanalytics .mapper .MapperUtils .PROPERTIES ;
@@ -78,9 +77,11 @@ public void createMappingAction(String indexName, String logType, String aliasMa
78
77
// since you can't update documents in non-write indices
79
78
String index = indexName ;
80
79
boolean shouldUpsertIndexTemplate = IndexUtils .isConcreteIndex (indexName , this .clusterService .state ()) == false ;
81
- if (IndexUtils .isDataStream (indexName , this .clusterService .state ())) {
80
+ if (IndexUtils .isDataStream (indexName , this .clusterService .state ()) || IndexUtils .isAlias (indexName , this .clusterService .state ())) {
81
+ log .debug ("{} is an alias or datastream. Fetching write index for create mapping action." , indexName );
82
82
String writeIndex = IndexUtils .getWriteIndex (indexName , this .clusterService .state ());
83
83
if (writeIndex != null ) {
84
+ log .debug ("Write index for {} is {}" , indexName , writeIndex );
84
85
index = writeIndex ;
85
86
}
86
87
}
@@ -92,6 +93,7 @@ public void onResponse(GetMappingsResponse getMappingsResponse) {
92
93
applyAliasMappings (getMappingsResponse .getMappings (), logType , aliasMappings , partial , new ActionListener <>() {
93
94
@ Override
94
95
public void onResponse (Collection <CreateMappingResult > createMappingResponse ) {
96
+ log .debug ("Completed create mappings for {}" , indexName );
95
97
// We will return ack==false if one of the requests returned that
96
98
// else return ack==true
97
99
Optional <AcknowledgedResponse > notAckd = createMappingResponse .stream ()
@@ -110,6 +112,7 @@ public void onResponse(Collection<CreateMappingResult> createMappingResponse) {
110
112
111
113
@ Override
112
114
public void onFailure (Exception e ) {
115
+ log .debug ("Failed to create mappings for {}" , indexName );
113
116
actionListener .onFailure (e );
114
117
}
115
118
});
@@ -478,13 +481,16 @@ public void onResponse(GetMappingsResponse getMappingsResponse) {
478
481
String rawPath = requiredField .getRawField ();
479
482
String ocsfPath = requiredField .getOcsf ();
480
483
if (allFieldsFromIndex .contains (rawPath )) {
481
- if (alias != null ) {
482
- // Maintain list of found paths in index
483
- applyableAliases .add (alias );
484
- } else {
485
- applyableAliases .add (rawPath );
484
+ // if the alias was already added into applyable aliases, then skip to avoid duplicates
485
+ if (!applyableAliases .contains (alias ) && !applyableAliases .contains (rawPath )) {
486
+ if (alias != null ) {
487
+ // Maintain list of found paths in index
488
+ applyableAliases .add (alias );
489
+ } else {
490
+ applyableAliases .add (rawPath );
491
+ }
492
+ pathsOfApplyableAliases .add (rawPath );
486
493
}
487
- pathsOfApplyableAliases .add (rawPath );
488
494
} else if (allFieldsFromIndex .contains (ocsfPath )) {
489
495
applyableAliases .add (alias );
490
496
pathsOfApplyableAliases .add (ocsfPath );
@@ -498,13 +504,23 @@ public void onResponse(GetMappingsResponse getMappingsResponse) {
498
504
}
499
505
}
500
506
507
+ // turn unmappedFieldAliases into a set to remove duplicates
508
+ Set <String > setOfUnmappedFieldAliases = new HashSet <>(unmappedFieldAliases );
509
+
510
+ // filter out aliases that were included in applyableAliases already
511
+ List <String > filteredUnmappedFieldAliases = setOfUnmappedFieldAliases .stream ()
512
+ .filter (e -> false == applyableAliases .contains (e ))
513
+ .collect (Collectors .toList ());
514
+
501
515
Map <String , Map <String , String >> aliasMappingFields = new HashMap <>();
502
516
XContentBuilder aliasMappingsObj = XContentFactory .jsonBuilder ().startObject ();
503
517
for (LogType .Mapping mapping : requiredFields ) {
504
518
if (allFieldsFromIndex .contains (mapping .getOcsf ())) {
505
519
aliasMappingFields .put (mapping .getEcs (), Map .of ("type" , "alias" , "path" , mapping .getOcsf ()));
506
520
} else if (mapping .getEcs () != null ) {
507
- aliasMappingFields .put (mapping .getEcs (), Map .of ("type" , "alias" , "path" , mapping .getRawField ()));
521
+ shouldUpdateEcsMappingAndMaybeUpdates (mapping , aliasMappingFields , pathsOfApplyableAliases );
522
+ } else if (mapping .getEcs () == null ) {
523
+ aliasMappingFields .put (mapping .getRawField (), Map .of ("type" , "alias" , "path" , mapping .getRawField ()));
508
524
}
509
525
}
510
526
aliasMappingsObj .field ("properties" , aliasMappingFields );
@@ -519,7 +535,7 @@ public void onResponse(GetMappingsResponse getMappingsResponse) {
519
535
.collect (Collectors .toList ());
520
536
521
537
actionListener .onResponse (
522
- new GetMappingsViewResponse (aliasMappings , unmappedIndexFields , unmappedFieldAliases )
538
+ new GetMappingsViewResponse (aliasMappings , unmappedIndexFields , filteredUnmappedFieldAliases )
523
539
);
524
540
} catch (Exception e ) {
525
541
actionListener .onFailure (e );
@@ -533,6 +549,26 @@ public void onFailure(Exception e) {
533
549
});
534
550
}
535
551
552
+ /**
553
+ * Only updates the alias mapping fields if the ecs key has not been mapped yet
554
+ * or if pathOfApplyableAliases contains the raw field
555
+ *
556
+ * @param mapping
557
+ * @param aliasMappingFields
558
+ * @param pathsOfApplyableAliases
559
+ */
560
+ private static void shouldUpdateEcsMappingAndMaybeUpdates (LogType .Mapping mapping , Map <String , Map <String , String >> aliasMappingFields , List <String > pathsOfApplyableAliases ) {
561
+ // check if aliasMappingFields already contains a key
562
+ if (aliasMappingFields .containsKey (mapping .getEcs ())) {
563
+ // if the pathOfApplyableAliases contains the raw field, then override the existing map
564
+ if (pathsOfApplyableAliases .contains (mapping .getRawField ())) {
565
+ aliasMappingFields .put (mapping .getEcs (), Map .of ("type" , "alias" , "path" , mapping .getRawField ()));
566
+ }
567
+ } else {
568
+ aliasMappingFields .put (mapping .getEcs (), Map .of ("type" , "alias" , "path" , mapping .getRawField ()));
569
+ }
570
+ }
571
+
536
572
/**
537
573
* Given index name, resolves it to single concrete index, depending on what initial <code>indexName</code> is.
538
574
* In case of Datastream or Alias, WriteIndex would be returned. In case of index pattern, newest index by creation date would be returned.
0 commit comments