From 15d800c0657dae7d7c96e0eb51ae0e2c7cc89775 Mon Sep 17 00:00:00 2001 From: Pat Whelan Date: Tue, 14 Oct 2025 14:37:18 -0400 Subject: [PATCH 1/2] [ML] Disable CrossProject for Datafeeds Initially, Datafeeds will not support cross-project source indices. We will verify that the IndicesOptions is not trying to resolve a cross-project index expression and throw a cross-project specific error message. --- .../xpack/core/ml/datafeed/DatafeedConfig.java | 4 ++++ .../xpack/core/ml/utils/ExceptionsHelper.java | 4 ++++ .../ml/datafeed/DatafeedConfigBuilderTests.java | 16 ++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfig.java index 44151f992f75e..2e66034b293e4 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfig.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfig.java @@ -1050,6 +1050,10 @@ public DatafeedConfig build() { if (indicesOptions == null) { indicesOptions = IndicesOptions.STRICT_EXPAND_OPEN_HIDDEN_FORBID_CLOSED; } + if (indicesOptions.resolveCrossProjectIndexExpression()) { + throw ExceptionsHelper.crossProjectSearchIsDisabled(); + } + return new DatafeedConfig( id, jobId, diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/utils/ExceptionsHelper.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/utils/ExceptionsHelper.java index 73e3c31297fbf..d574596fb3367 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/utils/ExceptionsHelper.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/utils/ExceptionsHelper.java @@ -101,6 +101,10 @@ public static ElasticsearchStatusException taskOperationFailureToStatusException return new ElasticsearchStatusException(failure.getCause().getMessage(), failure.getStatus(), failure.getCause()); } + public static ElasticsearchStatusException crossProjectSearchIsDisabled() { + return new ElasticsearchStatusException("Cross-project search is not enabled for any ML feature", RestStatus.FORBIDDEN); + } + /** * Creates an error message that explains there are shard failures, displays info * for the first failure (shard/reason) and kindly asks to see more info in the logs diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfigBuilderTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfigBuilderTests.java index ac3565e3d3be6..414d3ac44dd38 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfigBuilderTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfigBuilderTests.java @@ -6,12 +6,14 @@ */ package org.elasticsearch.xpack.core.ml.datafeed; +import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.core.TimeValue; +import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.SearchModule; import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; @@ -30,6 +32,7 @@ import static org.elasticsearch.xpack.core.ml.datafeed.DatafeedConfigTests.randomStringList; import static org.elasticsearch.xpack.core.ml.utils.QueryProviderTests.createTestQueryProvider; +import static org.hamcrest.Matchers.equalTo; public class DatafeedConfigBuilderTests extends AbstractWireSerializingTestCase { @@ -147,4 +150,17 @@ protected Writeable.Reader instanceReader() { return DatafeedConfig.Builder::new; } + public void testResolveCrossProjectIsDisabled() { + var datafeedBuilder = createRandomizedDatafeedConfigBuilder("jobId", "datafeed-id", 3600000); + datafeedBuilder = datafeedBuilder.setIndicesOptions( + IndicesOptions.builder(datafeedBuilder.getIndicesOptions()) + .crossProjectModeOptions(new IndicesOptions.CrossProjectModeOptions(true)) + .build() + ); + + var actualException = assertThrows(ElasticsearchStatusException.class, datafeedBuilder::build); + assertThat(actualException.getMessage(), equalTo("Cross-project search is not enabled for any ML feature")); + assertThat(actualException.status(), equalTo(RestStatus.FORBIDDEN)); + } + } From c15cd1b518a3b388e4ca847651d0cc962d85aaec Mon Sep 17 00:00:00 2001 From: Pat Whelan Date: Mon, 27 Oct 2025 17:09:44 -0400 Subject: [PATCH 2/2] Removing the more generic exception since no other implementation needed it --- .../elasticsearch/xpack/core/ml/datafeed/DatafeedConfig.java | 4 +++- .../elasticsearch/xpack/core/ml/utils/ExceptionsHelper.java | 4 ---- .../xpack/core/ml/datafeed/DatafeedConfigBuilderTests.java | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfig.java index 2e66034b293e4..b1ed7f61ef576 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfig.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfig.java @@ -9,6 +9,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.TransportVersion; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.support.IndicesOptions; @@ -21,6 +22,7 @@ import org.elasticsearch.core.TimeValue; import org.elasticsearch.core.Tuple; import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregatorFactories; import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder; @@ -1051,7 +1053,7 @@ public DatafeedConfig build() { indicesOptions = IndicesOptions.STRICT_EXPAND_OPEN_HIDDEN_FORBID_CLOSED; } if (indicesOptions.resolveCrossProjectIndexExpression()) { - throw ExceptionsHelper.crossProjectSearchIsDisabled(); + throw new ElasticsearchStatusException("Cross-project search is not enabled for Datafeeds", RestStatus.FORBIDDEN); } return new DatafeedConfig( diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/utils/ExceptionsHelper.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/utils/ExceptionsHelper.java index d574596fb3367..73e3c31297fbf 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/utils/ExceptionsHelper.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/utils/ExceptionsHelper.java @@ -101,10 +101,6 @@ public static ElasticsearchStatusException taskOperationFailureToStatusException return new ElasticsearchStatusException(failure.getCause().getMessage(), failure.getStatus(), failure.getCause()); } - public static ElasticsearchStatusException crossProjectSearchIsDisabled() { - return new ElasticsearchStatusException("Cross-project search is not enabled for any ML feature", RestStatus.FORBIDDEN); - } - /** * Creates an error message that explains there are shard failures, displays info * for the first failure (shard/reason) and kindly asks to see more info in the logs diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfigBuilderTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfigBuilderTests.java index 414d3ac44dd38..800406adc2868 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfigBuilderTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/datafeed/DatafeedConfigBuilderTests.java @@ -159,7 +159,7 @@ public void testResolveCrossProjectIsDisabled() { ); var actualException = assertThrows(ElasticsearchStatusException.class, datafeedBuilder::build); - assertThat(actualException.getMessage(), equalTo("Cross-project search is not enabled for any ML feature")); + assertThat(actualException.getMessage(), equalTo("Cross-project search is not enabled for Datafeeds")); assertThat(actualException.status(), equalTo(RestStatus.FORBIDDEN)); }