diff --git a/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java b/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java index 9f904d5b1c5..dcc3d469e2e 100644 --- a/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java +++ b/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.Set; import java.util.function.Predicate; +import java.util.regex.Pattern; import java.util.stream.Collectors; import org.yaml.snakeyaml.Yaml; @@ -38,6 +39,17 @@ public class ClusterConfigParser { + private static final Pattern GROUP_NAME_PATTERN = + Pattern.compile("^[a-zA-Z_]{1,}[a-zA-Z0-9_]{0,}$"); + + public static void validateGroupNames(Set names) { + for (String name : names) { + if (!GROUP_NAME_PATTERN.matcher(name).matches()) { + throw new RuntimeException("Group name: " + name + " contains invalid characters"); + } + } + } + private static final String PROPERTY_FORMAT = "%s=\"%s\"%n"; private static final String[] SECTIONS = new String[] {"manager", "monitor", "gc", "tserver"}; @@ -123,6 +135,7 @@ public static void outputShellVariables(Map config, PrintStream o Set compactorQueues = config.keySet().stream().filter(k -> k.startsWith(compactorPrefix)) .map(k -> k.substring(compactorPrefix.length())).collect(Collectors.toSet()); + validateGroupNames(compactorQueues); if (!compactorQueues.isEmpty()) { out.printf(PROPERTY_FORMAT, "COMPACTION_QUEUES", @@ -138,6 +151,7 @@ public static void outputShellVariables(Map config, PrintStream o String sserverPrefix = "sserver."; Set sserverGroups = config.keySet().stream().filter(k -> k.startsWith(sserverPrefix)) .map(k -> k.substring(sserverPrefix.length())).collect(Collectors.toSet()); + validateGroupNames(sserverGroups); if (!sserverGroups.isEmpty()) { out.printf(PROPERTY_FORMAT, "SSERVER_GROUPS", @@ -162,14 +176,19 @@ public static void main(String[] args) throws IOException { System.exit(1); } - if (args.length == 2) { - // Write to a file instead of System.out if provided as an argument - try (OutputStream os = Files.newOutputStream(Paths.get(args[1]), StandardOpenOption.CREATE); - PrintStream out = new PrintStream(os)) { - outputShellVariables(parseConfiguration(args[0]), new PrintStream(out)); + try { + if (args.length == 2) { + // Write to a file instead of System.out if provided as an argument + try (OutputStream os = Files.newOutputStream(Paths.get(args[1]), StandardOpenOption.CREATE); + PrintStream out = new PrintStream(os)) { + outputShellVariables(parseConfiguration(args[0]), new PrintStream(out)); + } + } else { + outputShellVariables(parseConfiguration(args[0]), System.out); } - } else { - outputShellVariables(parseConfiguration(args[0]), System.out); + } catch (Exception e) { + System.err.println("Processing error: " + e.getMessage()); + System.exit(1); } } diff --git a/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java b/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java index f0f27e629f7..9777abc9b99 100644 --- a/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java +++ b/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java @@ -35,6 +35,7 @@ import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.function.Function; import org.junit.jupiter.api.Test; @@ -271,4 +272,20 @@ public void testFileWithUnknownSections() throws Exception { assertTrue(exception.getMessage().contains("vserver")); } } + + @Test + public void testGroupNamePattern() { + ClusterConfigParser.validateGroupNames(Set.of("a")); + ClusterConfigParser.validateGroupNames(Set.of("a", "b")); + ClusterConfigParser.validateGroupNames(Set.of("default", "reg_ular")); + ClusterConfigParser.validateGroupNames(Set.of("a1b2c3d4__")); + assertThrows(RuntimeException.class, + () -> ClusterConfigParser.validateGroupNames(Set.of("0abcde"))); + assertThrows(RuntimeException.class, + () -> ClusterConfigParser.validateGroupNames(Set.of("a-b"))); + assertThrows(RuntimeException.class, + () -> ClusterConfigParser.validateGroupNames(Set.of("a*b"))); + assertThrows(RuntimeException.class, + () -> ClusterConfigParser.validateGroupNames(Set.of("a?b"))); + } }