This is an automated email from the ASF dual-hosted git repository.

gerlowskija pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_9x by this push:
     new f492e24881c SOLR-16781: Disable <lib/> by default on 9.x (#2894)
f492e24881c is described below

commit f492e24881c5724a1b1baecfc9549e2cb0257525
Author: Jason Gerlowski <gerlowsk...@apache.org>
AuthorDate: Wed Dec 4 10:21:47 2024 -0500

    SOLR-16781: Disable <lib/> by default on 9.x (#2894)
    
    `<lib/>` usage will now log a warning by default for future 9.x
    releases.  Wary users can re-enabled the feature by specifying a
    sysprop: `solr.config.lib.enabled=true`.
    
    (This commit is for 9.x branches only, and not 'main')
---
 solr/CHANGES.txt                                   |  2 +
 .../java/org/apache/solr/cli/RunExampleTool.java   | 10 +++-
 .../src/java/org/apache/solr/core/SolrConfig.java  | 66 ++++++++++++++--------
 .../org/apache/solr/cloud/TestConfigSetsAPI.java   |  2 +
 .../src/test/org/apache/solr/core/TestConfig.java  |  3 +
 .../solr/core/TestConfigWithLibDisabled.java       | 66 ++++++++++++++++++++++
 .../modules/configuration-guide/pages/libs.adoc    |  7 +++
 .../pages/resource-loading.adoc                    |  2 +-
 .../indexing-guide/pages/indexing-with-tika.adoc   |  9 +--
 .../query-guide/pages/learning-to-rank.adoc        |  9 +--
 .../pages/major-changes-in-solr-9.adoc             |  7 +++
 11 files changed, 142 insertions(+), 41 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 213846bf2c8..85a375a07f2 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -142,6 +142,8 @@ led to the suppression of exceptions. (Andrey Bozhko)
 
 * SOLR-17577: Remove "solr.indexfetcher.sotimeout" system property that was 
for optimizing replication tests.  It was disabled, but not removed. (Eric Pugh)
 
+* SOLR-16781: "<lib/>" tags in solrconfig.xml are now quietly ignored by 
default unless explicitly enabled with the `SOLR_CONFIG_LIB_ENABLED=true` 
enviroment variable (or corresponding sysprop).  These tags are now considered 
deprecated and will be removed in Solr 10.
+
 ==================  9.7.1 ==================
 Bug Fixes
 ---------------------
diff --git a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java 
b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
index 7ef74c5f298..0b278d13e60 100644
--- a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
@@ -620,10 +620,15 @@ public class RunExampleTool extends ToolBase {
     if (!isWindows && cwdPath.length() > 1 && solrHome.startsWith(cwdPath))
       solrHome = solrHome.substring(cwdPath.length() + 1);
 
+    final var syspropArg =
+        ("techproducts".equals(cli.getOptionValue("example")))
+            ? "-Dsolr.modules=clustering,extraction,langid,ltr,scripting 
-Dsolr.ltr.enabled=true -Dsolr.clustering.enabled=true"
+            : "";
+
     String startCmd =
         String.format(
             Locale.ROOT,
-            "\"%s\" start %s -p %d --solr-home \"%s\" %s %s %s %s %s %s %s",
+            "\"%s\" start %s -p %d --solr-home \"%s\" %s %s %s %s %s %s %s %s",
             callScript,
             cloudModeArg,
             port,
@@ -634,7 +639,8 @@ public class RunExampleTool extends ToolBase {
             forceArg,
             verboseArg,
             extraArgs,
-            jvmOptsArg);
+            jvmOptsArg,
+            syspropArg);
     startCmd = startCmd.replaceAll("\\s+", " ").trim(); // for pretty printing
 
     echo("\nStarting up Solr on port " + port + " using command:");
diff --git a/solr/core/src/java/org/apache/solr/core/SolrConfig.java 
b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
index 173a44b9ba2..b6e177d92a0 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
@@ -65,6 +65,7 @@ import org.apache.solr.common.ConfigNode;
 import org.apache.solr.common.MapSerializable;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.common.util.EnvUtils;
 import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.common.util.Utils;
 import org.apache.solr.handler.component.SearchComponent;
@@ -937,6 +938,8 @@ public class SolrConfig implements MapSerializable {
         SolrException.ErrorCode.SERVER_ERROR, "Multiple plugins configured for 
type: " + type);
   }
 
+  public static final String LIB_ENABLED_SYSPROP = "solr.config.lib.enabled";
+
   private void initLibs(SolrResourceLoader loader, boolean isConfigsetTrusted) 
{
     // TODO Want to remove SolrResourceLoader.getInstancePath; it can be on a 
Standalone subclass.
     // For Zk subclass, it's needed for the time being as well.  We could 
remove that one if we
@@ -954,6 +957,7 @@ public class SolrConfig implements MapSerializable {
       }
     }
 
+    boolean libDirectiveAllowed = 
EnvUtils.getPropertyAsBool(LIB_ENABLED_SYSPROP, false);
     List<ConfigNode> nodes = root.getAll("lib");
     if (nodes != null && nodes.size() > 0) {
       if (!isConfigsetTrusted) {
@@ -964,30 +968,12 @@ public class SolrConfig implements MapSerializable {
                 + " after enabling authentication and authorization.");
       }
 
-      for (int i = 0; i < nodes.size(); i++) {
-        ConfigNode node = nodes.get(i);
-        String baseDir = node.attr("dir");
-        String path = node.attr(PATH);
-        if (null != baseDir) {
-          // :TODO: add support for a simpler 'glob' mutually exclusive of 
regex
-          Path dir = instancePath.resolve(baseDir);
-          String regex = node.attr("regex");
-          try {
-            if (regex == null) urls.addAll(SolrResourceLoader.getURLs(dir));
-            else urls.addAll(SolrResourceLoader.getFilteredURLs(dir, regex));
-          } catch (IOException e) {
-            log.warn("Couldn't add files from {} filtered by {} to classpath: 
{}", dir, regex, e);
-          }
-        } else if (null != path) {
-          final Path dir = instancePath.resolve(path);
-          try {
-            urls.add(dir.toUri().toURL());
-          } catch (MalformedURLException e) {
-            log.warn("Couldn't add file {} to classpath: {}", dir, e);
-          }
-        } else {
-          throw new RuntimeException("lib: missing mandatory attributes: 'dir' 
or 'path'");
-        }
+      if (!libDirectiveAllowed) {
+        log.warn(
+            "Configset references one or more <lib/> directives, but <lib/> 
usage is disabled on this Solr node.  Either remove all <lib/> tags from the 
relevant configset, or enable use of this feature by setting '{}=true'",
+            LIB_ENABLED_SYSPROP);
+      } else {
+        urls.addAll(processLibDirectives(nodes, instancePath));
       }
     }
 
@@ -997,6 +983,38 @@ public class SolrConfig implements MapSerializable {
     }
   }
 
+  private List<URL> processLibDirectives(List<ConfigNode> nodes, Path 
instancePath) {
+    final var urls = new ArrayList<URL>();
+
+    for (int i = 0; i < nodes.size(); i++) {
+      ConfigNode node = nodes.get(i);
+      String baseDir = node.attr("dir");
+      String path = node.attr(PATH);
+      if (null != baseDir) {
+        // :TODO: add support for a simpler 'glob' mutually exclusive of regex
+        Path dir = instancePath.resolve(baseDir);
+        String regex = node.attr("regex");
+        try {
+          if (regex == null) urls.addAll(SolrResourceLoader.getURLs(dir));
+          else urls.addAll(SolrResourceLoader.getFilteredURLs(dir, regex));
+        } catch (IOException e) {
+          log.warn("Couldn't add files from {} filtered by {} to classpath: 
{}", dir, regex, e);
+        }
+      } else if (null != path) {
+        final Path dir = instancePath.resolve(path);
+        try {
+          urls.add(dir.toUri().toURL());
+        } catch (MalformedURLException e) {
+          log.warn("Couldn't add file {} to classpath: {}", dir, e);
+        }
+      } else {
+        throw new RuntimeException("lib: missing mandatory attributes: 'dir' 
or 'path'");
+      }
+    }
+
+    return urls;
+  }
+
   public int getMultipartUploadLimitKB() {
     return multipartUploadLimitKB;
   }
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java 
b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
index 68142392df1..eb28fdced07 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
@@ -19,6 +19,7 @@ package org.apache.solr.cloud;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.solr.common.params.CommonParams.NAME;
 import static org.apache.solr.core.ConfigSetProperties.DEFAULT_FILENAME;
+import static org.apache.solr.core.SolrConfig.LIB_ENABLED_SYSPROP;
 import static org.hamcrest.CoreMatchers.containsString;
 
 import java.io.ByteArrayInputStream;
@@ -122,6 +123,7 @@ public class TestConfigSetsAPI extends SolrCloudTestCase {
 
   @BeforeClass
   public static void setUpClass() throws Exception {
+    System.setProperty(LIB_ENABLED_SYSPROP, "true");
     System.setProperty("managed.schema.mutable", "true");
     configureCluster(1).withSecurityJson(getSecurityJson()).configure();
   }
diff --git a/solr/core/src/test/org/apache/solr/core/TestConfig.java 
b/solr/core/src/test/org/apache/solr/core/TestConfig.java
index 2c17cbf1e1a..ea5f1267c15 100644
--- a/solr/core/src/test/org/apache/solr/core/TestConfig.java
+++ b/solr/core/src/test/org/apache/solr/core/TestConfig.java
@@ -16,6 +16,8 @@
  */
 package org.apache.solr.core;
 
+import static org.apache.solr.core.SolrConfig.LIB_ENABLED_SYSPROP;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Collections;
@@ -38,6 +40,7 @@ public class TestConfig extends SolrTestCaseJ4 {
 
   @BeforeClass
   public static void beforeClass() throws Exception {
+    System.setProperty(LIB_ENABLED_SYSPROP, "true");
     initCore("solrconfig-test-misc.xml", "schema-reversed.xml");
   }
 
diff --git 
a/solr/core/src/test/org/apache/solr/core/TestConfigWithLibDisabled.java 
b/solr/core/src/test/org/apache/solr/core/TestConfigWithLibDisabled.java
new file mode 100644
index 00000000000..00c74d629b5
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/core/TestConfigWithLibDisabled.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.core;
+
+import static org.apache.solr.core.SolrConfig.LIB_ENABLED_SYSPROP;
+import static org.hamcrest.core.StringContains.containsString;
+
+import java.io.IOException;
+import org.apache.solr.SolrTestCaseJ4;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+// TODO - replace 'initCore' usage and merge with TestConfig
+/**
+ * Unit test verifying that "lib" tags are quietly ignored when not explicitly 
enabled.
+ *
+ * <p>Based on code from {@link TestConfig}.
+ */
+public class TestConfigWithLibDisabled extends SolrTestCaseJ4 {
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    System.setProperty(LIB_ENABLED_SYSPROP, "false"); // <lib> tags disabled!
+    initCore("solrconfig-test-misc.xml", "schema-reversed.xml");
+  }
+
+  // solrconfig-test-misc has lib tags referencing various files
+  // This test ensures that none of those files are loadable when
+  // <lib> tags are disabled
+  @Test
+  public void testLibFilesShouldntBeVisible() throws IOException {
+    SolrResourceLoader loader = h.getCore().getResourceLoader();
+    String[] filesReferencedByLib =
+        new String[] {
+          "empty-file-a1.txt",
+          "empty-file-a2.txt",
+          "empty-file-b1.txt",
+          "empty-file-b2.txt",
+          "empty-file-c1.txt"
+        };
+    for (String f : filesReferencedByLib) {
+      final var e =
+          expectThrows(
+              SolrResourceNotFoundException.class,
+              () -> {
+                loader.openResource(f);
+              });
+      assertThat(e.getMessage(), containsString("Can't find resource"));
+      assertThat(e.getMessage(), containsString(f));
+    }
+  }
+}
diff --git a/solr/solr-ref-guide/modules/configuration-guide/pages/libs.adoc 
b/solr/solr-ref-guide/modules/configuration-guide/pages/libs.adoc
index 269e56f4169..02910b1199b 100644
--- a/solr/solr-ref-guide/modules/configuration-guide/pages/libs.adoc
+++ b/solr/solr-ref-guide/modules/configuration-guide/pages/libs.adoc
@@ -50,6 +50,13 @@ Solr plugins won't work in these locations.
 
 == Lib Directives in SolrConfig
 
+[WARNING]
+====
+`<lib/>` directives are deprecated and will be removed in Solr 10.0.
+In the interim, Solr disables this feature by default in order to minimize the 
security exposure of our users.
+Expert users who wish to enable `<lib/>` directives in their deployment may do 
so by specifying setting the `solr.config.lib.enabled` sysprop to `true`.
+====
+
 _Both_ plugin and xref:resource-loading.adoc[resource] file paths are 
configurable via `<lib/>` directives in `solrconfig.xml`.
 When a directive matches a directory, then resources can be resolved from it.
 When a directive matches a `.jar` file, Solr plugins and their dependencies 
are resolved from it.
diff --git 
a/solr/solr-ref-guide/modules/configuration-guide/pages/resource-loading.adoc 
b/solr/solr-ref-guide/modules/configuration-guide/pages/resource-loading.adoc
index bcdbe17c5ef..1eb5e566ee4 100644
--- 
a/solr/solr-ref-guide/modules/configuration-guide/pages/resource-loading.adoc
+++ 
b/solr/solr-ref-guide/modules/configuration-guide/pages/resource-loading.adoc
@@ -37,7 +37,7 @@ Prefer to put resources here.
 
 == Resources in Other Places
 
-Resources can also be placed in an arbitrary directory and 
xref:libs.adoc#lib-directives-in-solrconfig[referenced] from a `<lib />` 
directive in `solrconfig.xml`, provided the directive refers to a directory and 
not the actual resource file.
+Users who have enabled Solr's `<lib/>` directive feature may place resources 
in an arbitrary directory 
xref:libs.adoc#lib-directives-in-solrconfig[referenced] from a `<lib />` 
directive in `solrconfig.xml`, provided the directive refers to a directory and 
not the actual resource file.
 Example: `<lib path="/volume/models/" />`
 This choice may make sense if the resource is too large for a configset in 
ZooKeeper.
 However it's up to you to somehow ensure that all nodes in your cluster have 
access to these resources.
diff --git 
a/solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-tika.adoc 
b/solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-tika.adoc
index b1344ed5519..b0cdb7eba30 100644
--- a/solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-tika.adoc
+++ b/solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-tika.adoc
@@ -421,13 +421,8 @@ Also see the section <<Defining XPath Expressions>> for an 
example.
 
 If you have started Solr with one of the supplied 
xref:configuration-guide:config-sets.adoc[example configsets], you may already 
have the `ExtractingRequestHandler` configured by default.
 
-First, you must enable the xref:#module[Module].
-If `solrconfig.xml` is not already configured, you will need to modify it to 
find the `ExtractingRequestHandler` and its dependencies:
-
-[source,xml]
-----
-  <lib dir="${solr.install.dir:../../..}/modules/extraction/lib" 
regex=".*\.jar" />
-----
+First, the `extraction` xref:#module[module] must be enabled.
+This can be done by specifying the environment variable 
`SOLR_MODULES=extraction` in your startup configuration.
 
 You can then configure the `ExtractingRequestHandler` in `solrconfig.xml`.
 The following is the default configuration found in Solr's 
`sample_techproducts_configs` configset, which you can modify as needed:
diff --git 
a/solr/solr-ref-guide/modules/query-guide/pages/learning-to-rank.adoc 
b/solr/solr-ref-guide/modules/query-guide/pages/learning-to-rank.adoc
index 1d3f575ba03..e40deb89cc1 100644
--- a/solr/solr-ref-guide/modules/query-guide/pages/learning-to-rank.adoc
+++ b/solr/solr-ref-guide/modules/query-guide/pages/learning-to-rank.adoc
@@ -125,13 +125,8 @@ Learning-To-Rank is a module and therefore its plugins 
must be configured in `so
 
 === Minimum Requirements
 
-* Include the required module JARs.
-Note that by default paths are relative to the Solr core, so they may need 
adjustments to your configuration, or an explicit specification of the 
`$solr.install.dir`.
-+
-[source,xml]
-----
-<lib dir="${solr.install.dir:../../../..}/modules/ltr/lib/" regex=".*\.jar" />
-----
+* Enable the `ltr` module to make the LTR classes available on Solr's 
classpath.
+See xref:configuration-guide:solr-modules.adoc[Solr Module] for more details.
 
 * Declaration of the `ltr` query parser.
 +
diff --git 
a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc 
b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc
index 1c7bbb93c7e..834c76fccac 100644
--- 
a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc
+++ 
b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc
@@ -71,6 +71,13 @@ Due to changes in Lucene 9, that isn't possible any more.
 === Configuration
 In solrconfig.xml, the `numVersionBuckets` and `versionBucketLockTimeoutMs` 
settings are now obsolete and ignored; a warning will be logged if specified.
 
+`<lib/>` directives have been made into an "opt-in" feature in Solr 9.8 and 
must be explicitly enabled if desired (using a system property or environment 
variable like `-Dsolr.config.lib.enabled=true`)
+If not explicitly enabled, Solr will log a warning but otherwise quietly 
ignore any `<lib/>` tags in configsets.
+This is a breaking change, and we apologize for the disruption, but it's a 
necessary response to a number of security gaps that have come to light around 
this feature.
+`<lib/>` directives should be considered deprecated and will be removed 
entirely in Solr 10.0.
+Current users of `<lib/>` have a number of options to ensure their libraries 
remain on Solr's classpath, including: `SOLR_MODULES`, core "lib" directories, 
the solr.xml `<sharedLib>` tag, Solr's package manager, etc.
+
+
 === Partial Results
 When query limits are in use and partial results are not desirable (i.e. 
reporting or quantitative usages of search)
 users may pass `partialResults=false`.

Reply via email to