diff --git a/command/agent/command.go b/command/agent/command.go index 606649846a..2e9aad86d8 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -11,6 +11,7 @@ import ( "net" "os" "os/signal" + "regexp" "runtime" "strings" "syscall" @@ -20,6 +21,9 @@ import ( // gracefulTimeout controls how long we wait before forcefully terminating var gracefulTimeout = 5 * time.Second +// validDatacenter is used to validate a datacenter +var validDatacenter = regexp.MustCompile("^[a-zA-Z0-9_-]+$") + // Command is a Command implementation that runs a Consul agent. // The command will not end unless a shutdown message is sent on the // ShutdownCh. If two messages are sent on the ShutdownCh it will forcibly @@ -111,6 +115,12 @@ func (c *Command) readConfig() *Config { return nil } + // Verify data center is valid + if !validDatacenter.MatchString(config.Datacenter) { + c.Ui.Error("Datacenter must be alpha-numeric with underscores and hypens only") + return nil + } + // Only allow bootstrap mode when acting as a server if config.Bootstrap && !config.Server { c.Ui.Error("Bootstrap mode cannot be enabled when server mode is not enabled") diff --git a/command/agent/command_test.go b/command/agent/command_test.go index 9259ea691e..23036a5386 100644 --- a/command/agent/command_test.go +++ b/command/agent/command_test.go @@ -8,3 +8,26 @@ import ( func TestCommand_implements(t *testing.T) { var _ cli.Command = new(Command) } + +func TestValidDatacenter(t *testing.T) { + shouldMatch := []string{ + "dc1", + "east-aws-001", + "PROD_aws01-small", + } + noMatch := []string{ + "east.aws", + "east!aws", + "first,second", + } + for _, m := range shouldMatch { + if !validDatacenter.MatchString(m) { + t.Fatalf("expected match: %s", m) + } + } + for _, m := range noMatch { + if validDatacenter.MatchString(m) { + t.Fatalf("expected no match: %s", m) + } + } +}