diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 6f4e369dd88..83fbe5de243 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -96,6 +96,9 @@ New Features * SOLR-12517: Support range values for replica in autoscaling policy (noble) +* SOLR-12530: Ability to disable configset upload via -Dconfigset.upload.enabled=false startup parameter + (Ishan Chattopadhyaya) + Bug Fixes ---------------------- diff --git a/solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java index 49de07bb69b..f8fc533bd1d 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/ConfigSetsHandler.java @@ -137,6 +137,11 @@ public class ConfigSetsHandler extends RequestHandlerBase implements PermissionN } private void handleConfigUploadRequest(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { + if (!"true".equals(System.getProperty("configset.upload.enabled", "true"))) { + throw new SolrException(ErrorCode.BAD_REQUEST, + "Configset upload feature is disabled. To enable this, start Solr with '-Dconfigset.upload.enabled=true'."); + } + String configSetName = req.getParams().get(NAME); if (StringUtils.isBlank(configSetName)) { throw new SolrException(ErrorCode.BAD_REQUEST, 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 ddd8fd9b98b..c76b3d68bd7 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java @@ -319,10 +319,28 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 { solrClient.close(); } + @Test + public void testUploadDisabled() throws Exception { + try (SolrZkClient zkClient = new SolrZkClient(solrCluster.getZkServer().getZkAddress(), + AbstractZkTestCase.TIMEOUT, 45000, null)) { + + for (boolean enabled: new boolean[] {true, false}) { + System.setProperty("configset.upload.enabled", String.valueOf(enabled)); + try { + long statusCode = uploadConfigSet("regular", "test-enabled-is-" + enabled, null, null, zkClient); + assertEquals("ConfigSet upload enabling/disabling not working as expected for enabled=" + enabled + ".", + enabled? 0l: 400l, statusCode); + } finally { + System.clearProperty("configset.upload.enabled"); + } + } + } + } + @Test public void testUpload() throws Exception { String suffix = "-untrusted"; - uploadConfigSet("regular", suffix, null, null); + uploadConfigSetWithAssertions("regular", suffix, null, null); // try to create a collection with the uploaded configset createCollection("newcollection", "regular" + suffix, 1, 1, solrCluster.getSolrClient()); } @@ -334,10 +352,10 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 { if (withAuthorization) { suffix = "-trusted"; protectConfigsHandler(); - uploadConfigSet("with-script-processor", suffix, "solr", "SolrRocks"); + uploadConfigSetWithAssertions("with-script-processor", suffix, "solr", "SolrRocks"); } else { suffix = "-untrusted"; - uploadConfigSet("with-script-processor", suffix, null, null); + uploadConfigSetWithAssertions("with-script-processor", suffix, null, null); } // try to create a collection with the uploaded configset CollectionAdminResponse resp = createCollection("newcollection2", "with-script-processor"+suffix, @@ -391,23 +409,11 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 { Thread.sleep(5000); // TODO: Without a delay, the test fails. Some problem with Authc/Authz framework? } - private void uploadConfigSet(String configSetName, String suffix, String username, String password) throws Exception { - // Read zipped sample config - ByteBuffer sampleZippedConfig = TestDynamicLoading - .getFileContent( - createTempZipFile("solr/configsets/upload/"+configSetName), false); - + private void uploadConfigSetWithAssertions(String configSetName, String suffix, String username, String password) throws Exception { SolrZkClient zkClient = new SolrZkClient(solrCluster.getZkServer().getZkAddress(), AbstractZkTestCase.TIMEOUT, 45000, null); try { - ZkConfigManager configManager = new ZkConfigManager(zkClient); - assertFalse(configManager.configExists(configSetName+suffix)); - - Map map = postDataAndGetResponse(solrCluster.getSolrClient(), - solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString() + "/admin/configs?action=UPLOAD&name="+configSetName+suffix, - sampleZippedConfig, username, password); - assertNotNull(map); - long statusCode = (long) getObjectByPath(map, false, Arrays.asList("responseHeader", "status")); + long statusCode = uploadConfigSet(configSetName, suffix, username, password, zkClient); assertEquals(0l, statusCode); assertTrue("managed-schema file should have been uploaded", @@ -427,6 +433,24 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 { zkClient.close(); } } + + private long uploadConfigSet(String configSetName, String suffix, String username, String password, + SolrZkClient zkClient) throws IOException { + // Read zipped sample config + ByteBuffer sampleZippedConfig = TestDynamicLoading + .getFileContent( + createTempZipFile("solr/configsets/upload/"+configSetName), false); + + ZkConfigManager configManager = new ZkConfigManager(zkClient); + assertFalse(configManager.configExists(configSetName+suffix)); + + Map map = postDataAndGetResponse(solrCluster.getSolrClient(), + solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString() + "/admin/configs?action=UPLOAD&name="+configSetName+suffix, + sampleZippedConfig, username, password); + assertNotNull(map); + long statusCode = (long) getObjectByPath(map, false, Arrays.asList("responseHeader", "status")); + return statusCode; + } /** * Create a zip file (in the temp directory) containing all the files within the specified directory diff --git a/solr/solr-ref-guide/src/configsets-api.adoc b/solr/solr-ref-guide/src/configsets-api.adoc index ba42b7978aa..8874f21849d 100644 --- a/solr/solr-ref-guide/src/configsets-api.adoc +++ b/solr/solr-ref-guide/src/configsets-api.adoc @@ -82,6 +82,8 @@ The output will look like: Upload a configset, which is sent as a zipped file. +This functionality is enabled by default, but can be disabled via a runtime parameter `-Dconfigset.upload.enabled=false`. Disabling this feature is advisable if you want to expose Solr installation to untrusted users (even though you should never do that!). + A configset is uploaded in a "trusted" mode if authentication is enabled and the upload operation is performed as an authenticated request. Without authentication, a configset is uploaded in an "untrusted" mode. Upon creation of a collection using an "untrusted" configset, the following functionality will not work: * If specified in the configset, the DataImportHandler's ScriptTransformer will not initialize.