Skip to content

Commit

Permalink
context: Ensure context name is valid on import
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Crone <christopher.crone@docker.com>
(cherry picked from commit 9ecc69d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
  • Loading branch information
chris-crone authored and thaJeztah committed Feb 2, 2021
1 parent a2f0cf5 commit 8c2872d
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 25 deletions.
21 changes: 0 additions & 21 deletions cli/command/context/cmd.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package context

import (
"errors"
"fmt"
"regexp"

"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
Expand All @@ -30,20 +26,3 @@ func NewContextCommand(dockerCli command.Cli) *cobra.Command {
)
return cmd
}

const restrictedNamePattern = "^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$"

var restrictedNameRegEx = regexp.MustCompile(restrictedNamePattern)

func validateContextName(name string) error {
if name == "" {
return errors.New("context name cannot be empty")
}
if name == "default" {
return errors.New(`"default" is a reserved context name`)
}
if !restrictedNameRegEx.MatchString(name) {
return fmt.Errorf("context name %q is invalid, names are validated against regexp %q", name, restrictedNamePattern)
}
return nil
}
2 changes: 1 addition & 1 deletion cli/command/context/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func createNewContext(o *CreateOptions, stackOrchestrator command.Orchestrator,
}

func checkContextNameForCreation(s store.Reader, name string) error {
if err := validateContextName(name); err != nil {
if err := store.ValidateContextName(name); err != nil {
return err
}
if _, err := s.GetMetadata(name); !store.IsErrContextDoesNotExist(err) {
Expand Down
2 changes: 1 addition & 1 deletion cli/command/context/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func writeTo(dockerCli command.Cli, reader io.Reader, dest string) error {

// RunExport exports a Docker context
func RunExport(dockerCli command.Cli, opts *ExportOptions) error {
if err := validateContextName(opts.ContextName); err != nil && opts.ContextName != command.DefaultContextName {
if err := store.ValidateContextName(opts.ContextName); err != nil && opts.ContextName != command.DefaultContextName {
return err
}
ctxMeta, err := dockerCli.ContextStore().GetMetadata(opts.ContextName)
Expand Down
2 changes: 1 addition & 1 deletion cli/command/context/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func newUpdateCommand(dockerCli command.Cli) *cobra.Command {

// RunUpdate updates a Docker context
func RunUpdate(cli command.Cli, o *UpdateOptions) error {
if err := validateContextName(o.Name); err != nil {
if err := store.ValidateContextName(o.Name); err != nil {
return err
}
s := cli.ContextStore()
Expand Down
3 changes: 2 additions & 1 deletion cli/command/context/use.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"

"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context/store"
"github.com/spf13/cobra"
)

Expand All @@ -23,7 +24,7 @@ func newUseCommand(dockerCli command.Cli) *cobra.Command {

// RunUse set the current Docker context
func RunUse(dockerCli command.Cli, name string) error {
if err := validateContextName(name); err != nil && name != "default" {
if err := store.ValidateContextName(name); err != nil && name != "default" {
return err
}
if _, err := dockerCli.ContextStore().GetMetadata(name); err != nil && name != "default" {
Expand Down
22 changes: 22 additions & 0 deletions cli/context/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@ import (
"net/http"
"path"
"path/filepath"
"regexp"
"strings"

"github.com/docker/docker/errdefs"
digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
)

const restrictedNamePattern = "^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$"

var restrictedNameRegEx = regexp.MustCompile(restrictedNamePattern)

// Store provides a context store for easily remembering endpoints configuration
type Store interface {
Reader
Expand Down Expand Up @@ -184,6 +189,20 @@ func (s *store) GetStorageInfo(contextName string) StorageInfo {
}
}

// ValidateContextName checks a context name is valid.
func ValidateContextName(name string) error {
if name == "" {
return errors.New("context name cannot be empty")
}
if name == "default" {
return errors.New(`"default" is a reserved context name`)
}
if !restrictedNameRegEx.MatchString(name) {
return fmt.Errorf("context name %q is invalid, names are validated against regexp %q", name, restrictedNamePattern)
}
return nil
}

// Export exports an existing namespace into an opaque data stream
// This stream is actually a tarball containing context metadata and TLS materials, but it does
// not map 1:1 the layout of the context store (don't try to restore it manually without calling store.Import)
Expand Down Expand Up @@ -427,6 +446,9 @@ func parseMetadata(data []byte, name string) (Metadata, error) {
if err := json.Unmarshal(data, &meta); err != nil {
return meta, err
}
if err := ValidateContextName(name); err != nil {
return Metadata{}, err
}
meta.Name = name
return meta, nil
}
Expand Down
13 changes: 13 additions & 0 deletions cli/context/store/storeconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,16 @@ func TestValidFilePaths(t *testing.T) {
assert.Equal(t, err == nil, expectedValid, "%q should report valid as: %v", p, expectedValid)
}
}

func TestValidateContextName(t *testing.T) {
names := map[string]bool{
"../../invalid/escape": false,
"/invalid/absolute": false,
`\invalid\windows`: false,
"validname": true,
}
for n, expectedValid := range names {
err := ValidateContextName(n)
assert.Equal(t, err == nil, expectedValid, "%q should report valid as: %v", n, expectedValid)
}
}

0 comments on commit 8c2872d

Please sign in to comment.