Browse Source

Restricts naming for repositories (#41008)

Applies the same naming restrictions to repositories as to snapshots except that leading underscores and uppercase characters are permitted.

Fixes #40817.
Dan Hermann 6 years ago
parent
commit
d922d4d44a

+ 16 - 0
server/src/main/java/org/elasticsearch/repositories/RepositoriesService.java

@@ -35,6 +35,7 @@ import org.elasticsearch.cluster.metadata.RepositoriesMetaData;
 import org.elasticsearch.cluster.metadata.RepositoryMetaData;
 import org.elasticsearch.cluster.node.DiscoveryNode;
 import org.elasticsearch.cluster.service.ClusterService;
+import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.regex.Regex;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
@@ -94,6 +95,7 @@ public class RepositoriesService implements ClusterStateApplier {
      */
     public void registerRepository(final PutRepositoryRequest request, final ActionListener<ClusterStateUpdateResponse> listener) {
         final RepositoryMetaData newRepositoryMetaData = new RepositoryMetaData(request.name(), request.type(), request.settings());
+        validate(request.name());
 
         final ActionListener<ClusterStateUpdateResponse> registrationListener;
         if (request.verify()) {
@@ -418,6 +420,20 @@ public class RepositoriesService implements ClusterStateApplier {
         }
     }
 
+    private static void validate(final String repositoryName) {
+        if (Strings.hasLength(repositoryName) == false) {
+            throw new RepositoryException(repositoryName, "cannot be empty");
+        }
+        if (repositoryName.contains("#")) {
+            throw new RepositoryException(repositoryName, "must not contain '#'");
+        }
+        if (Strings.validFileName(repositoryName) == false) {
+            throw new RepositoryException(repositoryName,
+                "must not contain the following characters " + Strings.INVALID_FILENAME_CHARS);
+        }
+    }
+
+
     private void ensureRepositoryNotInUse(ClusterState clusterState, String repository) {
         if (SnapshotsService.isRepositoryInUse(clusterState, repository) || RestoreService.isRepositoryInUse(clusterState, repository)) {
             throw new IllegalStateException("trying to modify or unregister repository that is currently used ");

+ 15 - 0
server/src/test/java/org/elasticsearch/repositories/RepositoriesServiceTests.java

@@ -22,11 +22,13 @@ package org.elasticsearch.repositories;
 import org.apache.lucene.index.IndexCommit;
 import org.elasticsearch.Version;
 import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.cluster.metadata.MetaData;
 import org.elasticsearch.cluster.metadata.RepositoryMetaData;
 import org.elasticsearch.cluster.node.DiscoveryNode;
 import org.elasticsearch.cluster.service.ClusterService;
+import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.UUIDs;
 import org.elasticsearch.common.component.Lifecycle;
 import org.elasticsearch.common.component.LifecycleListener;
@@ -100,6 +102,19 @@ public class RepositoriesServiceTests extends ESTestCase {
         assertSame(repository, repository2);
     }
 
+    public void testRegisterRejectsInvalidRepositoryNames() {
+        assertThrowsOnRegister("");
+        assertThrowsOnRegister("contains#InvalidCharacter");
+        for (char c : Strings.INVALID_FILENAME_CHARS) {
+            assertThrowsOnRegister("contains" + c + "InvalidCharacters");
+        }
+    }
+
+    private void assertThrowsOnRegister(String repoName) {
+        PutRepositoryRequest request = new PutRepositoryRequest(repoName);
+        expectThrows(RepositoryException.class, () -> repositoriesService.registerRepository(request, null));
+    }
+
     private static class TestRepository implements Repository {
 
         private static final String TYPE = "internal";