diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 4521288115d..2f4827b2294 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -211,6 +211,9 @@ Bug Fixes
* SOLR-9687: Fixed Interval Facet count issue in cases of open/close intervals on the same values
(Andy Chillrud, Tomás Fernández Löbbe)
+* SOLR-9441: Solr collection backup on HDFS can only be manipulated by the Solr process owner.
+ (Hrishikesh Gadre via Mark Miller)
+
Optimizations
----------------------
diff --git a/solr/core/src/java/org/apache/solr/core/backup/repository/HdfsBackupRepository.java b/solr/core/src/java/org/apache/solr/core/backup/repository/HdfsBackupRepository.java
index f12d9fdbb55..f46576527ba 100644
--- a/solr/core/src/java/org/apache/solr/core/backup/repository/HdfsBackupRepository.java
+++ b/solr/core/src/java/org/apache/solr/core/backup/repository/HdfsBackupRepository.java
@@ -26,6 +26,7 @@ import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexInput;
@@ -41,6 +42,8 @@ import org.apache.solr.store.hdfs.HdfsDirectory.HdfsIndexInput;
import com.google.common.base.Preconditions;
public class HdfsBackupRepository implements BackupRepository {
+ private static final String HDFS_UMASK_MODE_PARAM = "solr.hdfs.permissions.umask-mode";
+
private HdfsDirectoryFactory factory;
private Configuration hdfsConfig = null;
private FileSystem fileSystem = null;
@@ -58,6 +61,12 @@ public class HdfsBackupRepository implements BackupRepository {
factory.init(args);
this.hdfsConfig = factory.getConf();
+ // Configure the umask mode if specified.
+ if (args.get(HDFS_UMASK_MODE_PARAM) != null) {
+ String umaskVal = (String)args.get(HDFS_UMASK_MODE_PARAM);
+ this.hdfsConfig.set(FsPermission.UMASK_LABEL, umaskVal);
+ }
+
String hdfsSolrHome = (String) Preconditions.checkNotNull(args.get(HdfsDirectoryFactory.HDFS_HOME),
"Please specify " + HdfsDirectoryFactory.HDFS_HOME + " property.");
Path path = new Path(hdfsSolrHome);
diff --git a/solr/core/src/test/org/apache/solr/handler/TestHdfsBackupRestoreCore.java b/solr/core/src/test/org/apache/solr/handler/TestHdfsBackupRestoreCore.java
index 4e8d4ccd584..a07d4919312 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestHdfsBackupRestoreCore.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestHdfsBackupRestoreCore.java
@@ -27,7 +27,10 @@ import java.util.Map;
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.permission.FsAction;
+import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
@@ -88,6 +91,7 @@ public class TestHdfsBackupRestoreCore extends SolrCloudTestCase {
" ${solr.hdfs.default.backup.path}\n" +
" ${solr.hdfs.home:}\n" +
" ${solr.hdfs.confdir:}\n" +
+ " ${solr.hdfs.permissions.umask-mode:000}\n" +
" \n" +
" \n" +
" \n" +
@@ -233,6 +237,13 @@ public class TestHdfsBackupRestoreCore extends SolrCloudTestCase {
}
//See if restore was successful by checking if all the docs are present again
BackupRestoreUtils.verifyDocs(nDocs, masterClient, coreName);
+
+ // Verify the permissions for the backup folder.
+ FileStatus status = fs.getFileStatus(new org.apache.hadoop.fs.Path("/backup/snapshot."+backupName));
+ FsPermission perm = status.getPermission();
+ assertEquals(FsAction.ALL, perm.getUserAction());
+ assertEquals(FsAction.ALL, perm.getGroupAction());
+ assertEquals(FsAction.ALL, perm.getOtherAction());
}
}
}