[Backport] Initialize document subset bit set cache used for DLS (#46211) (#46359)

This commit initializes DocumentSubsetBitsetCache even if DLS
is disabled. Previously it would throw null pointer when querying
usage stats if we explicitly disabled DLS as there would be no instance of DocumentSubsetBitsetCache to query. It is okay to initialize
DocumentSubsetBitsetCache which will be empty as the license enforcement
would prevent usage of DLS feature and it will not fail when accessing usage stats.

Closes #45147
This commit is contained in:
Yogesh Gaikwad 2019-09-05 14:34:19 +10:00 committed by GitHub
parent 03ed18a010
commit d5acb15a71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 35 deletions

View File

@ -406,10 +406,6 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
securityContext.set(new SecurityContext(settings, threadPool.getThreadContext())); securityContext.set(new SecurityContext(settings, threadPool.getThreadContext()));
components.add(securityContext.get()); components.add(securityContext.get());
if (XPackSettings.DLS_FLS_ENABLED.get(settings)) {
dlsBitsetCache.set(new DocumentSubsetBitsetCache(settings));
}
// audit trail service construction // audit trail service construction
final List<AuditTrail> auditTrails = XPackSettings.AUDIT_ENABLED.get(settings) final List<AuditTrail> auditTrails = XPackSettings.AUDIT_ENABLED.get(settings)
? Collections.singletonList(new LoggingAuditTrail(settings, clusterService, threadPool)) ? Collections.singletonList(new LoggingAuditTrail(settings, clusterService, threadPool))
@ -453,6 +449,7 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
final NativePrivilegeStore privilegeStore = new NativePrivilegeStore(settings, client, securityIndex.get()); final NativePrivilegeStore privilegeStore = new NativePrivilegeStore(settings, client, securityIndex.get());
components.add(privilegeStore); components.add(privilegeStore);
dlsBitsetCache.set(new DocumentSubsetBitsetCache(settings));
final FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(settings); final FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(settings);
final FileRolesStore fileRolesStore = new FileRolesStore(settings, env, resourceWatcherService, getLicenseState()); final FileRolesStore fileRolesStore = new FileRolesStore(settings, env, resourceWatcherService, getLicenseState());
final NativeRolesStore nativeRolesStore = new NativeRolesStore(settings, client, getLicenseState(), securityIndex.get()); final NativeRolesStore nativeRolesStore = new NativeRolesStore(settings, client, getLicenseState(), securityIndex.get());

View File

@ -106,17 +106,17 @@ public class CompositeRolesStore {
ReservedRolesStore reservedRolesStore, NativePrivilegeStore privilegeStore, ReservedRolesStore reservedRolesStore, NativePrivilegeStore privilegeStore,
List<BiConsumer<Set<String>, ActionListener<RoleRetrievalResult>>> rolesProviders, List<BiConsumer<Set<String>, ActionListener<RoleRetrievalResult>>> rolesProviders,
ThreadContext threadContext, XPackLicenseState licenseState, FieldPermissionsCache fieldPermissionsCache, ThreadContext threadContext, XPackLicenseState licenseState, FieldPermissionsCache fieldPermissionsCache,
ApiKeyService apiKeyService, @Nullable DocumentSubsetBitsetCache dlsBitsetCache, ApiKeyService apiKeyService, DocumentSubsetBitsetCache dlsBitsetCache,
Consumer<Collection<RoleDescriptor>> effectiveRoleDescriptorsConsumer) { Consumer<Collection<RoleDescriptor>> effectiveRoleDescriptorsConsumer) {
this.fileRolesStore = fileRolesStore; this.fileRolesStore = Objects.requireNonNull(fileRolesStore);
this.dlsBitsetCache = dlsBitsetCache; this.dlsBitsetCache = Objects.requireNonNull(dlsBitsetCache);
fileRolesStore.addListener(this::invalidate); fileRolesStore.addListener(this::invalidate);
this.nativeRolesStore = nativeRolesStore; this.nativeRolesStore = Objects.requireNonNull(nativeRolesStore);
this.privilegeStore = privilegeStore; this.privilegeStore = Objects.requireNonNull(privilegeStore);
this.licenseState = licenseState; this.licenseState = Objects.requireNonNull(licenseState);
this.fieldPermissionsCache = fieldPermissionsCache; this.fieldPermissionsCache = Objects.requireNonNull(fieldPermissionsCache);
this.apiKeyService = apiKeyService; this.apiKeyService = Objects.requireNonNull(apiKeyService);
this.effectiveRoleDescriptorsConsumer = effectiveRoleDescriptorsConsumer; this.effectiveRoleDescriptorsConsumer = Objects.requireNonNull(effectiveRoleDescriptorsConsumer);
CacheBuilder<RoleKey, Role> builder = CacheBuilder.builder(); CacheBuilder<RoleKey, Role> builder = CacheBuilder.builder();
final int cacheSize = CACHE_SIZE_SETTING.get(settings); final int cacheSize = CACHE_SIZE_SETTING.get(settings);
if (cacheSize >= 0) { if (cacheSize >= 0) {
@ -415,10 +415,8 @@ public class CompositeRolesStore {
try (ReleasableLock ignored = roleCacheHelper.acquireUpdateLock()) { try (ReleasableLock ignored = roleCacheHelper.acquireUpdateLock()) {
roleCache.invalidateAll(); roleCache.invalidateAll();
} }
if (dlsBitsetCache != null) {
dlsBitsetCache.clear("role store invalidation"); dlsBitsetCache.clear("role store invalidation");
} }
}
public void invalidate(String role) { public void invalidate(String role) {
numInvalidation.incrementAndGet(); numInvalidation.incrementAndGet();

View File

@ -38,6 +38,7 @@ import org.elasticsearch.xpack.core.security.authc.Authentication.Authentication
import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef; import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef;
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges;
import org.elasticsearch.xpack.core.security.authz.accesscontrol.DocumentSubsetBitsetCache;
import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl;
import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission; import org.elasticsearch.xpack.core.security.authz.permission.ClusterPermission;
import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissionsCache; import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissionsCache;
@ -65,6 +66,7 @@ import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -151,9 +153,10 @@ public class CompositeRolesStoreTests extends ESTestCase {
when(fileRolesStore.roleDescriptors(Collections.singleton("fls_dls"))).thenReturn(Collections.singleton(flsDlsRole)); when(fileRolesStore.roleDescriptors(Collections.singleton("fls_dls"))).thenReturn(Collections.singleton(flsDlsRole));
when(fileRolesStore.roleDescriptors(Collections.singleton("no_fls_dls"))).thenReturn(Collections.singleton(noFlsDlsRole)); when(fileRolesStore.roleDescriptors(Collections.singleton("no_fls_dls"))).thenReturn(Collections.singleton(noFlsDlsRole));
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
CompositeRolesStore compositeRolesStore = new CompositeRolesStore(Settings.EMPTY, fileRolesStore, nativeRolesStore, CompositeRolesStore compositeRolesStore = new CompositeRolesStore(Settings.EMPTY, fileRolesStore, nativeRolesStore,
reservedRolesStore, mock(NativePrivilegeStore.class), Collections.emptyList(), reservedRolesStore, mock(NativePrivilegeStore.class), Collections.emptyList(),
new ThreadContext(Settings.EMPTY), licenseState, cache, mock(ApiKeyService.class), null, new ThreadContext(Settings.EMPTY), licenseState, cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
rds -> effectiveRoleDescriptors.set(rds)); rds -> effectiveRoleDescriptors.set(rds));
PlainActionFuture<Role> roleFuture = new PlainActionFuture<>(); PlainActionFuture<Role> roleFuture = new PlainActionFuture<>();
@ -226,9 +229,10 @@ public class CompositeRolesStoreTests extends ESTestCase {
when(fileRolesStore.roleDescriptors(Collections.singleton("fls_dls"))).thenReturn(Collections.singleton(flsDlsRole)); when(fileRolesStore.roleDescriptors(Collections.singleton("fls_dls"))).thenReturn(Collections.singleton(flsDlsRole));
when(fileRolesStore.roleDescriptors(Collections.singleton("no_fls_dls"))).thenReturn(Collections.singleton(noFlsDlsRole)); when(fileRolesStore.roleDescriptors(Collections.singleton("no_fls_dls"))).thenReturn(Collections.singleton(noFlsDlsRole));
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
CompositeRolesStore compositeRolesStore = new CompositeRolesStore(Settings.EMPTY, fileRolesStore, nativeRolesStore, CompositeRolesStore compositeRolesStore = new CompositeRolesStore(Settings.EMPTY, fileRolesStore, nativeRolesStore,
reservedRolesStore, mock(NativePrivilegeStore.class), Collections.emptyList(), reservedRolesStore, mock(NativePrivilegeStore.class), Collections.emptyList(),
new ThreadContext(Settings.EMPTY), licenseState, cache, mock(ApiKeyService.class), null, new ThreadContext(Settings.EMPTY), licenseState, cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
rds -> effectiveRoleDescriptors.set(rds)); rds -> effectiveRoleDescriptors.set(rds));
PlainActionFuture<Role> roleFuture = new PlainActionFuture<>(); PlainActionFuture<Role> roleFuture = new PlainActionFuture<>();
@ -277,11 +281,12 @@ public class CompositeRolesStoreTests extends ESTestCase {
}).when(nativePrivilegeStore).getPrivileges(isA(Set.class), isA(Set.class), any(ActionListener.class)); }).when(nativePrivilegeStore).getPrivileges(isA(Set.class), isA(Set.class), any(ActionListener.class));
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
nativePrivilegeStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS), nativePrivilegeStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), null, new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class),
rds -> effectiveRoleDescriptors.set(rds)); documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds));
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
final String roleName = randomAlphaOfLengthBetween(1, 10); final String roleName = randomAlphaOfLengthBetween(1, 10);
@ -339,9 +344,11 @@ public class CompositeRolesStoreTests extends ESTestCase {
.put("xpack.security.authz.store.roles.negative_lookup_cache.max_size", 0) .put("xpack.security.authz.store.roles.negative_lookup_cache.max_size", 0)
.build(); .build();
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final CompositeRolesStore compositeRolesStore = new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore, final CompositeRolesStore compositeRolesStore = new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore,
reservedRolesStore, mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(settings), reservedRolesStore, mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(settings),
new XPackLicenseState(settings), cache, mock(ApiKeyService.class), null, rds -> effectiveRoleDescriptors.set(rds)); new XPackLicenseState(settings), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
rds -> effectiveRoleDescriptors.set(rds));
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
final String roleName = randomAlphaOfLengthBetween(1, 10); final String roleName = randomAlphaOfLengthBetween(1, 10);
@ -375,10 +382,11 @@ public class CompositeRolesStoreTests extends ESTestCase {
final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore()); final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore());
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS), mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), null, new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
rds -> effectiveRoleDescriptors.set(rds)); rds -> effectiveRoleDescriptors.set(rds));
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
@ -460,11 +468,13 @@ public class CompositeRolesStoreTests extends ESTestCase {
})); }));
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Arrays.asList(inMemoryProvider1, inMemoryProvider2), mock(NativePrivilegeStore.class), Arrays.asList(inMemoryProvider1, inMemoryProvider2),
new ThreadContext(SECURITY_ENABLED_SETTINGS), new XPackLicenseState(SECURITY_ENABLED_SETTINGS), new ThreadContext(SECURITY_ENABLED_SETTINGS), new XPackLicenseState(SECURITY_ENABLED_SETTINGS),
cache, mock(ApiKeyService.class), null, rds -> effectiveRoleDescriptors.set(rds)); cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
rds -> effectiveRoleDescriptors.set(rds));
final Set<String> roleNames = Sets.newHashSet("roleA", "roleB", "unknown"); final Set<String> roleNames = Sets.newHashSet("roleA", "roleB", "unknown");
PlainActionFuture<Role> future = new PlainActionFuture<>(); PlainActionFuture<Role> future = new PlainActionFuture<>();
@ -687,11 +697,12 @@ public class CompositeRolesStoreTests extends ESTestCase {
(roles, listener) -> listener.onFailure(new Exception("fake failure")); (roles, listener) -> listener.onFailure(new Exception("fake failure"));
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Arrays.asList(inMemoryProvider1, failingProvider), mock(NativePrivilegeStore.class), Arrays.asList(inMemoryProvider1, failingProvider),
new ThreadContext(SECURITY_ENABLED_SETTINGS), new XPackLicenseState(SECURITY_ENABLED_SETTINGS), new ThreadContext(SECURITY_ENABLED_SETTINGS), new XPackLicenseState(SECURITY_ENABLED_SETTINGS),
cache, mock(ApiKeyService.class), null, rds -> effectiveRoleDescriptors.set(rds)); cache, mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds));
final Set<String> roleNames = Sets.newHashSet("roleA", "roleB", "unknown"); final Set<String> roleNames = Sets.newHashSet("roleA", "roleB", "unknown");
PlainActionFuture<Role> future = new PlainActionFuture<>(); PlainActionFuture<Role> future = new PlainActionFuture<>();
@ -734,10 +745,11 @@ public class CompositeRolesStoreTests extends ESTestCase {
// these licenses don't allow custom role providers // these licenses don't allow custom role providers
xPackLicenseState.update(randomFrom(OperationMode.BASIC, OperationMode.GOLD, OperationMode.STANDARD), true, null); xPackLicenseState.update(randomFrom(OperationMode.BASIC, OperationMode.GOLD, OperationMode.STANDARD), true, null);
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
CompositeRolesStore compositeRolesStore = new CompositeRolesStore( CompositeRolesStore compositeRolesStore = new CompositeRolesStore(
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(NativePrivilegeStore.class), Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(NativePrivilegeStore.class),
Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache, Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache,
mock(ApiKeyService.class), null, rds -> effectiveRoleDescriptors.set(rds)); mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds));
Set<String> roleNames = Sets.newHashSet("roleA"); Set<String> roleNames = Sets.newHashSet("roleA");
PlainActionFuture<Role> future = new PlainActionFuture<>(); PlainActionFuture<Role> future = new PlainActionFuture<>();
@ -752,7 +764,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
compositeRolesStore = new CompositeRolesStore( compositeRolesStore = new CompositeRolesStore(
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(NativePrivilegeStore.class), Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(NativePrivilegeStore.class),
Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache, Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache,
mock(ApiKeyService.class), null, rds -> effectiveRoleDescriptors.set(rds)); mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds));
// these licenses allow custom role providers // these licenses allow custom role providers
xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), true, null); xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), true, null);
roleNames = Sets.newHashSet("roleA"); roleNames = Sets.newHashSet("roleA");
@ -769,7 +781,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
compositeRolesStore = new CompositeRolesStore( compositeRolesStore = new CompositeRolesStore(
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(NativePrivilegeStore.class), Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(NativePrivilegeStore.class),
Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache, Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache,
mock(ApiKeyService.class), null, rds -> effectiveRoleDescriptors.set(rds)); mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds));
xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), false, null); xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), false, null);
roleNames = Sets.newHashSet("roleA"); roleNames = Sets.newHashSet("roleA");
future = new PlainActionFuture<>(); future = new PlainActionFuture<>();
@ -797,10 +809,12 @@ public class CompositeRolesStoreTests extends ESTestCase {
doCallRealMethod().when(reservedRolesStore).accept(any(Set.class), any(ActionListener.class)); doCallRealMethod().when(reservedRolesStore).accept(any(Set.class), any(ActionListener.class));
NativeRolesStore nativeRolesStore = mock(NativeRolesStore.class); NativeRolesStore nativeRolesStore = mock(NativeRolesStore.class);
doCallRealMethod().when(nativeRolesStore).accept(any(Set.class), any(ActionListener.class)); doCallRealMethod().when(nativeRolesStore).accept(any(Set.class), any(ActionListener.class));
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
CompositeRolesStore compositeRolesStore = new CompositeRolesStore( CompositeRolesStore compositeRolesStore = new CompositeRolesStore(
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(Settings.EMPTY), mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(Settings.EMPTY),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), null, rds -> {}) { new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
rds -> {}) {
@Override @Override
public void invalidateAll() { public void invalidateAll() {
numInvalidation.incrementAndGet(); numInvalidation.incrementAndGet();
@ -849,10 +863,12 @@ public class CompositeRolesStoreTests extends ESTestCase {
doCallRealMethod().when(reservedRolesStore).accept(any(Set.class), any(ActionListener.class)); doCallRealMethod().when(reservedRolesStore).accept(any(Set.class), any(ActionListener.class));
NativeRolesStore nativeRolesStore = mock(NativeRolesStore.class); NativeRolesStore nativeRolesStore = mock(NativeRolesStore.class);
doCallRealMethod().when(nativeRolesStore).accept(any(Set.class), any(ActionListener.class)); doCallRealMethod().when(nativeRolesStore).accept(any(Set.class), any(ActionListener.class));
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
CompositeRolesStore compositeRolesStore = new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, CompositeRolesStore compositeRolesStore = new CompositeRolesStore(SECURITY_ENABLED_SETTINGS,
fileRolesStore, nativeRolesStore, reservedRolesStore, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS), mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), null, rds -> {}) { new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class),
documentSubsetBitsetCache, rds -> {}) {
@Override @Override
public void invalidateAll() { public void invalidateAll() {
numInvalidation.incrementAndGet(); numInvalidation.incrementAndGet();
@ -879,10 +895,12 @@ public class CompositeRolesStoreTests extends ESTestCase {
}).when(nativeRolesStore).getRoleDescriptors(isA(Set.class), any(ActionListener.class)); }).when(nativeRolesStore).getRoleDescriptors(isA(Set.class), any(ActionListener.class));
final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore()); final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore());
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS), mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), null, rds -> {}); new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
rds -> {});
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
PlainActionFuture<Role> rolesFuture = new PlainActionFuture<>(); PlainActionFuture<Role> rolesFuture = new PlainActionFuture<>();
@ -918,10 +936,11 @@ public class CompositeRolesStoreTests extends ESTestCase {
}).when(nativeRolesStore).getRoleDescriptors(isA(Set.class), any(ActionListener.class)); }).when(nativeRolesStore).getRoleDescriptors(isA(Set.class), any(ActionListener.class));
final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore()); final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore());
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(settings), mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(settings),
new XPackLicenseState(settings), cache, mock(ApiKeyService.class), null, rds -> {}); new XPackLicenseState(settings), cache, mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> {});
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
PlainActionFuture<Role> rolesFuture = new PlainActionFuture<>(); PlainActionFuture<Role> rolesFuture = new PlainActionFuture<>();
@ -945,11 +964,12 @@ public class CompositeRolesStoreTests extends ESTestCase {
}).when(nativeRolesStore).getRoleDescriptors(isA(Set.class), any(ActionListener.class)); }).when(nativeRolesStore).getRoleDescriptors(isA(Set.class), any(ActionListener.class));
final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore()); final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore());
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS), mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), null, new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
rds -> effectiveRoleDescriptors.set(rds)); rds -> effectiveRoleDescriptors.set(rds));
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
@ -975,11 +995,12 @@ public class CompositeRolesStoreTests extends ESTestCase {
}).when(nativeRolesStore).getRoleDescriptors(isA(Set.class), any(ActionListener.class)); }).when(nativeRolesStore).getRoleDescriptors(isA(Set.class), any(ActionListener.class));
final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore()); final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore());
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS), mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), null, new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
rds -> effectiveRoleDescriptors.set(rds)); rds -> effectiveRoleDescriptors.set(rds));
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
@ -1010,11 +1031,12 @@ public class CompositeRolesStoreTests extends ESTestCase {
return Void.TYPE; return Void.TYPE;
}).when(nativePrivStore).getPrivileges(any(Collection.class), any(Collection.class), any(ActionListener.class)); }).when(nativePrivStore).getPrivileges(any(Collection.class), any(Collection.class), any(ActionListener.class));
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
nativePrivStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS), nativePrivStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, apiKeyService, null, new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, apiKeyService, documentSubsetBitsetCache,
rds -> effectiveRoleDescriptors.set(rds)); rds -> effectiveRoleDescriptors.set(rds));
AuditUtil.getOrGenerateRequestId(threadContext); AuditUtil.getOrGenerateRequestId(threadContext);
final Authentication authentication = new Authentication(new User("test api key user", "superuser"), final Authentication authentication = new Authentication(new User("test api key user", "superuser"),
@ -1055,11 +1077,12 @@ public class CompositeRolesStoreTests extends ESTestCase {
return Void.TYPE; return Void.TYPE;
}).when(nativePrivStore).getPrivileges(any(Collection.class), any(Collection.class), any(ActionListener.class)); }).when(nativePrivStore).getPrivileges(any(Collection.class), any(Collection.class), any(ActionListener.class));
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>(); final AtomicReference<Collection<RoleDescriptor>> effectiveRoleDescriptors = new AtomicReference<Collection<RoleDescriptor>>();
final CompositeRolesStore compositeRolesStore = final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore, new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
nativePrivStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS), nativePrivStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, apiKeyService, null, new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, apiKeyService, documentSubsetBitsetCache,
rds -> effectiveRoleDescriptors.set(rds)); rds -> effectiveRoleDescriptors.set(rds));
AuditUtil.getOrGenerateRequestId(threadContext); AuditUtil.getOrGenerateRequestId(threadContext);
final Authentication authentication = new Authentication(new User("test api key user", "api_key"), final Authentication authentication = new Authentication(new User("test api key user", "api_key"),
@ -1081,6 +1104,39 @@ public class CompositeRolesStoreTests extends ESTestCase {
verify(apiKeyService).getRoleForApiKey(eq(authentication), any(ActionListener.class)); verify(apiKeyService).getRoleForApiKey(eq(authentication), any(ActionListener.class));
} }
public void testUsageStats() {
final FileRolesStore fileRolesStore = mock(FileRolesStore.class);
final Map<String, Object> fileRolesStoreUsageStats = new HashMap<>();
fileRolesStoreUsageStats.put("size", "1");
fileRolesStoreUsageStats.put("fls", Boolean.FALSE);
fileRolesStoreUsageStats.put("dls", Boolean.TRUE);
when(fileRolesStore.usageStats()).thenReturn(fileRolesStoreUsageStats);
final NativeRolesStore nativeRolesStore = mock(NativeRolesStore.class);
final Map<String, Object> nativeRolesStoreUsageStats = Collections.emptyMap();
doAnswer((invocationOnMock) -> {
ActionListener<Map<String, Object>> usageStats = (ActionListener<Map<String, Object>>) invocationOnMock.getArguments()[0];
usageStats.onResponse(nativeRolesStoreUsageStats);
return Void.TYPE;
}).when(nativeRolesStore).usageStats(any(ActionListener.class));
final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore());
final DocumentSubsetBitsetCache documentSubsetBitsetCache = new DocumentSubsetBitsetCache(Settings.EMPTY);
final CompositeRolesStore compositeRolesStore =
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> {
});
PlainActionFuture<Map<String, Object>> usageStatsListener = new PlainActionFuture<>();
compositeRolesStore.usageStats(usageStatsListener);
Map<String, Object> usageStats = usageStatsListener.actionGet();
assertThat(usageStats.get("file"), is(fileRolesStoreUsageStats));
assertThat(usageStats.get("native"), is(nativeRolesStoreUsageStats));
assertThat(usageStats.get("dls"), is(Collections.singletonMap("bit_set_cache", documentSubsetBitsetCache.usageStats())));
}
private static class InMemoryRolesProvider implements BiConsumer<Set<String>, ActionListener<RoleRetrievalResult>> { private static class InMemoryRolesProvider implements BiConsumer<Set<String>, ActionListener<RoleRetrievalResult>> {
private final Function<Set<String>, RoleRetrievalResult> roleDescriptorsFunc; private final Function<Set<String>, RoleRetrievalResult> roleDescriptorsFunc;