Skip to content

Commit 8d1756c

Browse files
authored
Security: Simplify security index listeners (#30466)
This commit adds a general state listener to the SecurityIndexManager, and replaces the existing health and up-to-date listeners with that. It also moves helper methods relating to health to SecurityIndexManager from SecurityLifecycleService.
1 parent 2a79d92 commit 8d1756c

File tree

22 files changed

+358
-523
lines changed

22 files changed

+358
-523
lines changed

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

-12
This file was deleted.

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

+3-5
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@
231231
import static java.util.Collections.singletonList;
232232
import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING;
233233
import static org.elasticsearch.xpack.core.XPackSettings.HTTP_SSL_ENABLED;
234-
import static org.elasticsearch.xpack.core.security.SecurityLifecycleServiceField.SECURITY_TEMPLATE_NAME;
234+
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME;
235235
import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME;
236236
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT;
237237

@@ -424,8 +424,7 @@ Collection<Object> createComponents(Client client, ThreadPool threadPool, Cluste
424424
components.add(realms);
425425
components.add(reservedRealm);
426426

427-
securityLifecycleService.securityIndex().addIndexHealthChangeListener(nativeRoleMappingStore::onSecurityIndexHealthChange);
428-
securityLifecycleService.securityIndex().addIndexOutOfDateListener(nativeRoleMappingStore::onSecurityIndexOutOfDateChange);
427+
securityLifecycleService.securityIndex().addIndexStateListener(nativeRoleMappingStore::onSecurityIndexStateChange);
429428

430429
AuthenticationFailureHandler failureHandler = null;
431430
String extensionName = null;
@@ -458,8 +457,7 @@ Collection<Object> createComponents(Client client, ThreadPool threadPool, Cluste
458457
}
459458
final CompositeRolesStore allRolesStore = new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore,
460459
reservedRolesStore, rolesProviders, threadPool.getThreadContext(), getLicenseState());
461-
securityLifecycleService.securityIndex().addIndexHealthChangeListener(allRolesStore::onSecurityIndexHealthChange);
462-
securityLifecycleService.securityIndex().addIndexOutOfDateListener(allRolesStore::onSecurityIndexOutOfDateChange);
460+
securityLifecycleService.securityIndex().addIndexStateListener(allRolesStore::onSecurityIndexStateChange);
463461
// to keep things simple, just invalidate all cached entries on license change. this happens so rarely that the impact should be
464462
// minimal
465463
getLicenseState().addListener(allRolesStore::invalidateAll);

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

-31
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
4949
public static final String INTERNAL_SECURITY_INDEX = SecurityIndexManager.INTERNAL_SECURITY_INDEX;
5050
public static final String SECURITY_INDEX_NAME = ".security";
5151

52-
private static final Version MIN_READ_VERSION = Version.V_5_0_0;
53-
5452
private final Settings settings;
5553
private final ThreadPool threadPool;
5654
private final IndexAuditTrail indexAuditTrail;
@@ -125,36 +123,7 @@ private void close() {
125123
}
126124
}
127125

128-
public static boolean securityIndexMappingSufficientToRead(ClusterState clusterState, Logger logger) {
129-
return checkMappingVersions(clusterState, logger, MIN_READ_VERSION::onOrBefore);
130-
}
131-
132-
static boolean securityIndexMappingUpToDate(ClusterState clusterState, Logger logger) {
133-
return checkMappingVersions(clusterState, logger, Version.CURRENT::equals);
134-
}
135-
136-
private static boolean checkMappingVersions(ClusterState clusterState, Logger logger, Predicate<Version> versionPredicate) {
137-
return SecurityIndexManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, versionPredicate);
138-
}
139-
140126
public static List<String> indexNames() {
141127
return Collections.unmodifiableList(Arrays.asList(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX));
142128
}
143-
144-
/**
145-
* Is the move from {@code previousHealth} to {@code currentHealth} a move from an unhealthy ("RED") index state to a healthy
146-
* ("non-RED") state.
147-
*/
148-
public static boolean isMoveFromRedToNonRed(ClusterIndexHealth previousHealth, ClusterIndexHealth currentHealth) {
149-
return (previousHealth == null || previousHealth.getStatus() == ClusterHealthStatus.RED)
150-
&& currentHealth != null && currentHealth.getStatus() != ClusterHealthStatus.RED;
151-
}
152-
153-
/**
154-
* Is the move from {@code previousHealth} to {@code currentHealth} a move from index-exists to index-deleted
155-
*/
156-
public static boolean isIndexDeleted(ClusterIndexHealth previousHealth, ClusterIndexHealth currentHealth) {
157-
return previousHealth != null && currentHealth == null;
158-
}
159-
160129
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public static Map<String, Realm.Factory> getFactories(ThreadPool threadPool, Res
9696
map.put(FileRealmSettings.TYPE, config -> new FileRealm(config, resourceWatcherService));
9797
map.put(NativeRealmSettings.TYPE, config -> {
9898
final NativeRealm nativeRealm = new NativeRealm(config, nativeUsersStore);
99-
securityLifecycleService.securityIndex().addIndexHealthChangeListener(nativeRealm::onSecurityIndexHealthChange);
99+
securityLifecycleService.securityIndex().addIndexStateListener(nativeRealm::onSecurityIndexStateChange);
100100
return nativeRealm;
101101
});
102102
map.put(LdapRealmSettings.AD_TYPE, config -> new LdapRealm(LdapRealmSettings.AD_TYPE, config, sslService,

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealm.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
package org.elasticsearch.xpack.security.authc.esnative;
77

88
import org.elasticsearch.action.ActionListener;
9-
import org.elasticsearch.cluster.health.ClusterHealthStatus;
10-
import org.elasticsearch.cluster.health.ClusterIndexHealth;
119
import org.elasticsearch.xpack.core.security.authc.AuthenticationResult;
1210
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
1311
import org.elasticsearch.xpack.core.security.authc.esnative.NativeRealmSettings;
1412
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
1513
import org.elasticsearch.xpack.core.security.user.User;
1614
import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
15+
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
16+
17+
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isIndexDeleted;
18+
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isMoveFromRedToNonRed;
1719

1820
/**
1921
* User/password realm that is backed by an Elasticsearch index
@@ -37,12 +39,8 @@ protected void doAuthenticate(UsernamePasswordToken token, ActionListener<Authen
3739
userStore.verifyPassword(token.principal(), token.credentials(), listener);
3840
}
3941

40-
public void onSecurityIndexHealthChange(ClusterIndexHealth previousHealth, ClusterIndexHealth currentHealth) {
41-
final boolean movedFromRedToNonRed = (previousHealth == null || previousHealth.getStatus() == ClusterHealthStatus.RED)
42-
&& currentHealth != null && currentHealth.getStatus() != ClusterHealthStatus.RED;
43-
final boolean indexDeleted = previousHealth != null && currentHealth == null;
44-
45-
if (movedFromRedToNonRed || indexDeleted) {
42+
public void onSecurityIndexStateChange(SecurityIndexManager.State previousState, SecurityIndexManager.State currentState) {
43+
if (isMoveFromRedToNonRed(previousState, currentState) || isIndexDeleted(previousState, currentState)) {
4644
clearCache();
4745
}
4846
}

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStore.java

+7-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.action.search.SearchRequest;
1313
import org.elasticsearch.action.support.ContextPreservingActionListener;
1414
import org.elasticsearch.client.Client;
15+
import org.elasticsearch.cluster.health.ClusterHealthStatus;
1516
import org.elasticsearch.cluster.health.ClusterIndexHealth;
1617
import org.elasticsearch.common.CheckedBiConsumer;
1718
import org.elasticsearch.common.bytes.BytesReference;
@@ -38,6 +39,7 @@
3839
import org.elasticsearch.xpack.security.SecurityLifecycleService;
3940
import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
4041
import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
42+
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
4143

4244
import java.io.IOException;
4345
import java.io.InputStream;
@@ -61,8 +63,8 @@
6163
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
6264
import static org.elasticsearch.xpack.core.ClientHelper.stashWithOrigin;
6365
import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME;
64-
import static org.elasticsearch.xpack.security.SecurityLifecycleService.isIndexDeleted;
65-
import static org.elasticsearch.xpack.security.SecurityLifecycleService.isMoveFromRedToNonRed;
66+
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isIndexDeleted;
67+
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isMoveFromRedToNonRed;
6668

6769
/**
6870
* This store reads + writes {@link ExpressionRoleMapping role mappings} in an Elasticsearch
@@ -316,17 +318,13 @@ private void reportStats(ActionListener<Map<String, Object>> listener, List<Expr
316318
listener.onResponse(usageStats);
317319
}
318320

319-
public void onSecurityIndexHealthChange(ClusterIndexHealth previousHealth, ClusterIndexHealth currentHealth) {
320-
if (isMoveFromRedToNonRed(previousHealth, currentHealth) || isIndexDeleted(previousHealth, currentHealth)) {
321+
public void onSecurityIndexStateChange(SecurityIndexManager.State previousState, SecurityIndexManager.State currentState) {
322+
if (isMoveFromRedToNonRed(previousState, currentState) || isIndexDeleted(previousState, currentState) ||
323+
previousState.isIndexUpToDate != currentState.isIndexUpToDate) {
321324
refreshRealms(NO_OP_ACTION_LISTENER, null);
322325
}
323326
}
324327

325-
public void onSecurityIndexOutOfDateChange(boolean prevOutOfDate, boolean outOfDate) {
326-
assert prevOutOfDate != outOfDate : "this method should only be called if the two values are different";
327-
refreshRealms(NO_OP_ACTION_LISTENER, null);
328-
}
329-
330328
private <Result> void refreshRealms(ActionListener<Result> listener, Result result) {
331329
String[] realmNames = this.realmsToRefresh.toArray(new String[realmsToRefresh.size()]);
332330
final SecurityClient securityClient = new SecurityClient(client);

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStore.java

+7-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import org.apache.logging.log4j.message.ParameterizedMessage;
99
import org.elasticsearch.action.ActionListener;
10+
import org.elasticsearch.cluster.health.ClusterHealthStatus;
1011
import org.elasticsearch.cluster.health.ClusterIndexHealth;
1112
import org.elasticsearch.common.Nullable;
1213
import org.elasticsearch.common.Strings;
@@ -34,6 +35,7 @@
3435
import org.elasticsearch.xpack.core.security.authz.privilege.Privilege;
3536
import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore;
3637
import org.elasticsearch.xpack.security.SecurityLifecycleService;
38+
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
3739

3840
import java.util.ArrayList;
3941
import java.util.Arrays;
@@ -53,8 +55,8 @@
5355
import java.util.stream.Collectors;
5456

5557
import static org.elasticsearch.xpack.core.security.SecurityField.setting;
56-
import static org.elasticsearch.xpack.security.SecurityLifecycleService.isIndexDeleted;
57-
import static org.elasticsearch.xpack.security.SecurityLifecycleService.isMoveFromRedToNonRed;
58+
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isIndexDeleted;
59+
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isMoveFromRedToNonRed;
5860

5961
/**
6062
* A composite roles store that combines built in roles, file-based roles, and index-based roles. Checks the built in roles first, then the
@@ -323,17 +325,13 @@ public void usageStats(ActionListener<Map<String, Object>> listener) {
323325
}, listener::onFailure));
324326
}
325327

326-
public void onSecurityIndexHealthChange(ClusterIndexHealth previousHealth, ClusterIndexHealth currentHealth) {
327-
if (isMoveFromRedToNonRed(previousHealth, currentHealth) || isIndexDeleted(previousHealth, currentHealth)) {
328+
public void onSecurityIndexStateChange(SecurityIndexManager.State previousState, SecurityIndexManager.State currentState) {
329+
if (isMoveFromRedToNonRed(previousState, currentState) || isIndexDeleted(previousState, currentState) ||
330+
previousState.isIndexUpToDate != currentState.isIndexUpToDate) {
328331
invalidateAll();
329332
}
330333
}
331334

332-
public void onSecurityIndexOutOfDateChange(boolean prevOutOfDate, boolean outOfDate) {
333-
assert prevOutOfDate != outOfDate : "this method should only be called if the two values are different";
334-
invalidateAll();
335-
}
336-
337335
/**
338336
* A mutable class that can be used to represent the combination of one or more {@link IndicesPrivileges}
339337
*/

0 commit comments

Comments
 (0)