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

Fixes #40817.
This commit is contained in:
Dan Hermann 2019-04-29 07:31:01 -05:00 committed by GitHub
parent fc4f401214
commit b23709b178
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 0 deletions

View File

@ -35,6 +35,7 @@ import org.elasticsearch.cluster.metadata.RepositoriesMetaData;
import org.elasticsearch.cluster.metadata.RepositoryMetaData; import org.elasticsearch.cluster.metadata.RepositoryMetaData;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ConcurrentCollections; 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) { public void registerRepository(final PutRepositoryRequest request, final ActionListener<ClusterStateUpdateResponse> listener) {
final RepositoryMetaData newRepositoryMetaData = new RepositoryMetaData(request.name(), request.type(), request.settings()); final RepositoryMetaData newRepositoryMetaData = new RepositoryMetaData(request.name(), request.type(), request.settings());
validate(request.name());
final ActionListener<ClusterStateUpdateResponse> registrationListener; final ActionListener<ClusterStateUpdateResponse> registrationListener;
if (request.verify()) { 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) { private void ensureRepositoryNotInUse(ClusterState clusterState, String repository) {
if (SnapshotsService.isRepositoryInUse(clusterState, repository) || RestoreService.isRepositoryInUse(clusterState, repository)) { if (SnapshotsService.isRepositoryInUse(clusterState, repository) || RestoreService.isRepositoryInUse(clusterState, repository)) {
throw new IllegalStateException("trying to modify or unregister repository that is currently used "); throw new IllegalStateException("trying to modify or unregister repository that is currently used ");

View File

@ -22,11 +22,13 @@ package org.elasticsearch.repositories;
import org.apache.lucene.index.IndexCommit; import org.apache.lucene.index.IndexCommit;
import org.elasticsearch.Version; import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener; 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.IndexMetaData;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.metadata.RepositoryMetaData; import org.elasticsearch.cluster.metadata.RepositoryMetaData;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.UUIDs; import org.elasticsearch.common.UUIDs;
import org.elasticsearch.common.component.Lifecycle; import org.elasticsearch.common.component.Lifecycle;
import org.elasticsearch.common.component.LifecycleListener; import org.elasticsearch.common.component.LifecycleListener;
@ -100,6 +102,19 @@ public class RepositoriesServiceTests extends ESTestCase {
assertSame(repository, repository2); 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 class TestRepository implements Repository {
private static final String TYPE = "internal"; private static final String TYPE = "internal";