From 9ed7a240e39138f3ba572ea6b400920ff172ced8 Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Thu, 3 Jul 2025 09:52:22 -0400 Subject: [PATCH 01/12] Silence some warnings from IntelliJ --- .../authz/accesscontrol/DocumentSubsetBitsetCache.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java index 1177ff68c34c4..acc0353260442 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java @@ -55,23 +55,23 @@ /** * This is a cache for {@link BitSet} instances that are used with the {@link DocumentSubsetReader}. * It is bounded by memory size and access time. - * + *

* DLS uses {@link BitSet} instances to track which documents should be visible to the user ("live") and which should not ("dead"). * This means that there is a bit for each document in a Lucene index (ES shard). * Consequently, an index with 10 million document will use more than 1Mb of bitset memory for every unique DLS query, and an index * with 1 billion documents will use more than 100Mb of memory per DLS query. * Because DLS supports templating queries based on user metadata, there may be many distinct queries in use for each index, even if * there is only a single active role. - * + *

* The primary benefit of the cache is to avoid recalculating the "live docs" (visible documents) when a user performs multiple * consecutive queries across one or more large indices. Given the memory examples above, the cache is only useful if it can hold at * least 1 large (100Mb or more ) {@code BitSet} during a user's active session, and ideally should be capable of support multiple * simultaneous users with distinct DLS queries. - * + *

* For this reason the default memory usage (weight) for the cache set to 10% of JVM heap ({@link #CACHE_SIZE_SETTING}), so that it * automatically scales with the size of the Elasticsearch deployment, and can provide benefit to most use cases without needing * customisation. On a 32Gb heap, a 10% cache would be 3.2Gb which is large enough to store BitSets representing 25 billion docs. - * + *

* However, because queries can be templated by user metadata and that metadata can change frequently, it is common for the * effetively lifetime of a single DLS query to be relatively short. We do not want to sacrifice 10% of heap to a cache that is storing * BitSets that are not longer needed, so we set the TTL on this cache to be 2 hours ({@link #CACHE_TTL_SETTING}). This time has been From a079599167683380aaa0d454db4850dbcd699fad Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Thu, 3 Jul 2025 09:53:10 -0400 Subject: [PATCH 02/12] Silence some grammar nits from IntelliJ --- .../authz/accesscontrol/DocumentSubsetBitsetCache.java | 8 ++++---- .../authz/accesscontrol/DocumentSubsetReader.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java index acc0353260442..50f007d7e7886 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java @@ -73,8 +73,8 @@ * customisation. On a 32Gb heap, a 10% cache would be 3.2Gb which is large enough to store BitSets representing 25 billion docs. *

* However, because queries can be templated by user metadata and that metadata can change frequently, it is common for the - * effetively lifetime of a single DLS query to be relatively short. We do not want to sacrifice 10% of heap to a cache that is storing - * BitSets that are not longer needed, so we set the TTL on this cache to be 2 hours ({@link #CACHE_TTL_SETTING}). This time has been + * effective lifetime of a single DLS query to be relatively short. We do not want to sacrifice 10% of heap to a cache that is storing + * BitSets that are no longer needed, so we set the TTL on this cache to be 2 hours ({@link #CACHE_TTL_SETTING}). This time has been * chosen so that it will retain BitSets that are in active use during a user's session, but not be an ongoing drain on memory. * * @see org.elasticsearch.index.cache.bitset.BitsetFilterCache @@ -171,7 +171,7 @@ private void onCacheEviction(RemovalNotification notific } // We push this to a background thread, so that it reduces the risk of blocking searches, but also so that the lock management is // simpler - this callback is likely to take place on a thread that is actively adding something to the cache, and is therefore - // holding the read ("update") side of the lock. It is not possible to upgrade a read lock to a write ("eviction") lock, but we + // holding the read ("update") side of the lock. It is not possible to upgrade a read lock to a write lock ("eviction"), but we // need to acquire that lock here. cleanupExecutor.submit(() -> { try (ReleasableLock ignored = cacheEvictionLock.acquire()) { @@ -214,7 +214,7 @@ public long ramBytesUsed() { /** * Obtain the {@link BitSet} for the given {@code query} in the given {@code context}. * If there is a cached entry for that query and context, it will be returned. - * Otherwise a new BitSet will be created and stored in the cache. + * Otherwise, a new BitSet will be created and stored in the cache. * The returned BitSet may be null (e.g. if the query has no results). */ @Nullable diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetReader.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetReader.java index 50089309caddc..d61a2489f657e 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetReader.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetReader.java @@ -195,8 +195,8 @@ public Bits getLiveDocs() { computeNumDocsIfNeeded(); final Bits actualLiveDocs = in.getLiveDocs(); if (roleQueryBits == null) { - // If we would return a null liveDocs then that would mean that no docs are marked as deleted, - // but that isn't the case. No docs match with the role query and therefore all docs are marked as deleted + // If we were to return a null liveDocs then that would mean that no docs are marked as deleted, + // but that isn't the case. No docs match with the role query and therefore all docs are marked as deleted. return new Bits.MatchNoBits(in.maxDoc()); } else if (roleQueryBits instanceof MatchAllBitSet) { return actualLiveDocs; From bef03e52c41140c09a5241033e4f644ff2031c07 Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Thu, 3 Jul 2025 09:54:38 -0400 Subject: [PATCH 03/12] Fix a visbility nit from IntelliJ --- .../authz/accesscontrol/DocumentSubsetBitsetCache.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java index 50f007d7e7886..cb6dc8892c4fc 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java @@ -130,7 +130,8 @@ public DocumentSubsetBitsetCache(Settings settings, ThreadPool threadPool) { * @param cleanupExecutor An executor on which the cache cleanup tasks can be run. Due to the way the cache is structured internally, * it is sometimes necessary to run an asynchronous task to synchronize the internal state. */ - protected DocumentSubsetBitsetCache(Settings settings, ExecutorService cleanupExecutor) { + // visible for testing + DocumentSubsetBitsetCache(Settings settings, ExecutorService cleanupExecutor) { final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); this.cacheEvictionLock = new ReleasableLock(readWriteLock.writeLock()); this.cacheModificationLock = new ReleasableLock(readWriteLock.readLock()); From 2f6cbf8bb386dfaca1c4689ae3f1bc0fcb4022ba Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Thu, 3 Jul 2025 10:12:54 -0400 Subject: [PATCH 04/12] Rewrite this instanceof check --- .../security/authz/accesscontrol/DocumentSubsetBitsetCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java index cb6dc8892c4fc..2f3b65ce7222d 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java @@ -290,7 +290,7 @@ private static BitSet computeBitSet(Query query, LeafReaderContext context) thro // Package private for testing static boolean isEffectiveMatchAllDocsQuery(Query rewrittenQuery) { - if (rewrittenQuery instanceof ConstantScoreQuery && ((ConstantScoreQuery) rewrittenQuery).getQuery() instanceof MatchAllDocsQuery) { + if (rewrittenQuery instanceof ConstantScoreQuery csq && csq.getQuery() instanceof MatchAllDocsQuery) { return true; } if (rewrittenQuery instanceof MatchAllDocsQuery) { From 7f2ece7bbefea041c514ef24d541abf678f5dca8 Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Tue, 8 Jul 2025 11:16:54 -0400 Subject: [PATCH 05/12] Typo --- .../core/security/authz/permission/DocumentPermissions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/DocumentPermissions.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/DocumentPermissions.java index 92bb037888495..bf9e73e4518ac 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/DocumentPermissions.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/DocumentPermissions.java @@ -106,7 +106,7 @@ public boolean hasStoredScript() throws IOException { /** * Creates a {@link BooleanQuery} to be used as filter to restrict access to documents.
- * Document permission queries are used to create an boolean query.
+ * Document permission queries are used to create a boolean query.
* If the document permissions are limited, then there is an additional filter added restricting access to documents only allowed by the * limited queries. * From d58fbdd585619a4968ca165b6b635aa3ef64b210 Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Mon, 4 Aug 2025 10:39:52 -0400 Subject: [PATCH 06/12] Tidy up some collections code --- .../DocumentSubsetBitsetCacheTests.java | 7 +++--- ...ityIndexReaderWrapperIntegrationTests.java | 25 ++++++++----------- .../SecurityIndexReaderWrapperUnitTests.java | 8 +++--- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCacheTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCacheTests.java index 5369c95ad6fa7..c4f3e3ada9c01 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCacheTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCacheTests.java @@ -54,6 +54,7 @@ import java.util.Collections; import java.util.IdentityHashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -62,8 +63,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; @@ -600,7 +599,7 @@ private TestIndexContext testIndex(MappingLookup mappingLookup, Client client) t null, () -> true, null, - emptyMap(), + Map.of(), MapperMetrics.NOOP ); @@ -630,7 +629,7 @@ private void runTestOnIndices(int numberIndices, CheckedConsumer true, null, - emptyMap(), + Map.of(), MapperMetrics.NOOP ); SearchExecutionContext searchExecutionContext = spy(realSearchExecutionContext); @@ -172,7 +169,7 @@ public void testDLS() throws Exception { String termQuery = "{\"term\": {\"field\": \"" + values[i] + "\"} }"; IndicesAccessControl.IndexAccessControl indexAccessControl = new IndicesAccessControl.IndexAccessControl( FieldPermissions.DEFAULT, - DocumentPermissions.filteredBy(singleton(new BytesArray(termQuery))) + DocumentPermissions.filteredBy(Set.of(new BytesArray(termQuery))) ); SecurityIndexReaderWrapper wrapper = new SecurityIndexReaderWrapper( s -> searchExecutionContext, @@ -184,7 +181,7 @@ public void testDLS() throws Exception { @Override protected IndicesAccessControl getIndicesAccessControl() { - return new IndicesAccessControl(true, singletonMap("_index", indexAccessControl)); + return new IndicesAccessControl(true, Map.of("_index", indexAccessControl)); } }; @@ -237,9 +234,9 @@ public void testDLSWithLimitedPermissions() throws Exception { FieldPermissions.DEFAULT, DocumentPermissions.filteredBy(queries) ); - queries = singleton(new BytesArray("{\"terms\" : { \"f1\" : [\"fv11\", \"fv21\", \"fv31\"] } }")); + queries = Set.of(new BytesArray("{\"terms\" : { \"f1\" : [\"fv11\", \"fv21\", \"fv31\"] } }")); if (restrictiveLimitedIndexPermissions) { - queries = singleton(new BytesArray("{\"terms\" : { \"f1\" : [\"fv11\", \"fv31\"] } }")); + queries = Set.of(new BytesArray("{\"terms\" : { \"f1\" : [\"fv11\", \"fv31\"] } }")); } IndicesAccessControl.IndexAccessControl limitedIndexAccessControl = new IndicesAccessControl.IndexAccessControl( FieldPermissions.DEFAULT, @@ -271,7 +268,7 @@ public void testDLSWithLimitedPermissions() throws Exception { null, () -> true, null, - emptyMap(), + Map.of(), MapperMetrics.NOOP ); SearchExecutionContext searchExecutionContext = spy(realSearchExecutionContext); @@ -289,13 +286,13 @@ public void testDLSWithLimitedPermissions() throws Exception { @Override protected IndicesAccessControl getIndicesAccessControl() { - IndicesAccessControl indicesAccessControl = new IndicesAccessControl(true, singletonMap("_index", indexAccessControl)); + IndicesAccessControl indicesAccessControl = new IndicesAccessControl(true, Map.of("_index", indexAccessControl)); if (noFilteredIndexPermissions) { return indicesAccessControl; } IndicesAccessControl limitedByIndicesAccessControl = new IndicesAccessControl( true, - singletonMap("_index", limitedIndexAccessControl) + Map.of("_index", limitedIndexAccessControl) ); return indicesAccessControl.limitIndicesAccessControl(limitedByIndicesAccessControl); } @@ -494,7 +491,7 @@ public void testDLSWithNestedDocs() throws Exception { protected IndicesAccessControl getIndicesAccessControl() { IndicesAccessControl indicesAccessControl = new IndicesAccessControl( true, - singletonMap(indexSettings().getIndex().getName(), indexAccessControl) + Map.of(indexSettings().getIndex().getName(), indexAccessControl) ); return indicesAccessControl; } @@ -522,6 +519,6 @@ protected IndicesAccessControl getIndicesAccessControl() { private static MappingLookup createMappingLookup(List concreteFields) { List mappers = concreteFields.stream().map(MockFieldMapper::new).collect(Collectors.toList()); - return MappingLookup.fromMappers(Mapping.EMPTY, mappers, emptyList()); + return MappingLookup.fromMappers(Mapping.EMPTY, mappers, List.of()); } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperUnitTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperUnitTests.java index 104f6f2847ab0..a109f5f347a6f 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperUnitTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperUnitTests.java @@ -30,12 +30,12 @@ import org.junit.After; import org.junit.Before; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; -import static java.util.Collections.singletonMap; import static org.elasticsearch.xpack.core.security.SecurityField.DOCUMENT_LEVEL_SECURITY_FEATURE; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.sameInstance; @@ -93,7 +93,7 @@ protected IndicesAccessControl getIndicesAccessControl() { new FieldPermissions(fieldPermissionDef(new String[] {}, null)), DocumentPermissions.allowAll() ); - return new IndicesAccessControl(true, singletonMap("_index", indexAccessControl)); + return new IndicesAccessControl(true, Map.of("_index", indexAccessControl)); } }; @@ -166,7 +166,7 @@ public void testFieldPermissionsWithFieldExceptions() throws Exception { deniedFields = META_FIELDS.toArray(new String[0]); assertResolved( new FieldPermissions(fieldPermissionDef(null, deniedFields)), - new HashSet<>(Arrays.asList("foo", "bar", "_some_plugin_meta_field")) + new HashSet<>(List.of("foo", "bar", "_some_plugin_meta_field")) ); // check we can add all fields with * From 6b5aec1c6962b469be9be048c40e6ea04e82ce23 Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Mon, 4 Aug 2025 10:46:44 -0400 Subject: [PATCH 07/12] This test class can be a record --- .../DocumentSubsetBitsetCacheTests.java | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCacheTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCacheTests.java index c4f3e3ada9c01..0645ea8b43b16 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCacheTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCacheTests.java @@ -524,26 +524,13 @@ private void runTestOnIndex(CheckedBiConsumer Date: Mon, 4 Aug 2025 10:46:59 -0400 Subject: [PATCH 08/12] Silence some warnings from IntelliJ --- .../SecurityIndexReaderWrapperIntegrationTests.java | 6 +----- .../SecurityIndexReaderWrapperUnitTests.java | 10 +++++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperIntegrationTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperIntegrationTests.java index 25e929edb4101..6b07654467d0d 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperIntegrationTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperIntegrationTests.java @@ -489,11 +489,7 @@ public void testDLSWithNestedDocs() throws Exception { @Override protected IndicesAccessControl getIndicesAccessControl() { - IndicesAccessControl indicesAccessControl = new IndicesAccessControl( - true, - Map.of(indexSettings().getIndex().getName(), indexAccessControl) - ); - return indicesAccessControl; + return new IndicesAccessControl(true, Map.of(indexSettings().getIndex().getName(), indexAccessControl)); } }; diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperUnitTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperUnitTests.java index a109f5f347a6f..5ac21a4c126ba 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperUnitTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperUnitTests.java @@ -85,7 +85,7 @@ public void tearDown() throws Exception { esIn.close(); } - public void testDefaultMetaFields() throws Exception { + public void testDefaultMetaFields() { securityIndexReaderWrapper = new SecurityIndexReaderWrapper(null, null, securityContext, licenseState, scriptService) { @Override protected IndicesAccessControl getIndicesAccessControl() { @@ -115,14 +115,14 @@ protected IndicesAccessControl getIndicesAccessControl() { assertThat(result.getFilter().run("some_random_regular_field"), is(false)); } - public void testWrapReaderWhenFeatureDisabled() throws Exception { + public void testWrapReaderWhenFeatureDisabled() { when(licenseState.isAllowed(DOCUMENT_LEVEL_SECURITY_FEATURE)).thenReturn(false); securityIndexReaderWrapper = new SecurityIndexReaderWrapper(null, null, securityContext, licenseState, scriptService); DirectoryReader reader = securityIndexReaderWrapper.apply(esIn); assertThat(reader, sameInstance(esIn)); } - public void testWildcards() throws Exception { + public void testWildcards() { Set expected = new HashSet<>(META_FIELDS); expected.add("field1_a"); expected.add("field1_b"); @@ -130,7 +130,7 @@ public void testWildcards() throws Exception { assertResolved(new FieldPermissions(fieldPermissionDef(new String[] { "field1*" }, null)), expected, "field", "field2"); } - public void testDotNotion() throws Exception { + public void testDotNotion() { Set expected = new HashSet<>(META_FIELDS); expected.add("foo.bar"); assertResolved(new FieldPermissions(fieldPermissionDef(new String[] { "foo.bar" }, null)), expected, "foo", "foo.baz", "bar.foo"); @@ -149,7 +149,7 @@ private void assertResolved(FieldPermissions permissions, Set expected, } } - public void testFieldPermissionsWithFieldExceptions() throws Exception { + public void testFieldPermissionsWithFieldExceptions() { securityIndexReaderWrapper = new SecurityIndexReaderWrapper(null, null, securityContext, licenseState, null); String[] grantedFields = new String[] {}; String[] deniedFields; From 1145674a17ec47321c7514c0f6b6e2011e274205 Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Mon, 4 Aug 2025 10:47:31 -0400 Subject: [PATCH 09/12] Fix a minor test buglet --- .../SecurityIndexReaderWrapperIntegrationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperIntegrationTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperIntegrationTests.java index 6b07654467d0d..8461daeef5d8c 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperIntegrationTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapperIntegrationTests.java @@ -151,7 +151,7 @@ public void testDLS() throws Exception { if (doc % 11 == 0) { iw.deleteDocuments(new Term("id", id)); } else { - if (commitAfter % commitAfter == 0) { + if (doc % commitAfter == 0) { iw.commit(); } valuesHitCount[valueIndex]++; From 502dd3cc918a23055e9fe482a17a0580a08f9851 Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Fri, 1 Aug 2025 16:06:23 -0400 Subject: [PATCH 10/12] Move this logger definition --- .../authz/accesscontrol/DocumentSubsetBitsetCache.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java index 2f3b65ce7222d..d2dd6d63a3376 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java @@ -81,6 +81,8 @@ */ public final class DocumentSubsetBitsetCache implements IndexReader.ClosedListener, Closeable, Accountable { + private static final Logger logger = LogManager.getLogger(DocumentSubsetBitsetCache.class); + /** * The TTL defaults to 2 hours. We default to a large cache size ({@link #CACHE_SIZE_SETTING}), and aggressively * expire unused entries so that the cache does not hold on to memory unnecessarily. @@ -102,8 +104,6 @@ public final class DocumentSubsetBitsetCache implements IndexReader.ClosedListen private static final BitSet NULL_MARKER = new FixedBitSet(0); - private static final Logger logger = LogManager.getLogger(DocumentSubsetBitsetCache.class); - /** * When a {@link BitSet} is evicted from {@link #bitsetCache}, we need to also remove it from {@link #keysByIndex}. * We use a {@link ReentrantReadWriteLock} to control atomicity here - the "read" side represents potential insertions to the From c5df0eeed4f818f0bc5a8a4eaa94659352e61c15 Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Fri, 1 Aug 2025 16:10:00 -0400 Subject: [PATCH 11/12] Whitespace --- .../security/authz/accesscontrol/DocumentSubsetBitsetCache.java | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java index d2dd6d63a3376..f809a0fc00a28 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java @@ -324,6 +324,7 @@ public Map usageStats() { } private static class BitsetCacheKey { + final IndexReader.CacheKey index; final Query query; From 662ab62ceada862ecc795e71e9af1e76df4c03a0 Mon Sep 17 00:00:00 2001 From: Joe Gallo Date: Fri, 1 Aug 2025 16:10:16 -0400 Subject: [PATCH 12/12] Mark this class final --- .../security/authz/accesscontrol/DocumentSubsetBitsetCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java index f809a0fc00a28..18c13860efd6a 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/DocumentSubsetBitsetCache.java @@ -323,7 +323,7 @@ public Map usageStats() { return Map.of("count", entryCount(), "memory", ram.toString(), "memory_in_bytes", ram.getBytes()); } - private static class BitsetCacheKey { + private static final class BitsetCacheKey { final IndexReader.CacheKey index; final Query query;