This is an automated email from the ASF dual-hosted git repository.
mdrob pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new 2e4ddc7 SOLR-15249 Attempt to repair security.json ACLs
2e4ddc7 is described below
commit 2e4ddc7b9852124db63c0e5ab043dfc6445cac55
Author: Mike Drob <[email protected]>
AuthorDate: Mon Apr 5 17:31:00 2021 -0500
SOLR-15249 Attempt to repair security.json ACLs
---
.../java/org/apache/solr/cloud/ZkController.java | 37 ++++++++++++++++++++--
.../VMParamsZkACLAndCredentialsProvidersTest.java | 30 +++++++++++++++++-
.../common/cloud/SecurityAwareZkACLProvider.java | 2 +-
3 files changed, 64 insertions(+), 5 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
index 9c92892..c0cf7f0 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -92,6 +92,7 @@ import
org.apache.zookeeper.KeeperException.SessionExpiredException;
import org.apache.zookeeper.Op;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -856,9 +857,39 @@ public class ZkController implements Closeable {
cmdExecutor.ensureExists(ZkStateReader.ALIASES, zkClient);
byte[] emptyJson = "{}".getBytes(StandardCharsets.UTF_8);
cmdExecutor.ensureExists(ZkStateReader.SOLR_SECURITY_CONF_PATH, emptyJson,
zkClient);
- if (zkClient.getACL(ZkStateReader.SOLR_SECURITY_CONF_PATH, null,
true).equals(OPEN_ACL_UNSAFE)) {
- log.warn("Contents of zookeeper /security.json are world-readable;" +
- " consider setting up ACLs as described in
https://solr.apache.org/guide/zookeeper-access-control.html");
+ repairSecurityJson(zkClient);
+ }
+
+ private static void repairSecurityJson(SolrZkClient zkClient) throws
KeeperException, InterruptedException {
+ List<ACL> securityConfAcl =
zkClient.getACL(ZkStateReader.SOLR_SECURITY_CONF_PATH, null, true);
+ ZkACLProvider aclProvider = zkClient.getZkACLProvider();
+
+ boolean tryUpdate = false;
+
+ if (OPEN_ACL_UNSAFE.equals(securityConfAcl)) {
+ List<ACL> aclToAdd =
aclProvider.getACLsToAdd(ZkStateReader.SOLR_SECURITY_CONF_PATH);
+ if (OPEN_ACL_UNSAFE.equals(aclToAdd)) {
+ log.warn("Contents of zookeeper /security.json are world-readable;" +
+ " consider setting up ACLs as described in
https://solr.apache.org/guide/zookeeper-access-control.html");
+ } else {
+ tryUpdate = true;
+ }
+ } else if (aclProvider instanceof SecurityAwareZkACLProvider) {
+ // Use Set to explicitly ignore order
+ Set<ACL> nonSecureACL = new HashSet<>(aclProvider.getACLsToAdd(null));
+ // case where security.json was not treated as a secure path
+ if (nonSecureACL.equals(new HashSet<>(securityConfAcl))) {
+ tryUpdate = true;
+ }
+ }
+
+ if (tryUpdate) {
+ if (Boolean.getBoolean("solr.security.aclautorepair.disable")) {
+ log.warn("Detected inconsistent ACLs for zookeeper /security.json, but
self-repair is disabled.");
+ } else {
+ log.info("Detected inconsistent ACLs for zookeeper /security.json,
attempting to repair.");
+ zkClient.updateACLs(ZkStateReader.SOLR_SECURITY_CONF_PATH);
+ }
}
}
diff --git
a/solr/core/src/test/org/apache/solr/cloud/VMParamsZkACLAndCredentialsProvidersTest.java
b/solr/core/src/test/org/apache/solr/cloud/VMParamsZkACLAndCredentialsProvidersTest.java
index a8a3c74..47408ab 100644
---
a/solr/core/src/test/org/apache/solr/cloud/VMParamsZkACLAndCredentialsProvidersTest.java
+++
b/solr/core/src/test/org/apache/solr/cloud/VMParamsZkACLAndCredentialsProvidersTest.java
@@ -34,6 +34,8 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.zookeeper.ZooDefs.Ids.OPEN_ACL_UNSAFE;
+
public class VMParamsZkACLAndCredentialsProvidersTest extends SolrTestCaseJ4 {
private static final Logger log =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -151,6 +153,32 @@ public class VMParamsZkACLAndCredentialsProvidersTest
extends SolrTestCaseJ4 {
false, false, false, false, false);
}
}
+
+ @Test
+ public void testRepairACL() throws Exception {
+ clearSecuritySystemProperties();
+ try (SolrZkClient zkClient = new SolrZkClient(zkServer.getZkAddress(),
AbstractZkTestCase.TIMEOUT)) {
+ // Currently no credentials on ZK connection, because those same
VM-params are used for adding ACLs, and here we want
+ // no (or completely open) ACLs added. Therefore hack your way into
being authorized for creating anyway
+ zkClient.getSolrZooKeeper().addAuthInfo("digest",
("connectAndAllACLUsername:connectAndAllACLPassword")
+ .getBytes(StandardCharsets.UTF_8));
+
+ zkClient.create("/security.json", "{}".getBytes(StandardCharsets.UTF_8),
CreateMode.PERSISTENT, false);
+ assertEquals(OPEN_ACL_UNSAFE, zkClient.getACL("/security.json", null,
false));
+ }
+
+ setSecuritySystemProperties();
+ try (SolrZkClient zkClient = new SolrZkClient(zkServer.getZkAddress(),
AbstractZkTestCase.TIMEOUT)) {
+ ZkController.createClusterZkNodes(zkClient);
+ assertNotEquals(OPEN_ACL_UNSAFE, zkClient.getACL("/security.json", null,
false));
+ }
+
+ useReadonlyCredentials();
+ try (SolrZkClient zkClient = new SolrZkClient(zkServer.getZkAddress(),
AbstractZkTestCase.TIMEOUT)) {
+ NoAuthException e = assertThrows(NoAuthException.class, () ->
zkClient.getData("/security.json", null, null, false));
+ assertEquals("/security.json", e.getPath());
+ }
+ }
protected static void doTest(
SolrZkClient zkClient,
@@ -202,7 +230,7 @@ public class VMParamsZkACLAndCredentialsProvidersTest
extends SolrTestCaseJ4 {
private void useWrongCredentials() {
clearSecuritySystemProperties();
- System.setProperty(SolrZkClient.ZK_ACL_PROVIDER_CLASS_NAME_VM_PARAM_NAME,
VMParamsSingleSetCredentialsDigestZkCredentialsProvider.class.getName());
+ System.setProperty(SolrZkClient.ZK_CRED_PROVIDER_CLASS_NAME_VM_PARAM_NAME,
VMParamsSingleSetCredentialsDigestZkCredentialsProvider.class.getName());
System.setProperty(VMParamsSingleSetCredentialsDigestZkCredentialsProvider.DEFAULT_DIGEST_USERNAME_VM_PARAM_NAME,
"connectAndAllACLUsername");
System.setProperty(VMParamsSingleSetCredentialsDigestZkCredentialsProvider.DEFAULT_DIGEST_PASSWORD_VM_PARAM_NAME,
"connectAndAllACLPasswordWrong");
}
diff --git
a/solr/solrj/src/java/org/apache/solr/common/cloud/SecurityAwareZkACLProvider.java
b/solr/solrj/src/java/org/apache/solr/common/cloud/SecurityAwareZkACLProvider.java
index 2fe2da9..300c649 100644
---
a/solr/solrj/src/java/org/apache/solr/common/cloud/SecurityAwareZkACLProvider.java
+++
b/solr/solrj/src/java/org/apache/solr/common/cloud/SecurityAwareZkACLProvider.java
@@ -33,7 +33,7 @@ public abstract class SecurityAwareZkACLProvider implements
ZkACLProvider {
@Override
- public List<ACL> getACLsToAdd(String zNodePath) {
+ public final List<ACL> getACLsToAdd(String zNodePath) {
if (isSecurityZNodePath(zNodePath)) {
return getSecurityACLsToAdd();
} else {