mirror of https://github.com/portainer/portainer
fix(stacks): allow root based compose file paths (#5564)
parent
1374e53dfa
commit
396a921b12
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -58,8 +59,8 @@ func (manager *ComposeStackManager) Up(ctx context.Context, stack *portainer.Sta
|
||||||
return errors.Wrap(err, "failed to create env file")
|
return errors.Wrap(err, "failed to create env file")
|
||||||
}
|
}
|
||||||
|
|
||||||
filePaths := append([]string{stack.EntryPoint}, stack.AdditionalFiles...)
|
filePaths := getStackFiles(stack)
|
||||||
return manager.deployer.Deploy(ctx, stack.ProjectPath, url, stack.Name, filePaths, envFilePath)
|
err = manager.deployer.Deploy(ctx, stack.ProjectPath, url, stack.Name, filePaths, envFilePath)
|
||||||
return errors.Wrap(err, "failed to deploy a stack")
|
return errors.Wrap(err, "failed to deploy a stack")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,9 +74,9 @@ func (manager *ComposeStackManager) Down(ctx context.Context, stack *portainer.S
|
||||||
defer proxy.Close()
|
defer proxy.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
filePaths := append([]string{stack.EntryPoint}, stack.AdditionalFiles...)
|
filePaths := getStackFiles(stack)
|
||||||
|
err = manager.deployer.Remove(ctx, stack.ProjectPath, url, stack.Name, filePaths)
|
||||||
return manager.deployer.Remove(ctx, stack.ProjectPath, url, stack.Name, filePaths)
|
return errors.Wrap(err, "failed to remove a stack")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NormalizeStackName returns a new stack name with unsupported characters replaced
|
// NormalizeStackName returns a new stack name with unsupported characters replaced
|
||||||
|
@ -116,3 +117,27 @@ func createEnvFile(stack *portainer.Stack) (string, error) {
|
||||||
|
|
||||||
return "stack.env", nil
|
return "stack.env", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getStackFiles returns list of stack's confile file paths.
|
||||||
|
// items in the list would be sanitized according to following criterias:
|
||||||
|
// 1. no empty paths
|
||||||
|
// 2. no "../xxx" paths that are trying to escape stack folder
|
||||||
|
// 3. no dir paths
|
||||||
|
// 4. root paths would be made relative
|
||||||
|
func getStackFiles(stack *portainer.Stack) []string {
|
||||||
|
paths := make([]string, 0, len(stack.AdditionalFiles)+1)
|
||||||
|
|
||||||
|
for _, p := range append([]string{stack.EntryPoint}, stack.AdditionalFiles...) {
|
||||||
|
if strings.HasPrefix(p, "/") {
|
||||||
|
p = `.` + p
|
||||||
|
}
|
||||||
|
|
||||||
|
if p == `` || p == `.` || strings.HasPrefix(p, `..`) || strings.HasSuffix(p, string(filepath.Separator)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
paths = append(paths, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
|
|
@ -64,3 +64,21 @@ func Test_createEnvFile(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_getStackFiles(t *testing.T) {
|
||||||
|
stack := &portainer.Stack{
|
||||||
|
EntryPoint: "./file", // picks entry point
|
||||||
|
AdditionalFiles: []string{
|
||||||
|
``, // ignores empty string
|
||||||
|
`.`, // ignores .
|
||||||
|
`..`, // ignores ..
|
||||||
|
`./dir/`, // ignrores paths that end with trailing /
|
||||||
|
`/with-root-prefix`, // replaces "root" based paths with relative
|
||||||
|
`./relative`, // keeps relative paths
|
||||||
|
`../escape`, // prevents dir escape
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
filePaths := getStackFiles(stack)
|
||||||
|
assert.ElementsMatch(t, filePaths, []string{`./file`, `./with-root-prefix`, `./relative`})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue