Test kubectl cp escape

This commit is contained in:
Tim Allclair 2019-04-12 18:37:53 -07:00 committed by Maciej Szulik
parent 1c5eed4233
commit a867b399af
No known key found for this signature in database
GPG Key ID: F15E55D276FA84C4

View File

@ -30,6 +30,7 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/require"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
@ -578,7 +579,6 @@ func TestBadTar(t *testing.T) {
t.Errorf("Error finding file: %v", err)
}
}
}
func TestClean(t *testing.T) {
@ -768,6 +768,163 @@ func TestValidate(t *testing.T) {
}
}
func TestUntar(t *testing.T) {
testdir, err := ioutil.TempDir("", "test-untar")
require.NoError(t, err)
defer os.RemoveAll(testdir)
t.Logf("Test base: %s", testdir)
const (
dest = "base"
)
type file struct {
path string
linkTarget string // For link types
expected string // Expect to find the file here (or not, if empty)
}
files := []file{{
// Absolute file within dest
path: filepath.Join(testdir, dest, "abs"),
expected: filepath.Join(testdir, dest, testdir, dest, "abs"),
}, { // Absolute file outside dest
path: filepath.Join(testdir, "abs-out"),
expected: filepath.Join(testdir, dest, testdir, "abs-out"),
}, { // Absolute nested file within dest
path: filepath.Join(testdir, dest, "nested/nest-abs"),
expected: filepath.Join(testdir, dest, testdir, dest, "nested/nest-abs"),
}, { // Absolute nested file outside dest
path: filepath.Join(testdir, dest, "nested/../../nest-abs-out"),
expected: filepath.Join(testdir, dest, testdir, "nest-abs-out"),
}, { // Relative file inside dest
path: "relative",
expected: filepath.Join(testdir, dest, "relative"),
}, { // Relative file outside dest
path: "../unrelative",
expected: filepath.Join(testdir, dest, "unrelative"),
}, { // Nested relative file inside dest
path: "nested/nest-rel",
expected: filepath.Join(testdir, dest, "nested/nest-rel"),
}, { // Nested relative file outside dest
path: "nested/../../nest-unrelative",
expected: filepath.Join(testdir, dest, "nest-unrelative"),
}}
mkExpectation := func(expected, suffix string) string {
if expected == "" {
return ""
}
return expected + suffix
}
links := []file{}
for _, f := range files {
links = append(links, file{
path: f.path + "-innerlink",
linkTarget: "link-target",
expected: mkExpectation(f.expected, "-innerlink"),
}, file{
path: f.path + "-innerlink-abs",
linkTarget: filepath.Join(testdir, dest, "link-target"),
expected: "",
}, file{
path: f.path + "-outerlink",
linkTarget: filepath.Join(backtick(f.path), "link-target"),
expected: "",
}, file{
path: f.path + "-outerlink-abs",
linkTarget: filepath.Join(testdir, "link-target"),
expected: "",
})
}
files = append(files, links...)
// Test back-tick escaping through a symlink.
files = append(files,
file{
path: "nested/again/back-link",
linkTarget: "../../nested",
expected: filepath.Join(testdir, dest, "nested/again/back-link"),
},
file{
path: "nested/again/back-link/../../../back-link-file",
expected: filepath.Join(testdir, dest, "back-link-file"),
})
// Test chaining back-tick symlinks.
files = append(files,
file{
path: "nested/back-link-first",
linkTarget: "../",
expected: filepath.Join(testdir, dest, "nested/back-link-first"),
},
file{
path: "nested/back-link-first/back-link-second",
linkTarget: "../",
expected: filepath.Join(testdir, dest, "back-link-second"),
},
file{
path: "nested/back-link-first/back-link-second/back-link-term",
})
buf := &bytes.Buffer{}
tw := tar.NewWriter(buf)
expectations := map[string]bool{}
for _, f := range files {
if f.expected != "" {
expectations[f.expected] = false
}
if f.linkTarget == "" {
hdr := &tar.Header{
Name: f.path,
Mode: 0666,
Size: int64(len(f.path)),
}
require.NoError(t, tw.WriteHeader(hdr), f.path)
_, err := tw.Write([]byte(f.path))
require.NoError(t, err, f.path)
} else {
hdr := &tar.Header{
Name: f.path,
Mode: int64(0777 | os.ModeSymlink),
Typeflag: tar.TypeSymlink,
Linkname: f.linkTarget,
}
require.NoError(t, tw.WriteHeader(hdr), f.path)
}
}
tw.Close()
opts := NewCopyOptions(genericclioptions.NewTestIOStreamsDiscard())
require.NoError(t, opts.untarAll(buf, filepath.Join(testdir, dest), ""))
filepath.Walk(testdir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil // Ignore directories.
}
if _, ok := expectations[path]; !ok {
t.Errorf("Unexpected file at %s", path)
} else {
expectations[path] = true
}
return nil
})
for path, found := range expectations {
if !found {
t.Errorf("Missing expected file %s", path)
}
}
}
// backtick returns a path to one directory up from the target
func backtick(target string) string {
rel, _ := filepath.Rel(filepath.Dir(target), "../")
return rel
}
func createTmpFile(t *testing.T, filepath, data string) {
f, err := os.Create(filepath)
if err != nil {