Skip to content

Commit 70a1472

Browse files
committed
Move Security to use auto-managed system indices
Backport of elastic#67114. Part of elastic#61656. Change the Security plugin so that its system indices are managed automatically by the system indices infrastructure. Also add an `origin` field to `CreateIndexRequest` and `UpdateSettingsRequest`.
1 parent 5bce45b commit 70a1472

File tree

30 files changed

+926
-849
lines changed

30 files changed

+926
-849
lines changed

server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class TestSystemIndexDescriptor extends SystemIndexDescriptor {
5151
.build();
5252

5353
TestSystemIndexDescriptor() {
54+
<<<<<<< HEAD
5455
super(
5556
INDEX_NAME + "*",
5657
PRIMARY_INDEX_NAME,
@@ -63,6 +64,9 @@ public class TestSystemIndexDescriptor extends SystemIndexDescriptor {
6364
"stack",
6465
MapperService.SINGLE_MAPPING_NAME
6566
);
67+
=======
68+
super(INDEX_NAME + "*", PRIMARY_INDEX_NAME, "Test system index", null, SETTINGS, INDEX_NAME, 0, "version", "stack", null);
69+
>>>>>>> 6ffddf8f018... Move Security to use auto-managed system indices (#67114)
6670
}
6771

6872
@Override

server/src/main/java/org/elasticsearch/action/admin/indices/create/AutoCreateAction.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,24 @@ public ClusterState execute(ClusterState currentState) throws Exception {
151151
}
152152

153153
final SystemIndexDescriptor descriptor = systemIndices.findMatchingDescriptor(indexName);
154-
CreateIndexClusterStateUpdateRequest updateRequest = descriptor != null && descriptor.isAutomaticallyManaged()
155-
? buildSystemIndexUpdateRequest(descriptor)
156-
: buildUpdateRequest(indexName);
154+
final boolean isSystemIndex = descriptor != null && descriptor.isAutomaticallyManaged();
155+
156+
final CreateIndexClusterStateUpdateRequest updateRequest;
157+
158+
if (isSystemIndex) {
159+
final String message = descriptor.checkMinimumNodeVersion(
160+
"auto-create index",
161+
state.nodes().getMinNodeVersion()
162+
);
163+
if (message != null) {
164+
logger.warn(message);
165+
throw new IllegalStateException(message);
166+
}
167+
168+
updateRequest = buildSystemIndexUpdateRequest(descriptor);
169+
} else {
170+
updateRequest = buildUpdateRequest(indexName);
171+
}
157172

158173
return createIndexService.applyCreateIndexRequest(currentState, updateRequest, false);
159174
}

server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ public class CreateIndexRequest extends AcknowledgedRequest<CreateIndexRequest>
8787

8888
private ActiveShardCount waitForActiveShards = ActiveShardCount.DEFAULT;
8989

90+
private String origin = "";
91+
92+
/**
93+
* Constructs a new request by deserializing an input
94+
* @param in the input from which to deserialize
95+
*/
9096
public CreateIndexRequest(StreamInput in) throws IOException {
9197
super(in);
9298
cause = in.readString();
@@ -118,20 +124,28 @@ public CreateIndexRequest(StreamInput in) throws IOException {
118124
in.readBoolean(); // updateAllTypes
119125
}
120126
waitForActiveShards = ActiveShardCount.readFrom(in);
127+
if (in.getVersion().onOrAfter(Version.V_7_12_0)) {
128+
origin = in.readString();
129+
}
121130
}
122131

123132
public CreateIndexRequest() {
124133
}
125134

126135
/**
127-
* Constructs a new request to create an index with the specified name.
136+
* Constructs a request to create an index.
137+
*
138+
* @param index the name of the index
128139
*/
129140
public CreateIndexRequest(String index) {
130141
this(index, EMPTY_SETTINGS);
131142
}
132143

133144
/**
134-
* Constructs a new request to create an index with the specified name and settings.
145+
* Constructs a request to create an index.
146+
*
147+
* @param index the name of the index
148+
* @param settings the settings to apply to the index
135149
*/
136150
public CreateIndexRequest(String index, Settings settings) {
137151
this.index = index;
@@ -183,6 +197,15 @@ public String cause() {
183197
return cause;
184198
}
185199

200+
public String origin() {
201+
return origin;
202+
}
203+
204+
public CreateIndexRequest origin(String origin) {
205+
this.origin = Objects.requireNonNull(origin);
206+
return this;
207+
}
208+
186209
/**
187210
* The settings to create the index with.
188211
*/
@@ -276,7 +299,7 @@ public CreateIndexRequest mapping(String type, Map<String, ?> source) {
276299
throw new IllegalStateException("mappings for type \"" + type + "\" were already defined");
277300
}
278301
// wrap it in a type map if its not
279-
if (source.size() != 1 || !source.containsKey(type)) {
302+
if (source.size() != 1 || source.containsKey(type) == false) {
280303
source = MapBuilder.<String, Object>newMapBuilder().put(type, source).map();
281304
}
282305
try {
@@ -477,6 +500,9 @@ public void writeTo(StreamOutput out) throws IOException {
477500
out.writeBoolean(true); // updateAllTypes
478501
}
479502
waitForActiveShards.writeTo(out);
503+
if (out.getVersion().onOrAfter(Version.V_7_12_0)) {
504+
out.writeString(origin);
505+
}
480506
}
481507

482508
@Override

server/src/main/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexAction.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
package org.elasticsearch.action.admin.indices.create;
2121

22+
import org.apache.logging.log4j.LogManager;
23+
import org.apache.logging.log4j.Logger;
2224
import org.elasticsearch.action.ActionListener;
2325
import org.elasticsearch.action.admin.indices.alias.Alias;
2426
import org.elasticsearch.action.support.ActionFilters;
@@ -30,6 +32,7 @@
3032
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
3133
import org.elasticsearch.cluster.metadata.MetadataCreateIndexService;
3234
import org.elasticsearch.cluster.service.ClusterService;
35+
import org.elasticsearch.common.Strings;
3336
import org.elasticsearch.common.inject.Inject;
3437
import org.elasticsearch.common.settings.Settings;
3538
import org.elasticsearch.indices.SystemIndexDescriptor;
@@ -46,6 +49,7 @@
4649
* Create index action.
4750
*/
4851
public class TransportCreateIndexAction extends TransportMasterNodeAction<CreateIndexRequest, CreateIndexResponse> {
52+
private static final Logger logger = LogManager.getLogger(TransportCreateIndexAction.class);
4953

5054
private final MetadataCreateIndexService createIndexService;
5155
private final SystemIndices systemIndices;
@@ -77,9 +81,25 @@ protected void masterOperation(final CreateIndexRequest request, final ClusterSt
7781
final String indexName = indexNameExpressionResolver.resolveDateMathExpression(request.index());
7882

7983
final SystemIndexDescriptor descriptor = systemIndices.findMatchingDescriptor(indexName);
80-
final CreateIndexClusterStateUpdateRequest updateRequest = descriptor != null && descriptor.isAutomaticallyManaged()
81-
? buildSystemIndexUpdateRequest(request, cause, descriptor)
82-
: buildUpdateRequest(request, cause, indexName);
84+
final boolean isSystemIndex = descriptor != null && descriptor.isAutomaticallyManaged();
85+
86+
final CreateIndexClusterStateUpdateRequest updateRequest;
87+
88+
// Requests that a cluster generates itself are permitted to create a system index with
89+
// different mappings, settings etc. This is so that rolling upgrade scenarios still work.
90+
// We check this via the request's origin. Eventually, `SystemIndexManager` will reconfigure
91+
// the index to the latest settings.
92+
if (isSystemIndex && Strings.isNullOrEmpty(request.origin())) {
93+
final String message = descriptor.checkMinimumNodeVersion("create index", state.nodes().getMinNodeVersion());
94+
if (message != null) {
95+
logger.warn(message);
96+
listener.onFailure(new IllegalStateException(message));
97+
return;
98+
}
99+
updateRequest = buildSystemIndexUpdateRequest(request, cause, descriptor);
100+
} else {
101+
updateRequest = buildUpdateRequest(request, cause, indexName);
102+
}
83103

84104
createIndexService.createIndex(updateRequest, listener.map(response ->
85105
new CreateIndexResponse(response.isAcknowledged(), response.isShardsAcknowledged(), indexName)));

server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/TransportAutoPutMappingAction.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
package org.elasticsearch.action.admin.indices.mapping.put;
2020

21+
import org.apache.logging.log4j.LogManager;
22+
import org.apache.logging.log4j.Logger;
2123
import org.elasticsearch.action.ActionListener;
2224
import org.elasticsearch.action.support.ActionFilters;
2325
import org.elasticsearch.action.support.master.AcknowledgedResponse;
@@ -30,6 +32,7 @@
3032
import org.elasticsearch.cluster.service.ClusterService;
3133
import org.elasticsearch.common.inject.Inject;
3234
import org.elasticsearch.index.Index;
35+
import org.elasticsearch.indices.SystemIndices;
3336
import org.elasticsearch.tasks.Task;
3437
import org.elasticsearch.threadpool.ThreadPool;
3538
import org.elasticsearch.transport.TransportService;
@@ -38,7 +41,10 @@
3841

3942
public class TransportAutoPutMappingAction extends AcknowledgedTransportMasterNodeAction<PutMappingRequest> {
4043

44+
private static final Logger logger = LogManager.getLogger(TransportAutoPutMappingAction.class);
45+
4146
private final MetadataMappingService metadataMappingService;
47+
private final SystemIndices systemIndices;
4248

4349
@Inject
4450
public TransportAutoPutMappingAction(
@@ -47,10 +53,12 @@ public TransportAutoPutMappingAction(
4753
final ThreadPool threadPool,
4854
final MetadataMappingService metadataMappingService,
4955
final ActionFilters actionFilters,
50-
final IndexNameExpressionResolver indexNameExpressionResolver) {
56+
final IndexNameExpressionResolver indexNameExpressionResolver,
57+
final SystemIndices systemIndices) {
5158
super(AutoPutMappingAction.NAME, transportService, clusterService, threadPool, actionFilters,
5259
PutMappingRequest::new, indexNameExpressionResolver, ThreadPool.Names.SAME);
5360
this.metadataMappingService = metadataMappingService;
61+
this.systemIndices = systemIndices;
5462
}
5563

5664
@Override
@@ -72,6 +80,14 @@ protected ClusterBlockException checkBlock(PutMappingRequest request, ClusterSta
7280
protected void masterOperation(final PutMappingRequest request, final ClusterState state,
7381
final ActionListener<AcknowledgedResponse> listener) {
7482
final Index[] concreteIndices = new Index[] {request.getConcreteIndex()};
83+
84+
final String message = TransportPutMappingAction.checkForSystemIndexViolations(systemIndices, concreteIndices, request);
85+
if (message != null) {
86+
logger.warn(message);
87+
listener.onFailure(new IllegalStateException(message));
88+
return;
89+
}
90+
7591
performMappingUpdate(concreteIndices, request, listener, metadataMappingService);
7692
}
7793

server/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/TransportPutMappingAction.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
3434
import org.elasticsearch.cluster.metadata.MetadataMappingService;
3535
import org.elasticsearch.cluster.service.ClusterService;
36+
import org.elasticsearch.common.Strings;
3637
import org.elasticsearch.common.inject.Inject;
3738
import org.elasticsearch.index.Index;
3839
import org.elasticsearch.index.IndexNotFoundException;
@@ -91,22 +92,17 @@ protected void masterOperation(final PutMappingRequest request, final ClusterSta
9192
final ActionListener<AcknowledgedResponse> listener) {
9293
try {
9394
final Index[] concreteIndices = resolveIndices(state, request, indexNameExpressionResolver);
94-
final String mappingSource = request.source();
9595

9696
final Optional<Exception> maybeValidationException = requestValidators.validateRequest(request, state, concreteIndices);
9797
if (maybeValidationException.isPresent()) {
9898
listener.onFailure(maybeValidationException.get());
9999
return;
100100
}
101101

102-
final List<String> violations = checkForSystemIndexViolations(concreteIndices, mappingSource);
103-
if (violations.isEmpty() == false) {
104-
final String message = "Cannot update mappings in "
105-
+ violations
106-
+ ": system indices can only use mappings from their descriptors, "
107-
+ "but the mappings in the request did not match those in the descriptors(s)";
102+
final String message = checkForSystemIndexViolations(systemIndices, concreteIndices, request);
103+
if (message != null) {
108104
logger.warn(message);
109-
listener.onFailure(new IllegalArgumentException(message));
105+
listener.onFailure(new IllegalStateException(message));
110106
return;
111107
}
112108

@@ -160,21 +156,36 @@ public void onFailure(Exception t) {
160156
});
161157
}
162158

163-
private List<String> checkForSystemIndexViolations(Index[] concreteIndices, String requestMappings) {
159+
static String checkForSystemIndexViolations(SystemIndices systemIndices, Index[] concreteIndices, PutMappingRequest request) {
160+
// Requests that a cluster generates itself are permitted to have a difference in mappings
161+
// so that rolling upgrade scenarios still work. We check this via the request's origin.
162+
if (Strings.isNullOrEmpty(request.origin()) == false) {
163+
return null;
164+
}
165+
164166
List<String> violations = new ArrayList<>();
165167

168+
final String requestMappings = request.source();
169+
166170
for (Index index : concreteIndices) {
167171
final SystemIndexDescriptor descriptor = systemIndices.findMatchingDescriptor(index.getName());
168172
if (descriptor != null && descriptor.isAutomaticallyManaged()) {
169173
final String descriptorMappings = descriptor.getMappings();
170-
171174
// Technically we could trip over a difference in whitespace here, but then again nobody should be trying to manually
172175
// update a descriptor's mappings.
173176
if (descriptorMappings.equals(requestMappings) == false) {
174177
violations.add(index.getName());
175178
}
176179
}
177180
}
178-
return violations;
181+
182+
if (violations.isEmpty() == false) {
183+
return "Cannot update mappings in "
184+
+ violations
185+
+ ": system indices can only use mappings from their descriptors, "
186+
+ "but the mappings in the request did not match those in the descriptors(s)";
187+
}
188+
189+
return null;
179190
}
180191
}

0 commit comments

Comments
 (0)