Skip to content
This repository has been archived by the owner on Jun 13, 2021. It is now read-only.

Commit

Permalink
Check compose file don't use relative paths for bind mount
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
  • Loading branch information
ndeloof committed Nov 13, 2019
1 parent 80c0233 commit 986e7e6
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 2 deletions.
17 changes: 15 additions & 2 deletions internal/commands/build/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ import (
type ServiceConfig struct {
Name string `yaml:"-" json:"-"`

Build *ImageBuildConfig
Image *string
Build *ImageBuildConfig
Image *string
Volumes []ServiceVolumeConfig `yaml:",omitempty" json:"volumes,omitempty"`
}

type ServiceVolumeConfig struct {
Type string `yaml:",omitempty" json:"type,omitempty"`
Source string `yaml:",omitempty" json:"source,omitempty"`
}

type ImageBuildConfig struct {
Expand Down Expand Up @@ -46,6 +52,13 @@ func loadServices(servicesDict map[string]interface{}, buildArgs []string) ([]Se
return nil, err
}
services = append(services, *serviceConfig)

// Sanity check
for _, volume := range serviceConfig.Volumes {
if volume.Type == "bind" && strings.HasPrefix(volume.Source, ".") {
return nil, fmt.Errorf("invalid service %q: can't use relative path as volume source", name)
}
}
}
return services, nil
}
Expand Down
43 changes: 43 additions & 0 deletions internal/packager/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,46 @@ func checkEnvFiles(errWriter io.Writer, appName string, cfgMap map[string]interf
return nil
}

func checkRelativePaths(cfgMap map[string]interface{}) error {
services := cfgMap["services"]
servicesMap, ok := services.(map[string]interface{})
if !ok {
return fmt.Errorf("invalid Compose file")
}
for svcName, svc := range servicesMap {
svcContent, ok := svc.(map[string]interface{})
if !ok {
return fmt.Errorf("invalid service %q", svcName)
}
v := svcContent["volumes"]
volumes, ok := v.([]interface{})
if !ok {
return fmt.Errorf("invalid Compose file")
}
for _, volume := range volumes {
switch volume.(type) {
case string:
svol := volume.(string)
if strings.HasPrefix(svol, ".") {
return fmt.Errorf("invalid service %q: can't use relative path as volume source", svcName)
}
case map[string]interface{}:
lvol := volume.(map[string]interface{})
src, ok := lvol["source"]
if !ok {
return fmt.Errorf("invalid volume in service %q", svcName)
}
if strings.HasPrefix(src.(string), ".") {
return fmt.Errorf("invalid service %q: can't use relative path as volume source", svcName)
}
default:
return fmt.Errorf("invalid Compose file")
}
}
}
return nil
}

func getParamsFromDefaultEnvFile(composeFile string, composeRaw []byte) (map[string]string, bool, error) {
params := make(map[string]string)
envs, err := opts.ParseEnvFile(filepath.Join(filepath.Dir(composeFile), ".env"))
Expand Down Expand Up @@ -173,6 +213,9 @@ func initFromComposeFile(errWriter io.Writer, name string, composeFile string) e
if err := checkEnvFiles(errWriter, name, cfgMap); err != nil {
return err
}
if err := checkRelativePaths(cfgMap); err != nil {
return err
}
params, needsFilling, err := getParamsFromDefaultEnvFile(composeFile, composeRaw)
if err != nil {
return err
Expand Down
36 changes: 36 additions & 0 deletions internal/packager/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,39 @@ maintainers:
)
assert.Assert(t, fs.Equal(tmpdir.Path(), manifest))
}

func TestInitRelativeVolumePath(t *testing.T) {
for _, composeData := range []string{`
version: '3.7'
services:
nginx:
image: nginx
volumes:
- ./foo:/data
`,
`
version: '3.7'
services:
nginx:
image: nginx
volumes:
- type: bind
source: ./foo
target: /data
`,
} {
inputDir := fs.NewDir(t, "app_input_",
fs.WithFile(internal.ComposeFileName, composeData),
)
defer inputDir.Remove()

appName := "my.dockerapp"
dir := fs.NewDir(t, "app_",
fs.WithDir(appName),
)
defer dir.Remove()

err := initFromComposeFile(nil, dir.Join(appName), inputDir.Join(internal.ComposeFileName))
assert.ErrorContains(t, err, "can't use relative path")
}
}

0 comments on commit 986e7e6

Please sign in to comment.