Skip to content

Commit 745861d

Browse files
committed
Revert "Fix BWC for file-settings based role mappings (#113900)"
This reverts commit 763764c.
1 parent 6c4632b commit 745861d

File tree

13 files changed

+64
-265
lines changed

13 files changed

+64
-265
lines changed

docs/changelog/113900.yaml

Lines changed: 0 additions & 5 deletions
This file was deleted.

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/rolemapping/GetRoleMappingsResponse.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping;
1212

1313
import java.io.IOException;
14-
import java.util.Collection;
1514

1615
/**
1716
* Response to {@link GetRoleMappingsAction get role-mappings API}.
@@ -22,10 +21,6 @@ public class GetRoleMappingsResponse extends ActionResponse {
2221

2322
private final ExpressionRoleMapping[] mappings;
2423

25-
public GetRoleMappingsResponse(Collection<ExpressionRoleMapping> mappings) {
26-
this(mappings.toArray(new ExpressionRoleMapping[0]));
27-
}
28-
2924
public GetRoleMappingsResponse(ExpressionRoleMapping... mappings) {
3025
this.mappings = mappings;
3126
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/RoleMappingMetadata.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.elasticsearch.cluster.AbstractNamedDiffable;
1313
import org.elasticsearch.cluster.ClusterState;
1414
import org.elasticsearch.cluster.NamedDiff;
15-
import org.elasticsearch.cluster.block.ClusterBlockLevel;
1615
import org.elasticsearch.cluster.metadata.Metadata;
1716
import org.elasticsearch.common.collect.Iterators;
1817
import org.elasticsearch.common.io.stream.StreamInput;
@@ -58,7 +57,6 @@ public final class RoleMappingMetadata extends AbstractNamedDiffable<Metadata.Cu
5857
private static final RoleMappingMetadata EMPTY = new RoleMappingMetadata(Set.of());
5958

6059
public static RoleMappingMetadata getFromClusterState(ClusterState clusterState) {
61-
clusterState.blocks().globalBlockedRaiseException(ClusterBlockLevel.READ);
6260
return clusterState.metadata().custom(RoleMappingMetadata.TYPE, RoleMappingMetadata.EMPTY);
6361
}
6462

x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/integration/RoleMappingFileSettingsIT.java

Lines changed: 45 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import org.elasticsearch.xpack.core.security.action.rolemapping.PutRoleMappingAction;
3535
import org.elasticsearch.xpack.core.security.action.rolemapping.PutRoleMappingRequest;
3636
import org.elasticsearch.xpack.core.security.action.rolemapping.PutRoleMappingRequestBuilder;
37-
import org.elasticsearch.xpack.core.security.action.rolemapping.PutRoleMappingResponse;
3837
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
3938
import org.elasticsearch.xpack.core.security.authc.support.UserRoleMapper;
4039
import org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping;
@@ -59,11 +58,12 @@
5958
import static org.elasticsearch.indices.recovery.RecoverySettings.INDICES_RECOVERY_MAX_BYTES_PER_SEC_SETTING;
6059
import static org.elasticsearch.xcontent.XContentType.JSON;
6160
import static org.elasticsearch.xpack.core.security.test.TestRestrictedIndices.INTERNAL_SECURITY_MAIN_INDEX_7;
62-
import static org.elasticsearch.xpack.security.authc.support.mapper.ClusterStateRoleMapper.RESERVED_ROLE_MAPPING_SUFFIX;
6361
import static org.hamcrest.Matchers.allOf;
62+
import static org.hamcrest.Matchers.contains;
6463
import static org.hamcrest.Matchers.containsInAnyOrder;
6564
import static org.hamcrest.Matchers.containsString;
6665
import static org.hamcrest.Matchers.empty;
66+
import static org.hamcrest.Matchers.emptyArray;
6767
import static org.hamcrest.Matchers.equalTo;
6868
import static org.hamcrest.Matchers.hasSize;
6969
import static org.hamcrest.Matchers.notNullValue;
@@ -270,28 +270,21 @@ private void assertRoleMappingsSaveOK(CountDownLatch savedClusterState, AtomicLo
270270
assertThat(resolveRolesFuture.get(), containsInAnyOrder("kibana_user", "fleet_user"));
271271
}
272272

273-
// the role mappings are retrievable by the role mapping action for BWC
274-
assertGetResponseHasMappings(true, "everyone_kibana", "everyone_fleet");
275-
276-
// role mappings (with the same names) can be stored in the "native" store
277-
{
278-
PutRoleMappingResponse response = client().execute(PutRoleMappingAction.INSTANCE, sampleRestRequest("everyone_kibana"))
279-
.actionGet();
280-
assertTrue(response.isCreated());
281-
response = client().execute(PutRoleMappingAction.INSTANCE, sampleRestRequest("everyone_fleet")).actionGet();
282-
assertTrue(response.isCreated());
283-
}
284-
{
285-
// deleting role mappings that exist in the native store and in cluster-state should result in success
286-
var response = client().execute(DeleteRoleMappingAction.INSTANCE, deleteRequest("everyone_kibana")).actionGet();
287-
assertTrue(response.isFound());
288-
response = client().execute(DeleteRoleMappingAction.INSTANCE, deleteRequest("everyone_fleet")).actionGet();
289-
assertTrue(response.isFound());
290-
}
291-
273+
// the role mappings are not retrievable by the role mapping action (which only accesses "native" i.e. index-based role mappings)
274+
var request = new GetRoleMappingsRequest();
275+
request.setNames("everyone_kibana", "everyone_fleet");
276+
var response = client().execute(GetRoleMappingsAction.INSTANCE, request).get();
277+
assertFalse(response.hasMappings());
278+
assertThat(response.mappings(), emptyArray());
279+
280+
// role mappings (with the same names) can also be stored in the "native" store
281+
var putRoleMappingResponse = client().execute(PutRoleMappingAction.INSTANCE, sampleRestRequest("everyone_kibana")).actionGet();
282+
assertTrue(putRoleMappingResponse.isCreated());
283+
putRoleMappingResponse = client().execute(PutRoleMappingAction.INSTANCE, sampleRestRequest("everyone_fleet")).actionGet();
284+
assertTrue(putRoleMappingResponse.isCreated());
292285
}
293286

294-
public void testClusterStateRoleMappingsAddedThenDeleted() throws Exception {
287+
public void testRoleMappingsApplied() throws Exception {
295288
ensureGreen();
296289

297290
var savedClusterState = setupClusterStateListener(internalCluster().getMasterName(), "everyone_kibana");
@@ -300,12 +293,6 @@ public void testClusterStateRoleMappingsAddedThenDeleted() throws Exception {
300293
assertRoleMappingsSaveOK(savedClusterState.v1(), savedClusterState.v2());
301294
logger.info("---> cleanup cluster settings...");
302295

303-
{
304-
// Deleting non-existent native role mappings returns not found even if they exist in config file
305-
var response = client().execute(DeleteRoleMappingAction.INSTANCE, deleteRequest("everyone_kibana")).get();
306-
assertFalse(response.isFound());
307-
}
308-
309296
savedClusterState = setupClusterStateListenerForCleanup(internalCluster().getMasterName());
310297

311298
writeJSONFile(internalCluster().getMasterName(), emptyJSON, logger, versionCounter);
@@ -320,85 +307,48 @@ public void testClusterStateRoleMappingsAddedThenDeleted() throws Exception {
320307
clusterStateResponse.getState().metadata().persistentSettings().get(INDICES_RECOVERY_MAX_BYTES_PER_SEC_SETTING.getKey())
321308
);
322309

323-
// cluster-state role mapping was removed and is not returned in the API anymore
310+
// native role mappings are not affected by the removal of the cluster-state based ones
324311
{
325312
var request = new GetRoleMappingsRequest();
326313
request.setNames("everyone_kibana", "everyone_fleet");
327314
var response = client().execute(GetRoleMappingsAction.INSTANCE, request).get();
328-
assertFalse(response.hasMappings());
315+
assertTrue(response.hasMappings());
316+
assertThat(
317+
Arrays.stream(response.mappings()).map(ExpressionRoleMapping::getName).toList(),
318+
containsInAnyOrder("everyone_kibana", "everyone_fleet")
319+
);
329320
}
330321

331-
// no role mappings means no roles are resolved
322+
// and roles are resolved based on the native role mappings
332323
for (UserRoleMapper userRoleMapper : internalCluster().getInstances(UserRoleMapper.class)) {
333324
PlainActionFuture<Set<String>> resolveRolesFuture = new PlainActionFuture<>();
334325
userRoleMapper.resolveRoles(
335326
new UserRoleMapper.UserData("anyUsername", null, List.of(), Map.of(), mock(RealmConfig.class)),
336327
resolveRolesFuture
337328
);
338-
assertThat(resolveRolesFuture.get(), empty());
329+
assertThat(resolveRolesFuture.get(), contains("kibana_user_native"));
339330
}
340-
}
341331

342-
public void testGetRoleMappings() throws Exception {
343-
ensureGreen();
344-
345-
final List<String> nativeMappings = List.of("everyone_kibana", "_everyone_kibana", "zzz_mapping", "123_mapping");
346-
for (var mapping : nativeMappings) {
347-
client().execute(PutRoleMappingAction.INSTANCE, sampleRestRequest(mapping)).actionGet();
332+
{
333+
var request = new DeleteRoleMappingRequest();
334+
request.setName("everyone_kibana");
335+
var response = client().execute(DeleteRoleMappingAction.INSTANCE, request).get();
336+
assertTrue(response.isFound());
337+
request = new DeleteRoleMappingRequest();
338+
request.setName("everyone_fleet");
339+
response = client().execute(DeleteRoleMappingAction.INSTANCE, request).get();
340+
assertTrue(response.isFound());
348341
}
349342

350-
var savedClusterState = setupClusterStateListener(internalCluster().getMasterName(), "everyone_kibana");
351-
writeJSONFile(internalCluster().getMasterName(), testJSON, logger, versionCounter);
352-
boolean awaitSuccessful = savedClusterState.v1().await(20, TimeUnit.SECONDS);
353-
assertTrue(awaitSuccessful);
354-
355-
var request = new GetRoleMappingsRequest();
356-
var response = client().execute(GetRoleMappingsAction.INSTANCE, request).get();
357-
assertTrue(response.hasMappings());
358-
assertThat(
359-
Arrays.stream(response.mappings()).map(ExpressionRoleMapping::getName).toList(),
360-
containsInAnyOrder(
361-
"everyone_kibana",
362-
"everyone_kibana " + RESERVED_ROLE_MAPPING_SUFFIX,
363-
"_everyone_kibana",
364-
"everyone_fleet " + RESERVED_ROLE_MAPPING_SUFFIX,
365-
"zzz_mapping",
366-
"123_mapping"
367-
)
368-
);
369-
370-
int readOnlyCount = 0;
371-
// assert that cluster-state role mappings come last
372-
for (ExpressionRoleMapping mapping : response.mappings()) {
373-
readOnlyCount = mapping.getName().endsWith(RESERVED_ROLE_MAPPING_SUFFIX) ? readOnlyCount + 1 : readOnlyCount;
343+
// no roles are resolved now, because both native and cluster-state based stores have been cleared
344+
for (UserRoleMapper userRoleMapper : internalCluster().getInstances(UserRoleMapper.class)) {
345+
PlainActionFuture<Set<String>> resolveRolesFuture = new PlainActionFuture<>();
346+
userRoleMapper.resolveRoles(
347+
new UserRoleMapper.UserData("anyUsername", null, List.of(), Map.of(), mock(RealmConfig.class)),
348+
resolveRolesFuture
349+
);
350+
assertThat(resolveRolesFuture.get(), empty());
374351
}
375-
// Two sourced from cluster-state
376-
assertEquals(readOnlyCount, 2);
377-
378-
// it's possible to delete overlapping native role mapping
379-
assertTrue(client().execute(DeleteRoleMappingAction.INSTANCE, deleteRequest("everyone_kibana")).actionGet().isFound());
380-
381-
savedClusterState = setupClusterStateListenerForCleanup(internalCluster().getMasterName());
382-
writeJSONFile(internalCluster().getMasterName(), emptyJSON, logger, versionCounter);
383-
awaitSuccessful = savedClusterState.v1().await(20, TimeUnit.SECONDS);
384-
assertTrue(awaitSuccessful);
385-
386-
final ClusterStateResponse clusterStateResponse = clusterAdmin().state(
387-
new ClusterStateRequest(TEST_REQUEST_TIMEOUT).waitForMetadataVersion(savedClusterState.v2().get())
388-
).get();
389-
390-
assertNull(
391-
clusterStateResponse.getState().metadata().persistentSettings().get(INDICES_RECOVERY_MAX_BYTES_PER_SEC_SETTING.getKey())
392-
);
393-
394-
// Make sure remaining native mappings can still be fetched
395-
request = new GetRoleMappingsRequest();
396-
response = client().execute(GetRoleMappingsAction.INSTANCE, request).get();
397-
assertTrue(response.hasMappings());
398-
assertThat(
399-
Arrays.stream(response.mappings()).map(ExpressionRoleMapping::getName).toList(),
400-
containsInAnyOrder("_everyone_kibana", "zzz_mapping", "123_mapping")
401-
);
402352
}
403353

404354
public static Tuple<CountDownLatch, AtomicLong> setupClusterStateListenerForError(
@@ -483,8 +433,11 @@ public void testRoleMappingApplyWithSecurityIndexClosed() throws Exception {
483433
boolean awaitSuccessful = savedClusterState.v1().await(20, TimeUnit.SECONDS);
484434
assertTrue(awaitSuccessful);
485435

486-
// even if index is closed, cluster-state role mappings are still returned
487-
assertGetResponseHasMappings(true, "everyone_kibana", "everyone_fleet");
436+
// no native role mappings exist
437+
var request = new GetRoleMappingsRequest();
438+
request.setNames("everyone_kibana", "everyone_fleet");
439+
var response = client().execute(GetRoleMappingsAction.INSTANCE, request).get();
440+
assertFalse(response.hasMappings());
488441

489442
// cluster state settings are also applied
490443
var clusterStateResponse = clusterAdmin().state(
@@ -523,12 +476,6 @@ public void testRoleMappingApplyWithSecurityIndexClosed() throws Exception {
523476
}
524477
}
525478

526-
private DeleteRoleMappingRequest deleteRequest(String name) {
527-
var request = new DeleteRoleMappingRequest();
528-
request.setName(name);
529-
return request;
530-
}
531-
532479
private PutRoleMappingRequest sampleRestRequest(String name) throws Exception {
533480
var json = """
534481
{
@@ -547,19 +494,4 @@ private PutRoleMappingRequest sampleRestRequest(String name) throws Exception {
547494
return new PutRoleMappingRequestBuilder(null).source(name, parser).request();
548495
}
549496
}
550-
551-
private static void assertGetResponseHasMappings(boolean readOnly, String... mappings) throws InterruptedException, ExecutionException {
552-
var request = new GetRoleMappingsRequest();
553-
request.setNames(mappings);
554-
var response = client().execute(GetRoleMappingsAction.INSTANCE, request).get();
555-
assertTrue(response.hasMappings());
556-
assertThat(
557-
Arrays.stream(response.mappings()).map(ExpressionRoleMapping::getName).toList(),
558-
containsInAnyOrder(
559-
Arrays.stream(mappings)
560-
.map(mapping -> mapping + (readOnly ? " " + RESERVED_ROLE_MAPPING_SUFFIX : ""))
561-
.toArray(String[]::new)
562-
)
563-
);
564-
}
565497
}

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -897,8 +897,7 @@ Collection<Object> createComponents(
897897
reservedRealm
898898
);
899899
components.add(nativeUsersStore);
900-
components.add(clusterStateRoleMapper);
901-
components.add(nativeRoleMappingStore);
900+
components.add(new PluginComponentBinding<>(NativeRoleMappingStore.class, nativeRoleMappingStore));
902901
components.add(new PluginComponentBinding<>(UserRoleMapper.class, userRoleMapper));
903902
components.add(reservedRealm);
904903
components.add(realms);

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/rolemapping/TransportDeleteRoleMappingAction.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,24 @@
99
import org.elasticsearch.action.ActionListener;
1010
import org.elasticsearch.action.support.ActionFilters;
1111
import org.elasticsearch.action.support.HandledTransportAction;
12-
import org.elasticsearch.common.logging.HeaderWarning;
1312
import org.elasticsearch.common.util.concurrent.EsExecutors;
1413
import org.elasticsearch.injection.guice.Inject;
1514
import org.elasticsearch.tasks.Task;
1615
import org.elasticsearch.transport.TransportService;
1716
import org.elasticsearch.xpack.core.security.action.rolemapping.DeleteRoleMappingAction;
1817
import org.elasticsearch.xpack.core.security.action.rolemapping.DeleteRoleMappingRequest;
1918
import org.elasticsearch.xpack.core.security.action.rolemapping.DeleteRoleMappingResponse;
20-
import org.elasticsearch.xpack.security.authc.support.mapper.ClusterStateRoleMapper;
2119
import org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore;
2220

2321
public class TransportDeleteRoleMappingAction extends HandledTransportAction<DeleteRoleMappingRequest, DeleteRoleMappingResponse> {
2422

2523
private final NativeRoleMappingStore roleMappingStore;
26-
private final ClusterStateRoleMapper clusterStateRoleMapper;
2724

2825
@Inject
2926
public TransportDeleteRoleMappingAction(
3027
ActionFilters actionFilters,
3128
TransportService transportService,
32-
NativeRoleMappingStore roleMappingStore,
33-
ClusterStateRoleMapper clusterStateRoleMapper
29+
NativeRoleMappingStore roleMappingStore
3430
) {
3531
super(
3632
DeleteRoleMappingAction.NAME,
@@ -40,22 +36,10 @@ public TransportDeleteRoleMappingAction(
4036
EsExecutors.DIRECT_EXECUTOR_SERVICE
4137
);
4238
this.roleMappingStore = roleMappingStore;
43-
this.clusterStateRoleMapper = clusterStateRoleMapper;
4439
}
4540

4641
@Override
4742
protected void doExecute(Task task, DeleteRoleMappingRequest request, ActionListener<DeleteRoleMappingResponse> listener) {
48-
if (clusterStateRoleMapper.hasMapping(request.getName())) {
49-
// Since it's allowed to add a mapping with the same name in the native role mapping store as the file_settings namespace,
50-
// a warning header is added to signal to the caller that this could be a problem.
51-
HeaderWarning.addWarning(
52-
"A read only role mapping with the same name ["
53-
+ request.getName()
54-
+ "] has been previously been defined in a configuration file. The role mapping ["
55-
+ request.getName()
56-
+ "] defined in the configuration file is read only, will not be deleted, and will remain active."
57-
);
58-
}
5943
roleMappingStore.deleteRoleMapping(request, listener.safeMap(DeleteRoleMappingResponse::new));
6044
}
6145
}

0 commit comments

Comments
 (0)