40
40
import java .util .concurrent .CopyOnWriteArraySet ;
41
41
import java .util .stream .Collectors ;
42
42
43
+ import static org .elasticsearch .xpack .core .security .authz .IndicesAndAliasesResolverField .NO_INDEX_PLACEHOLDER ;
44
+
43
45
public class IndicesAndAliasesResolver {
44
46
45
- private static final ResolvedIndices NO_INDEX_PLACEHOLDER_RESOLVED =
46
- ResolvedIndices .local (IndicesAndAliasesResolverField .NO_INDEX_PLACEHOLDER );
47
47
//`*,-*` what we replace indices with if we need Elasticsearch to return empty responses without throwing exception
48
48
private static final String [] NO_INDICES_ARRAY = new String [] { "*" , "-*" };
49
49
static final List <String > NO_INDICES_LIST = Arrays .asList (NO_INDICES_ARRAY );
@@ -87,12 +87,14 @@ public IndicesAndAliasesResolver(Settings settings, ClusterService clusterServic
87
87
88
88
public ResolvedIndices resolve (TransportRequest request , MetaData metaData , AuthorizedIndices authorizedIndices ) {
89
89
if (request instanceof IndicesAliasesRequest ) {
90
- ResolvedIndices indices = ResolvedIndices .empty ();
90
+ ResolvedIndices . Builder resolvedIndicesBuilder = new ResolvedIndices .Builder ();
91
91
IndicesAliasesRequest indicesAliasesRequest = (IndicesAliasesRequest ) request ;
92
92
for (IndicesRequest indicesRequest : indicesAliasesRequest .getAliasActions ()) {
93
- indices = ResolvedIndices .add (indices , resolveIndicesAndAliases (indicesRequest , metaData , authorizedIndices ));
93
+ final ResolvedIndices resolved = resolveIndicesAndAliases (indicesRequest , metaData , authorizedIndices );
94
+ resolvedIndicesBuilder .addLocal (resolved .getLocal ());
95
+ resolvedIndicesBuilder .addRemote (resolved .getRemote ());
94
96
}
95
- return indices ;
97
+ return resolvedIndicesBuilder . build () ;
96
98
}
97
99
98
100
// if for some reason we are missing an action... just for safety we'll reject
@@ -102,10 +104,10 @@ public ResolvedIndices resolve(TransportRequest request, MetaData metaData, Auth
102
104
return resolveIndicesAndAliases ((IndicesRequest ) request , metaData , authorizedIndices );
103
105
}
104
106
105
- ResolvedIndices resolveIndicesAndAliases (IndicesRequest indicesRequest , MetaData metaData ,
106
- AuthorizedIndices authorizedIndices ) {
107
+
108
+ ResolvedIndices resolveIndicesAndAliases (IndicesRequest indicesRequest , MetaData metaData , AuthorizedIndices authorizedIndices ) {
109
+ final ResolvedIndices .Builder resolvedIndicesBuilder = new ResolvedIndices .Builder ();
107
110
boolean indicesReplacedWithNoIndices = false ;
108
- final ResolvedIndices indices ;
109
111
if (indicesRequest instanceof PutMappingRequest && ((PutMappingRequest ) indicesRequest ).getConcreteIndex () != null ) {
110
112
/*
111
113
* This is a special case since PutMappingRequests from dynamic mapping updates have a concrete index
@@ -114,7 +116,7 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
114
116
*/
115
117
assert indicesRequest .indices () == null || indicesRequest .indices ().length == 0
116
118
: "indices are: " + Arrays .toString (indicesRequest .indices ()); // Arrays.toString() can handle null values - all good
117
- return ResolvedIndices . local (((PutMappingRequest ) indicesRequest ).getConcreteIndex ().getName ());
119
+ resolvedIndicesBuilder . addLocal (((PutMappingRequest ) indicesRequest ).getConcreteIndex ().getName ());
118
120
} else if (indicesRequest instanceof IndicesRequest .Replaceable ) {
119
121
IndicesRequest .Replaceable replaceable = (IndicesRequest .Replaceable ) indicesRequest ;
120
122
final boolean replaceWildcards = indicesRequest .indicesOptions ().expandWildcardsOpen ()
@@ -127,13 +129,12 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
127
129
indicesOptions .expandWildcardsOpen (), indicesOptions .expandWildcardsClosed ());
128
130
}
129
131
130
- ResolvedIndices result = ResolvedIndices .empty ();
131
132
// check for all and return list of authorized indices
132
133
if (IndexNameExpressionResolver .isAllIndices (indicesList (indicesRequest .indices ()))) {
133
134
if (replaceWildcards ) {
134
135
for (String authorizedIndex : authorizedIndices .get ()) {
135
136
if (isIndexVisible (authorizedIndex , indicesOptions , metaData )) {
136
- result = ResolvedIndices . add ( result , ResolvedIndices . local ( authorizedIndex ) );
137
+ resolvedIndicesBuilder . addLocal ( authorizedIndex );
137
138
}
138
139
}
139
140
}
@@ -144,7 +145,7 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
144
145
if (allowsRemoteIndices (indicesRequest )) {
145
146
split = remoteClusterResolver .splitLocalAndRemoteIndexNames (indicesRequest .indices ());
146
147
} else {
147
- split = ResolvedIndices . local (indicesRequest .indices ());
148
+ split = new ResolvedIndices ( Arrays . asList (indicesRequest .indices ()), Collections . emptyList ());
148
149
}
149
150
List <String > replaced = replaceWildcardsWithAuthorizedIndices (split .getLocal (), indicesOptions , metaData ,
150
151
authorizedIndices .get (), replaceWildcards );
@@ -153,22 +154,23 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
153
154
//remove all the ones that the current user is not authorized for and ignore them
154
155
replaced = replaced .stream ().filter (authorizedIndices .get ()::contains ).collect (Collectors .toList ());
155
156
}
156
- result = new ResolvedIndices (new ArrayList <>(replaced ), split .getRemote ());
157
+ resolvedIndicesBuilder .addLocal (replaced );
158
+ resolvedIndicesBuilder .addRemote (split .getRemote ());
157
159
}
158
- if (result .isEmpty ()) {
160
+
161
+ if (resolvedIndicesBuilder .isEmpty ()) {
159
162
if (indicesOptions .allowNoIndices ()) {
160
163
//this is how we tell es core to return an empty response, we can let the request through being sure
161
164
//that the '-*' wildcard expression will be resolved to no indices. We can't let empty indices through
162
165
//as that would be resolved to _all by es core.
163
166
replaceable .indices (NO_INDICES_ARRAY );
164
167
indicesReplacedWithNoIndices = true ;
165
- indices = NO_INDEX_PLACEHOLDER_RESOLVED ;
168
+ resolvedIndicesBuilder . addLocal ( NO_INDEX_PLACEHOLDER ) ;
166
169
} else {
167
170
throw new IndexNotFoundException (Arrays .toString (indicesRequest .indices ()));
168
171
}
169
172
} else {
170
- replaceable .indices (result .toArray ());
171
- indices = result ;
173
+ replaceable .indices (resolvedIndicesBuilder .build ().toArray ());
172
174
}
173
175
} else {
174
176
if (containsWildcards (indicesRequest )) {
@@ -182,11 +184,9 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
182
184
//That is fine though because they never contain wildcards, as they get replaced as part of the authorization of their
183
185
//corresponding parent request on the coordinating node. Hence wildcards don't need to get replaced nor exploded for
184
186
// shard level requests.
185
- List <String > resolvedNames = new ArrayList <>();
186
187
for (String name : indicesRequest .indices ()) {
187
- resolvedNames . add (nameExpressionResolver .resolveDateMathExpression (name ));
188
+ resolvedIndicesBuilder . addLocal (nameExpressionResolver .resolveDateMathExpression (name ));
188
189
}
189
- indices = new ResolvedIndices (resolvedNames , new ArrayList <>());
190
190
}
191
191
192
192
if (indicesRequest instanceof AliasesRequest ) {
@@ -207,10 +207,10 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
207
207
//if we replaced the indices with '-*' we shouldn't be adding the aliases to the list otherwise the request will
208
208
//not get authorized. Leave only '-*' and ignore the rest, result will anyway be empty.
209
209
} else {
210
- return ResolvedIndices . add ( indices , ResolvedIndices . local ( aliasesRequest .aliases () ));
210
+ resolvedIndicesBuilder . addLocal ( aliasesRequest .aliases ());
211
211
}
212
212
}
213
- return indices ;
213
+ return resolvedIndicesBuilder . build () ;
214
214
}
215
215
216
216
public static boolean allowsRemoteIndices (IndicesRequest request ) {
@@ -423,24 +423,8 @@ public static class ResolvedIndices {
423
423
private final List <String > remote ;
424
424
425
425
ResolvedIndices (List <String > local , List <String > remote ) {
426
- this .local = local ;
427
- this .remote = remote ;
428
- }
429
-
430
- /**
431
- * Constructs a new instance of this class where both the {@link #getLocal() local} and {@link #getRemote() remote} index lists
432
- * are empty.
433
- */
434
- private static ResolvedIndices empty () {
435
- return new ResolvedIndices (Collections .emptyList (), Collections .emptyList ());
436
- }
437
-
438
- /**
439
- * Constructs a new instance of this class where both the {@link #getLocal() local} index list is populated with <code>names</code>
440
- * and the {@link #getRemote() remote} index list is empty.
441
- */
442
- private static ResolvedIndices local (String ... names ) {
443
- return new ResolvedIndices (Arrays .asList (names ), Collections .emptyList ());
426
+ this .local = Collections .unmodifiableList (local );
427
+ this .remote = Collections .unmodifiableList (remote );
444
428
}
445
429
446
430
/**
@@ -449,14 +433,14 @@ private static ResolvedIndices local(String... names) {
449
433
* to <code>[ "-a1", "a*" ]</code>. As a consequence, this list <em>may contain duplicates</em>.
450
434
*/
451
435
public List <String > getLocal () {
452
- return Collections . unmodifiableList ( local ) ;
436
+ return local ;
453
437
}
454
438
455
439
/**
456
440
* Returns the collection of index names that have been stored as "remote" indices.
457
441
*/
458
442
public List <String > getRemote () {
459
- return Collections . unmodifiableList ( remote ) ;
443
+ return remote ;
460
444
}
461
445
462
446
/**
@@ -471,7 +455,7 @@ public boolean isEmpty() {
471
455
* {@link IndicesAndAliasesResolverField#NO_INDEX_PLACEHOLDER no-index-placeholder} and nothing else.
472
456
*/
473
457
public boolean isNoIndicesPlaceholder () {
474
- return remote .isEmpty () && local .size () == 1 && local .contains (IndicesAndAliasesResolverField . NO_INDEX_PLACEHOLDER );
458
+ return remote .isEmpty () && local .size () == 1 && local .contains (NO_INDEX_PLACEHOLDER );
475
459
}
476
460
477
461
private String [] toArray () {
@@ -487,19 +471,43 @@ private String[] toArray() {
487
471
}
488
472
489
473
/**
490
- * Returns a new <code> ResolvedIndices</code> contains the {@link #getLocal() local} and {@link #getRemote() remote}
491
- * index lists from <code>b</code> appended to the corresponding lists in <code>a</code>.
474
+ * Builder class for ResolvedIndices that allows for the building of a list of indices
475
+ * without the need to construct new objects and merging them together
492
476
*/
493
- private static ResolvedIndices add (ResolvedIndices a , ResolvedIndices b ) {
494
- List <String > local = new ArrayList <>(a .local .size () + b .local .size ());
495
- local .addAll (a .local );
496
- local .addAll (b .local );
497
-
498
- List <String > remote = new ArrayList <>(a .remote .size () + b .remote .size ());
499
- remote .addAll (a .remote );
500
- remote .addAll (b .remote );
501
- return new ResolvedIndices (local , remote );
502
- }
477
+ private static class Builder {
478
+
479
+ private final List <String > local = new ArrayList <>();
480
+ private final List <String > remote = new ArrayList <>();
503
481
482
+ /** add a local index name */
483
+ private void addLocal (String index ) {
484
+ local .add (index );
485
+ }
486
+
487
+ /** adds the array of local index names */
488
+ private void addLocal (String [] indices ) {
489
+ local .addAll (Arrays .asList (indices ));
490
+ }
491
+
492
+ /** adds the list of local index names */
493
+ private void addLocal (List <String > indices ) {
494
+ local .addAll (indices );
495
+ }
496
+
497
+ /** adds the list of remote index names */
498
+ private void addRemote (List <String > indices ) {
499
+ remote .addAll (indices );
500
+ }
501
+
502
+ /** @return <code>true</code> if both the local and remote index lists are empty. */
503
+ private boolean isEmpty () {
504
+ return local .isEmpty () && remote .isEmpty ();
505
+ }
506
+
507
+ /** @return a immutable ResolvedIndices instance with the local and remote index lists */
508
+ private ResolvedIndices build () {
509
+ return new ResolvedIndices (local , remote );
510
+ }
511
+ }
504
512
}
505
513
}
0 commit comments