Reject names that aren't url-safe
Environment names can be used in a number of contexts, and should be properly escaped for safety. Since most state names are store in path structures, and often in a URL, use `url.PathEscape` to check for disallowed characters
This commit is contained in:
parent
3e8a8c5e23
commit
9d118325b3
|
@ -1,6 +1,9 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// EnvCommand is a Command Implementation that manipulates local state
|
// EnvCommand is a Command Implementation that manipulates local state
|
||||||
// environments.
|
// environments.
|
||||||
|
@ -39,6 +42,13 @@ func (c *EnvCommand) Synopsis() string {
|
||||||
return "Environment management"
|
return "Environment management"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validEnvName returns true is this name is valid to use as an environment name.
|
||||||
|
// Since most named states are accessed via a filesystem path or URL, check if
|
||||||
|
// escaping the name would be required.
|
||||||
|
func validEnvName(name string) bool {
|
||||||
|
return name == url.PathEscape(name)
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
envNotSupported = `Backend does not support environments`
|
envNotSupported = `Backend does not support environments`
|
||||||
|
|
||||||
|
@ -81,5 +91,10 @@ Environment %[1]q is your active environment!
|
||||||
|
|
||||||
You cannot delete the currently active environment. Please switch
|
You cannot delete the currently active environment. Please switch
|
||||||
to another environment and try again.
|
to another environment and try again.
|
||||||
|
`
|
||||||
|
|
||||||
|
envInvalidName = `
|
||||||
|
The environment name %q is not allowed. The name must contain only URL safe
|
||||||
|
characters, and no path separators.
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
|
@ -103,6 +103,44 @@ func TestEnv_createAndList(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't allow names that aren't URL safe
|
||||||
|
func TestEnv_createInvalid(t *testing.T) {
|
||||||
|
// Create a temporary working directory that is empty
|
||||||
|
td := tempDir(t)
|
||||||
|
os.MkdirAll(td, 0755)
|
||||||
|
defer os.RemoveAll(td)
|
||||||
|
defer testChdir(t, td)()
|
||||||
|
|
||||||
|
newCmd := &EnvNewCommand{}
|
||||||
|
|
||||||
|
envs := []string{"test_a*", "test_b/foo", "../../../test_c", "好_d"}
|
||||||
|
|
||||||
|
// create multiple envs
|
||||||
|
for _, env := range envs {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
newCmd.Meta = Meta{Ui: ui}
|
||||||
|
if code := newCmd.Run([]string{env}); code == 0 {
|
||||||
|
t.Fatalf("expected failure: \n%s", ui.OutputWriter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// list envs to make sure none were created
|
||||||
|
listCmd := &EnvListCommand{}
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
listCmd.Meta = Meta{Ui: ui}
|
||||||
|
|
||||||
|
if code := listCmd.Run(nil); code != 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := strings.TrimSpace(ui.OutputWriter.String())
|
||||||
|
expected := "* default"
|
||||||
|
|
||||||
|
if actual != expected {
|
||||||
|
t.Fatalf("\nexpected: %q\nactual: %q", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestEnv_createWithState(t *testing.T) {
|
func TestEnv_createWithState(t *testing.T) {
|
||||||
td := tempDir(t)
|
td := tempDir(t)
|
||||||
os.MkdirAll(td, 0755)
|
os.MkdirAll(td, 0755)
|
||||||
|
|
|
@ -32,6 +32,11 @@ func (c *EnvDeleteCommand) Run(args []string) int {
|
||||||
|
|
||||||
delEnv := args[0]
|
delEnv := args[0]
|
||||||
|
|
||||||
|
if !validEnvName(delEnv) {
|
||||||
|
c.Ui.Error(fmt.Sprintf(envInvalidName, delEnv))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
configPath, err := ModulePath(args[1:])
|
configPath, err := ModulePath(args[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(err.Error())
|
c.Ui.Error(err.Error())
|
||||||
|
|
|
@ -35,6 +35,11 @@ func (c *EnvNewCommand) Run(args []string) int {
|
||||||
|
|
||||||
newEnv := args[0]
|
newEnv := args[0]
|
||||||
|
|
||||||
|
if !validEnvName(newEnv) {
|
||||||
|
c.Ui.Error(fmt.Sprintf(envInvalidName, newEnv))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
configPath, err := ModulePath(args[1:])
|
configPath, err := ModulePath(args[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(err.Error())
|
c.Ui.Error(err.Error())
|
||||||
|
|
|
@ -39,6 +39,10 @@ func (c *EnvSelectCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
name := args[0]
|
name := args[0]
|
||||||
|
if !validEnvName(name) {
|
||||||
|
c.Ui.Error(fmt.Sprintf(envInvalidName, name))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
states, err := b.States()
|
states, err := b.States()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue