Skip to content

Commit

Permalink
Security: Rename IndexLifecycleManager to SecurityIndexManager (#30442)
Browse files Browse the repository at this point in the history
This commit renames IndexLifecycleManager to SecurityIndexManager as it
is not actually a general purpose class, but specific to security. It
also removes indirection in code calling the lifecycle service, instead
calling the security index manager directly.
  • Loading branch information
rjernst committed May 8, 2018
1 parent 3aead66 commit 1712f09
Show file tree
Hide file tree
Showing 27 changed files with 166 additions and 203 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@
import org.elasticsearch.xpack.security.rest.action.user.RestHasPrivilegesAction;
import org.elasticsearch.xpack.security.rest.action.user.RestPutUserAction;
import org.elasticsearch.xpack.security.rest.action.user.RestSetEnabledAction;
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.elasticsearch.xpack.security.transport.netty4.SecurityNetty4HttpServerTransport;
Expand Down Expand Up @@ -236,7 +236,7 @@
import static org.elasticsearch.xpack.core.XPackSettings.HTTP_SSL_ENABLED;
import static org.elasticsearch.xpack.core.security.SecurityLifecycleServiceField.SECURITY_INDEX_NAME;
import static org.elasticsearch.xpack.core.security.SecurityLifecycleServiceField.SECURITY_TEMPLATE_NAME;
import static org.elasticsearch.xpack.security.support.IndexLifecycleManager.INTERNAL_INDEX_FORMAT;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT;

public class Security extends Plugin implements ActionPlugin, IngestPlugin, NetworkPlugin, ClusterPlugin, DiscoveryPlugin, MapperPlugin,
ExtensiblePlugin {
Expand Down Expand Up @@ -442,8 +442,8 @@ Collection<Object> createComponents(Client client, ThreadPool threadPool, Cluste
components.add(realms);
components.add(reservedRealm);

securityLifecycleService.addSecurityIndexHealthChangeListener(nativeRoleMappingStore::onSecurityIndexHealthChange);
securityLifecycleService.addSecurityIndexOutOfDateListener(nativeRoleMappingStore::onSecurityIndexOutOfDateChange);
securityLifecycleService.securityIndex().addIndexHealthChangeListener(nativeRoleMappingStore::onSecurityIndexHealthChange);
securityLifecycleService.securityIndex().addIndexOutOfDateListener(nativeRoleMappingStore::onSecurityIndexOutOfDateChange);

AuthenticationFailureHandler failureHandler = null;
String extensionName = null;
Expand Down Expand Up @@ -474,9 +474,9 @@ Collection<Object> createComponents(Client client, ThreadPool threadPool, Cluste
rolesProviders.addAll(extension.getRolesProviders(settings, resourceWatcherService));
}
final CompositeRolesStore allRolesStore = new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore,
reservedRolesStore, rolesProviders, threadPool.getThreadContext(), getLicenseState());
securityLifecycleService.addSecurityIndexHealthChangeListener(allRolesStore::onSecurityIndexHealthChange);
securityLifecycleService.addSecurityIndexOutOfDateListener(allRolesStore::onSecurityIndexOutOfDateChange);
reservedRolesStore, rolesProviders, threadPool.getThreadContext(), getLicenseState());
securityLifecycleService.securityIndex().addIndexHealthChangeListener(allRolesStore::onSecurityIndexHealthChange);
securityLifecycleService.securityIndex().addIndexOutOfDateListener(allRolesStore::onSecurityIndexOutOfDateChange);
// to keep things simple, just invalidate all cached entries on license change. this happens so rarely that the impact should be
// minimal
getLicenseState().addListener(allRolesStore::invalidateAll);
Expand Down Expand Up @@ -963,7 +963,7 @@ public UnaryOperator<Map<String, IndexTemplateMetaData>> getIndexTemplateMetaDat
return templates -> {
// TODO the upgrade service needs the template - need to add a way without using templates!
final byte[] securityTemplate = TemplateUtils.loadTemplate("/" + SECURITY_TEMPLATE_NAME + ".json",
Version.CURRENT.toString(), IndexLifecycleManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
Version.CURRENT.toString(), SecurityIndexManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
final XContent xContent = XContentFactory.xContent(XContentType.JSON);

try (XContentParser parser = xContent
Expand All @@ -975,7 +975,7 @@ public UnaryOperator<Map<String, IndexTemplateMetaData>> getIndexTemplateMetaDat
}

final byte[] auditTemplate = TemplateUtils.loadTemplate("/" + IndexAuditTrail.INDEX_TEMPLATE_NAME + ".json",
Version.CURRENT.toString(), IndexLifecycleManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
Version.CURRENT.toString(), SecurityIndexManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);

try (XContentParser parser = xContent
.createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, auditTemplate)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.elasticsearch.gateway.GatewayService;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
import org.elasticsearch.xpack.security.support.SecurityIndexManager;

import java.util.Arrays;
import java.util.Collections;
Expand All @@ -48,15 +48,16 @@
*/
public class SecurityLifecycleService extends AbstractComponent implements ClusterStateListener {

public static final String INTERNAL_SECURITY_INDEX = IndexLifecycleManager.INTERNAL_SECURITY_INDEX;
public static final String INTERNAL_SECURITY_INDEX = SecurityIndexManager.INTERNAL_SECURITY_INDEX;
public static final String SECURITY_INDEX_NAME = ".security";

private static final Version MIN_READ_VERSION = Version.V_5_0_0;

private final Settings settings;
private final ThreadPool threadPool;
private final IndexAuditTrail indexAuditTrail;

private final IndexLifecycleManager securityIndex;
private final SecurityIndexManager securityIndex;

public SecurityLifecycleService(Settings settings, ClusterService clusterService,
ThreadPool threadPool, Client client,
Expand All @@ -65,7 +66,7 @@ public SecurityLifecycleService(Settings settings, ClusterService clusterService
this.settings = settings;
this.threadPool = threadPool;
this.indexAuditTrail = indexAuditTrail;
this.securityIndex = new IndexLifecycleManager(settings, client, SECURITY_INDEX_NAME);
this.securityIndex = new SecurityIndexManager(settings, client, SECURITY_INDEX_NAME);
clusterService.addListener(this);
clusterService.addLifecycleListener(new LifecycleListener() {
@Override
Expand Down Expand Up @@ -111,69 +112,10 @@ public void doRun() {
}
}

IndexLifecycleManager securityIndex() {
public SecurityIndexManager securityIndex() {
return securityIndex;
}

/**
* Returns {@code true} if the security index exists
*/
public boolean isSecurityIndexExisting() {
return securityIndex.indexExists();
}

/**
* Returns <code>true</code> if the security index does not exist or it exists and has the current
* value for the <code>index.format</code> index setting
*/
public boolean isSecurityIndexUpToDate() {
return securityIndex.isIndexUpToDate();
}

/**
* Returns <code>true</code> if the security index exists and all primary shards are active
*/
public boolean isSecurityIndexAvailable() {
return securityIndex.isAvailable();
}

/**
* Returns <code>true</code> if the security index does not exist or the mappings are up to date
* based on the version in the <code>_meta</code> field
*/
public boolean isSecurityIndexMappingUpToDate() {
return securityIndex().isMappingUpToDate();
}

/**
* Test whether the effective (active) version of the security mapping meets the
* <code>requiredVersion</code>.
*
* @return <code>true</code> if the effective version passes the predicate, or the security
* mapping does not exist (<code>null</code> version). Otherwise, <code>false</code>.
*/
public boolean checkSecurityMappingVersion(Predicate<Version> requiredVersion) {
return securityIndex.checkMappingVersion(requiredVersion);
}

/**
* Adds a listener which will be notified when the security index health changes. The previous and
* current health will be provided to the listener so that the listener can determine if any action
* needs to be taken.
*/
public void addSecurityIndexHealthChangeListener(BiConsumer<ClusterIndexHealth, ClusterIndexHealth> listener) {
securityIndex.addIndexHealthChangeListener(listener);
}

/**
* Adds a listener which will be notified when the security index out of date value changes. The previous and
* current value will be provided to the listener so that the listener can determine if any action
* needs to be taken.
*/
void addSecurityIndexOutOfDateListener(BiConsumer<Boolean, Boolean> listener) {
securityIndex.addIndexOutOfDateListener(listener);
}

// this is called in a lifecycle listener beforeStop on the cluster service
private void close() {
if (indexAuditTrail != null) {
Expand All @@ -194,29 +136,13 @@ static boolean securityIndexMappingUpToDate(ClusterState clusterState, Logger lo
}

private static boolean checkMappingVersions(ClusterState clusterState, Logger logger, Predicate<Version> versionPredicate) {
return IndexLifecycleManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, versionPredicate);
return SecurityIndexManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, versionPredicate);
}

public static List<String> indexNames() {
return Collections.unmodifiableList(Arrays.asList(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX));
}

/**
* Prepares the security index by creating it if it doesn't exist or updating the mappings if the mappings are
* out of date. After any tasks have been executed, the runnable is then executed.
*/
public void prepareIndexIfNeededThenExecute(final Consumer<Exception> consumer, final Runnable andThen) {
securityIndex.prepareIndexIfNeededThenExecute(consumer, andThen);
}

/**
* Checks if the security index is out of date with the current version. If the index does not exist
* we treat the index as up to date as we expect it to be created with the current format.
*/
public boolean isSecurityIndexOutOfDate() {
return securityIndex.isIndexUpToDate() == false;
}

/**
* Is the move from {@code previousHealth} to {@code currentHealth} a move from an unhealthy ("RED") index state to a healthy
* ("non-RED") state.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
import org.elasticsearch.xpack.security.audit.AuditLevel;
import org.elasticsearch.xpack.security.audit.AuditTrail;
import org.elasticsearch.xpack.security.rest.RemoteHostHeader;
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
Expand Down Expand Up @@ -105,7 +105,7 @@
import static org.elasticsearch.xpack.security.audit.AuditUtil.indices;
import static org.elasticsearch.xpack.security.audit.AuditUtil.restRequestContent;
import static org.elasticsearch.xpack.security.audit.index.IndexNameResolver.resolve;
import static org.elasticsearch.xpack.security.support.IndexLifecycleManager.SECURITY_VERSION_STRING;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_VERSION_STRING;

/**
* Audit trail implementation that writes events into an index.
Expand Down Expand Up @@ -1001,7 +1001,7 @@ private void putTemplate(Settings customSettings, Consumer<Exception> consumer)

private PutIndexTemplateRequest getPutIndexTemplateRequest(Settings customSettings) {
final byte[] template = TemplateUtils.loadTemplate("/" + INDEX_TEMPLATE_NAME + ".json",
Version.CURRENT.toString(), IndexLifecycleManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
Version.CURRENT.toString(), SecurityIndexManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
final PutIndexTemplateRequest request = new PutIndexTemplateRequest(INDEX_TEMPLATE_NAME).source(template, XContentType.JSON);
if (customSettings != null && customSettings.names().size() > 0) {
Settings updatedSettings = Settings.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public static Map<String, Realm.Factory> getFactories(ThreadPool threadPool, Res
map.put(FileRealmSettings.TYPE, config -> new FileRealm(config, resourceWatcherService));
map.put(NativeRealmSettings.TYPE, config -> {
final NativeRealm nativeRealm = new NativeRealm(config, nativeUsersStore);
securityLifecycleService.addSecurityIndexHealthChangeListener(nativeRealm::onSecurityIndexHealthChange);
securityLifecycleService.securityIndex().addIndexHealthChangeListener(nativeRealm::onSecurityIndexHealthChange);
return nativeRealm;
});
map.put(LdapRealmSettings.AD_TYPE, config -> new LdapRealm(LdapRealmSettings.AD_TYPE, config, sslService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ public void createUserToken(Authentication authentication, Authentication origin
.setSource(builder)
.setRefreshPolicy(RefreshPolicy.WAIT_UNTIL)
.request();
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client, SECURITY_ORIGIN, IndexAction.INSTANCE, request,
ActionListener.wrap(indexResponse -> listener.onResponse(new Tuple<>(userToken, refreshToken)),
listener::onFailure))
Expand Down Expand Up @@ -370,7 +370,7 @@ void decodeToken(String token, ActionListener<UserToken> listener) throws IOExce
if (version.onOrAfter(Version.V_6_2_0)) {
// we only have the id and need to get the token from the doc!
decryptTokenId(in, cipher, version, ActionListener.wrap(tokenId ->
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
final GetRequest getRequest =
client.prepareGet(SecurityLifecycleServiceField.SECURITY_INDEX_NAME, TYPE,
getTokenDocumentId(tokenId)).request();
Expand Down Expand Up @@ -540,7 +540,7 @@ private void indexBwcInvalidation(UserToken userToken, ActionListener<Boolean> l
.request();
final String tokenDocId = getTokenDocumentId(userToken);
final Version version = userToken.getVersion();
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, indexRequest,
ActionListener.<IndexResponse>wrap(indexResponse -> {
ActionListener<Boolean> wrappedListener =
Expand Down Expand Up @@ -582,7 +582,7 @@ private void indexInvalidation(String tokenDocId, Version version, ActionListene
.setVersion(documentVersion)
.setRefreshPolicy(RefreshPolicy.WAIT_UNTIL)
.request();
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request,
ActionListener.<UpdateResponse>wrap(updateResponse -> {
if (updateResponse.getGetResult() != null
Expand Down Expand Up @@ -681,7 +681,7 @@ private void findTokenFromRefreshToken(String refreshToken, ActionListener<Tuple
.setVersion(true)
.request();

lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request,
ActionListener.<SearchResponse>wrap(searchResponse -> {
if (searchResponse.isTimedOut()) {
Expand Down Expand Up @@ -863,7 +863,7 @@ public void findActiveTokensForRealm(String realmName, ActionListener<Collection
.request();

final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () ->
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () ->
ScrollHelper.fetchAllByEntity(client, request, new ContextPreservingActionListener<>(supplier, listener), this::parseHit));
}

Expand Down Expand Up @@ -930,11 +930,11 @@ private void ensureEnabled() {
* have been explicitly cleared.
*/
private void checkIfTokenIsRevoked(UserToken userToken, ActionListener<UserToken> listener) {
if (lifecycleService.isSecurityIndexExisting() == false) {
if (lifecycleService.securityIndex().indexExists() == false) {
// index doesn't exist so the token is considered valid.
listener.onResponse(userToken);
} else {
lifecycleService.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
lifecycleService.securityIndex().prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
MultiGetRequest mGetRequest = client.prepareMultiGet()
.add(SecurityLifecycleServiceField.SECURITY_INDEX_NAME, TYPE, getInvalidatedTokenDocumentId(userToken))
.add(SecurityLifecycleServiceField.SECURITY_INDEX_NAME, TYPE, getTokenDocumentId(userToken))
Expand Down Expand Up @@ -1005,7 +1005,7 @@ private Instant getExpirationTime(Instant now) {
}

private void maybeStartTokenRemover() {
if (lifecycleService.isSecurityIndexAvailable()) {
if (lifecycleService.securityIndex().isAvailable()) {
if (client.threadPool().relativeTimeInMillis() - lastExpirationRunMs > deleteInterval.getMillis()) {
expiredTokenRemover.submit(client.threadPool());
lastExpirationRunMs = client.threadPool().relativeTimeInMillis();
Expand Down
Loading

0 comments on commit 1712f09

Please sign in to comment.