Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
6f5e251f
Commit
6f5e251f
authored
Jul 12, 2019
by
Tim Allclair
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactors to kubernetes cp command
parent
be929daa
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
93 additions
and
71 deletions
+93
-71
BUILD
pkg/kubectl/cmd/cp/BUILD
+1
-0
cp.go
pkg/kubectl/cmd/cp/cp.go
+16
-18
cp_test.go
pkg/kubectl/cmd/cp/cp_test.go
+76
-53
No files found.
pkg/kubectl/cmd/cp/BUILD
View file @
6f5e251f
...
@@ -32,6 +32,7 @@ go_test(
...
@@ -32,6 +32,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/genericclioptions:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/genericclioptions:go_default_library",
"//staging/src/k8s.io/client-go/rest/fake:go_default_library",
"//staging/src/k8s.io/client-go/rest/fake:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
],
],
)
)
...
...
pkg/kubectl/cmd/cp/cp.go
View file @
6f5e251f
...
@@ -436,9 +436,14 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
...
@@ -436,9 +436,14 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
// basic file information
// basic file information
mode
:=
header
.
FileInfo
()
.
Mode
()
mode
:=
header
.
FileInfo
()
.
Mode
()
destFileName
:=
path
.
Join
(
destDir
,
header
.
Name
[
len
(
prefix
)
:
])
destFileName
:=
filepath
.
Join
(
destDir
,
header
.
Name
[
len
(
prefix
)
:
])
baseName
:=
path
.
Dir
(
destFileName
)
if
!
isDestRelative
(
destDir
,
destFileName
)
{
fmt
.
Fprintf
(
o
.
IOStreams
.
ErrOut
,
"warning: file %q is outside target destination, skipping
\n
"
,
destFileName
)
continue
}
baseName
:=
filepath
.
Dir
(
destFileName
)
if
err
:=
os
.
MkdirAll
(
baseName
,
0755
);
err
!=
nil
{
if
err
:=
os
.
MkdirAll
(
baseName
,
0755
);
err
!=
nil
{
return
err
return
err
}
}
...
@@ -452,15 +457,14 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
...
@@ -452,15 +457,14 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
// We need to ensure that the destination file is always within boundries
// We need to ensure that the destination file is always within boundries
// of the destination directory. This prevents any kind of path traversal
// of the destination directory. This prevents any kind of path traversal
// from within tar archive.
// from within tar archive.
dir
,
file
:=
filepath
.
Split
(
destFileName
)
evaledPath
,
err
:=
filepath
.
EvalSymlinks
(
baseName
)
evaledPath
,
err
:=
filepath
.
EvalSymlinks
(
dir
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
// For scrutiny we verify both the actual destination as well as we follow
// For scrutiny we verify both the actual destination as well as we follow
// all the links that might lead outside of the destination directory.
// all the links that might lead outside of the destination directory.
if
!
isDestRelative
(
destDir
,
destFileName
)
||
!
isDestRelative
(
destDir
,
filepath
.
Join
(
evaledPath
,
file
))
{
if
!
isDestRelative
(
destDir
,
filepath
.
Join
(
evaledPath
,
filepath
.
Base
(
destFileName
)
))
{
fmt
.
Fprintf
(
o
.
IOStreams
.
ErrOut
,
"warning:
link %q is pointing to %q which is outside target destination, skipping
\n
"
,
destFileName
,
header
.
Linkn
ame
)
fmt
.
Fprintf
(
o
.
IOStreams
.
ErrOut
,
"warning:
file %q is outside target destination, skipping
\n
"
,
destFileN
ame
)
continue
continue
}
}
...
@@ -469,7 +473,11 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
...
@@ -469,7 +473,11 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
// We need to ensure that the link destination is always within boundries
// We need to ensure that the link destination is always within boundries
// of the destination directory. This prevents any kind of path traversal
// of the destination directory. This prevents any kind of path traversal
// from within tar archive.
// from within tar archive.
if
!
isDestRelative
(
destDir
,
linkJoin
(
destFileName
,
linkname
))
{
linkTarget
:=
linkname
if
!
filepath
.
IsAbs
(
linkname
)
{
linkTarget
=
filepath
.
Join
(
evaledPath
,
linkname
)
}
if
!
isDestRelative
(
destDir
,
linkTarget
)
{
fmt
.
Fprintf
(
o
.
IOStreams
.
ErrOut
,
"warning: link %q is pointing to %q which is outside target destination, skipping
\n
"
,
destFileName
,
header
.
Linkname
)
fmt
.
Fprintf
(
o
.
IOStreams
.
ErrOut
,
"warning: link %q is pointing to %q which is outside target destination, skipping
\n
"
,
destFileName
,
header
.
Linkname
)
continue
continue
}
}
...
@@ -494,20 +502,10 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
...
@@ -494,20 +502,10 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
return
nil
return
nil
}
}
// linkJoin joins base and link to get the final path to be created.
// It will consider whether link is an absolute path or not when returning result.
func
linkJoin
(
base
,
link
string
)
string
{
if
filepath
.
IsAbs
(
link
)
{
return
link
}
return
filepath
.
Join
(
filepath
.
Dir
(
base
),
link
)
}
// isDestRelative returns true if dest is pointing outside the base directory,
// isDestRelative returns true if dest is pointing outside the base directory,
// false otherwise.
// false otherwise.
func
isDestRelative
(
base
,
dest
string
)
bool
{
func
isDestRelative
(
base
,
dest
string
)
bool
{
fullPath
:=
dest
relative
,
err
:=
filepath
.
Rel
(
base
,
dest
)
relative
,
err
:=
filepath
.
Rel
(
base
,
fullPath
)
if
err
!=
nil
{
if
err
!=
nil
{
return
false
return
false
}
}
...
...
pkg/kubectl/cmd/cp/cp_test.go
View file @
6f5e251f
...
@@ -30,6 +30,7 @@ import (
...
@@ -30,6 +30,7 @@ import (
"strings"
"strings"
"testing"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
"k8s.io/api/core/v1"
"k8s.io/api/core/v1"
...
@@ -745,9 +746,7 @@ func TestUntar(t *testing.T) {
...
@@ -745,9 +746,7 @@ func TestUntar(t *testing.T) {
defer
os
.
RemoveAll
(
testdir
)
defer
os
.
RemoveAll
(
testdir
)
t
.
Logf
(
"Test base: %s"
,
testdir
)
t
.
Logf
(
"Test base: %s"
,
testdir
)
const
(
basedir
:=
filepath
.
Join
(
testdir
,
"base"
)
dest
=
"base"
)
type
file
struct
{
type
file
struct
{
path
string
path
string
...
@@ -756,26 +755,26 @@ func TestUntar(t *testing.T) {
...
@@ -756,26 +755,26 @@ func TestUntar(t *testing.T) {
}
}
files
:=
[]
file
{{
files
:=
[]
file
{{
// Absolute file within dest
// Absolute file within dest
path
:
filepath
.
Join
(
testdir
,
dest
,
"abs"
),
path
:
filepath
.
Join
(
basedir
,
"abs"
),
expected
:
filepath
.
Join
(
testdir
,
dest
,
testdir
,
dest
,
"abs"
),
expected
:
filepath
.
Join
(
basedir
,
basedir
,
"abs"
),
},
{
// Absolute file outside dest
},
{
// Absolute file outside dest
path
:
filepath
.
Join
(
testdir
,
"abs-out"
),
path
:
filepath
.
Join
(
testdir
,
"abs-out"
),
expected
:
filepath
.
Join
(
testdir
,
dest
,
testdir
,
"abs-out"
),
expected
:
filepath
.
Join
(
basedir
,
testdir
,
"abs-out"
),
},
{
// Absolute nested file within dest
},
{
// Absolute nested file within dest
path
:
filepath
.
Join
(
testdir
,
dest
,
"nested/nest-abs"
),
path
:
filepath
.
Join
(
basedir
,
"nested/nest-abs"
),
expected
:
filepath
.
Join
(
testdir
,
dest
,
testdir
,
dest
,
"nested/nest-abs"
),
expected
:
filepath
.
Join
(
basedir
,
basedir
,
"nested/nest-abs"
),
},
{
// Absolute nested file outside dest
},
{
// Absolute nested file outside dest
path
:
filepath
.
Join
(
testdir
,
dest
,
"nested/../../nest-abs-out"
),
path
:
filepath
.
Join
(
basedir
,
"nested/../../nest-abs-out"
),
expected
:
filepath
.
Join
(
testdir
,
dest
,
testdir
,
"nest-abs-out"
),
expected
:
filepath
.
Join
(
basedir
,
testdir
,
"nest-abs-out"
),
},
{
// Relative file inside dest
},
{
// Relative file inside dest
path
:
"relative"
,
path
:
"relative"
,
expected
:
filepath
.
Join
(
testdir
,
dest
,
"relative"
),
expected
:
filepath
.
Join
(
basedir
,
"relative"
),
},
{
// Relative file outside dest
},
{
// Relative file outside dest
path
:
"../unrelative"
,
path
:
"../unrelative"
,
expected
:
""
,
expected
:
""
,
},
{
// Nested relative file inside dest
},
{
// Nested relative file inside dest
path
:
"nested/nest-rel"
,
path
:
"nested/nest-rel"
,
expected
:
filepath
.
Join
(
testdir
,
dest
,
"nested/nest-rel"
),
expected
:
filepath
.
Join
(
basedir
,
"nested/nest-rel"
),
},
{
// Nested relative file outside dest
},
{
// Nested relative file outside dest
path
:
"nested/../../nest-unrelative"
,
path
:
"nested/../../nest-unrelative"
,
expected
:
""
,
expected
:
""
,
...
@@ -787,10 +786,11 @@ func TestUntar(t *testing.T) {
...
@@ -787,10 +786,11 @@ func TestUntar(t *testing.T) {
}
}
return
expected
+
suffix
return
expected
+
suffix
}
}
mkBacktickExpectation
:=
func
(
path
,
expected
,
suffix
string
)
string
{
mkBacklinkExpectation
:=
func
(
expected
,
suffix
string
)
string
{
linkTarget
:=
filepath
.
Join
(
backtick
(
path
),
"link-target"
)
// "resolve" the back link relative to the expectation
baseDir
:=
filepath
.
Join
(
testdir
,
dest
)
targetDir
:=
filepath
.
Dir
(
filepath
.
Dir
(
expected
))
if
!
isDestRelative
(
baseDir
,
linkJoin
(
filepath
.
Join
(
baseDir
,
path
),
linkTarget
))
{
// If the "resolved" target is not nested in basedir, it is escaping.
if
!
filepath
.
HasPrefix
(
targetDir
,
basedir
)
{
return
""
return
""
}
}
return
expected
+
suffix
return
expected
+
suffix
...
@@ -803,17 +803,27 @@ func TestUntar(t *testing.T) {
...
@@ -803,17 +803,27 @@ func TestUntar(t *testing.T) {
expected
:
mkExpectation
(
f
.
expected
,
"-innerlink"
),
expected
:
mkExpectation
(
f
.
expected
,
"-innerlink"
),
},
file
{
},
file
{
path
:
f
.
path
+
"-innerlink-abs"
,
path
:
f
.
path
+
"-innerlink-abs"
,
linkTarget
:
filepath
.
Join
(
testdir
,
dest
,
"link-target"
),
linkTarget
:
filepath
.
Join
(
basedir
,
"link-target"
),
expected
:
mkExpectation
(
f
.
expected
,
"-innerlink-abs"
),
expected
:
mkExpectation
(
f
.
expected
,
"-innerlink-abs"
),
},
file
{
},
file
{
path
:
f
.
path
+
"-
outer
link"
,
path
:
f
.
path
+
"-
back
link"
,
linkTarget
:
filepath
.
Join
(
backtick
(
f
.
path
)
,
"link-target"
),
linkTarget
:
filepath
.
Join
(
".."
,
"link-target"
),
expected
:
mkBack
tickExpectation
(
f
.
path
,
f
.
expected
,
"-outer
link"
),
expected
:
mkBack
linkExpectation
(
f
.
expected
,
"-back
link"
),
},
file
{
},
file
{
path
:
f
.
path
+
"-outerlink-abs"
,
path
:
f
.
path
+
"-outerlink-abs"
,
linkTarget
:
filepath
.
Join
(
testdir
,
"link-target"
),
linkTarget
:
filepath
.
Join
(
testdir
,
"link-target"
),
expected
:
""
,
expected
:
""
,
})
})
if
f
.
expected
!=
""
{
// outerlink is the number of backticks to escape to testdir
outerlink
,
_
:=
filepath
.
Rel
(
f
.
expected
,
testdir
)
links
=
append
(
links
,
file
{
path
:
f
.
path
+
"outerlink"
,
linkTarget
:
filepath
.
Join
(
outerlink
,
"link-target"
),
expected
:
""
,
})
}
}
}
files
=
append
(
files
,
links
...
)
files
=
append
(
files
,
links
...
)
...
@@ -822,11 +832,11 @@ func TestUntar(t *testing.T) {
...
@@ -822,11 +832,11 @@ func TestUntar(t *testing.T) {
file
{
file
{
path
:
"nested/again/back-link"
,
path
:
"nested/again/back-link"
,
linkTarget
:
"../../nested"
,
linkTarget
:
"../../nested"
,
expected
:
filepath
.
Join
(
testdir
,
dest
,
"nested/again/back-link"
),
expected
:
filepath
.
Join
(
basedir
,
"nested/again/back-link"
),
},
},
file
{
file
{
path
:
"nested/again/back-link/../../../back-link-file"
,
path
:
"nested/again/back-link/../../../back-link-file"
,
expected
:
filepath
.
Join
(
testdir
,
dest
,
"back-link-file"
),
expected
:
filepath
.
Join
(
basedir
,
"back-link-file"
),
})
})
// Test chaining back-tick symlinks.
// Test chaining back-tick symlinks.
...
@@ -834,20 +844,11 @@ func TestUntar(t *testing.T) {
...
@@ -834,20 +844,11 @@ func TestUntar(t *testing.T) {
file
{
file
{
path
:
"nested/back-link-first"
,
path
:
"nested/back-link-first"
,
linkTarget
:
"../"
,
linkTarget
:
"../"
,
expected
:
filepath
.
Join
(
testdir
,
dest
,
"nested/back-link-first"
),
expected
:
filepath
.
Join
(
basedir
,
"nested/back-link-first"
),
},
},
file
{
file
{
path
:
"nested/back-link-first/back-link-second"
,
path
:
"nested/back-link-first/back-link-second"
,
linkTarget
:
"../"
,
linkTarget
:
"../"
,
expected
:
filepath
.
Join
(
testdir
,
dest
,
"back-link-second"
),
},
file
{
// This case is chaining together symlinks that step back, so that
// if you just look at the target relative to the path it appears
// inside the destination directory, but if you actually follow each
// step of the path you end up outside the destination directory.
path
:
"nested/back-link-first/back-link-second/back-link-term"
,
linkTarget
:
""
,
expected
:
""
,
expected
:
""
,
})
})
...
@@ -887,9 +888,11 @@ func TestUntar(t *testing.T) {
...
@@ -887,9 +888,11 @@ func TestUntar(t *testing.T) {
}
}
tw
.
Close
()
tw
.
Close
()
opts
:=
NewCopyOptions
(
genericclioptions
.
NewTestIOStreamsDiscard
())
// Capture warnings to stderr for debugging.
output
:=
(
*
testWriter
)(
t
)
opts
:=
NewCopyOptions
(
genericclioptions
.
IOStreams
{
In
:
&
bytes
.
Buffer
{},
Out
:
output
,
ErrOut
:
output
})
require
.
NoError
(
t
,
opts
.
untarAll
(
buf
,
filepath
.
Join
(
testdir
,
dest
),
""
))
require
.
NoError
(
t
,
opts
.
untarAll
(
buf
,
filepath
.
Join
(
basedir
),
""
))
filepath
.
Walk
(
testdir
,
func
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
filepath
.
Walk
(
testdir
,
func
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -912,10 +915,36 @@ func TestUntar(t *testing.T) {
...
@@ -912,10 +915,36 @@ func TestUntar(t *testing.T) {
}
}
}
}
// backtick returns a path to one directory up from the target
func
TestUntar_SingleFile
(
t
*
testing
.
T
)
{
func
backtick
(
target
string
)
string
{
testdir
,
err
:=
ioutil
.
TempDir
(
""
,
"test-untar"
)
rel
:=
filepath
.
Join
(
filepath
.
Dir
(
target
),
"../"
)
require
.
NoError
(
t
,
err
)
return
rel
defer
os
.
RemoveAll
(
testdir
)
dest
:=
filepath
.
Join
(
testdir
,
"target"
)
buf
:=
&
bytes
.
Buffer
{}
tw
:=
tar
.
NewWriter
(
buf
)
const
(
srcName
=
"source"
content
=
"file contents"
)
hdr
:=
&
tar
.
Header
{
Name
:
srcName
,
Mode
:
0666
,
Size
:
int64
(
len
(
content
)),
}
require
.
NoError
(
t
,
tw
.
WriteHeader
(
hdr
))
_
,
err
=
tw
.
Write
([]
byte
(
content
))
require
.
NoError
(
t
,
err
)
tw
.
Close
()
// Capture warnings to stderr for debugging.
output
:=
(
*
testWriter
)(
t
)
opts
:=
NewCopyOptions
(
genericclioptions
.
IOStreams
{
In
:
&
bytes
.
Buffer
{},
Out
:
output
,
ErrOut
:
output
})
require
.
NoError
(
t
,
opts
.
untarAll
(
buf
,
filepath
.
Join
(
dest
),
srcName
))
cmpFileData
(
t
,
dest
,
content
)
}
}
func
createTmpFile
(
t
*
testing
.
T
,
filepath
,
data
string
)
{
func
createTmpFile
(
t
*
testing
.
T
,
filepath
,
data
string
)
{
...
@@ -933,20 +962,14 @@ func createTmpFile(t *testing.T, filepath, data string) {
...
@@ -933,20 +962,14 @@ func createTmpFile(t *testing.T, filepath, data string) {
}
}
func
cmpFileData
(
t
*
testing
.
T
,
filePath
,
data
string
)
{
func
cmpFileData
(
t
*
testing
.
T
,
filePath
,
data
string
)
{
f
,
err
:=
os
.
Open
(
filePath
)
actual
,
err
:=
ioutil
.
ReadFile
(
filePath
)
if
err
!=
nil
{
require
.
NoError
(
t
,
err
)
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
assert
.
EqualValues
(
t
,
data
,
actual
)
}
}
defer
f
.
Close
()
type
testWriter
testing
.
T
buff
:=
&
bytes
.
Buffer
{}
if
_
,
err
:=
io
.
Copy
(
buff
,
f
);
err
!=
nil
{
func
(
t
*
testWriter
)
Write
(
p
[]
byte
)
(
n
int
,
err
error
)
{
t
.
Fatal
(
err
)
t
.
Logf
(
string
(
p
))
}
return
len
(
p
),
nil
if
err
:=
f
.
Close
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
data
!=
string
(
buff
.
Bytes
())
{
t
.
Fatalf
(
"expected: %s, saw: %s"
,
data
,
string
(
buff
.
Bytes
()))
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment