-
-
Notifications
You must be signed in to change notification settings - Fork 185
Expand file tree
/
Copy pathcommand_docker_test.go
More file actions
176 lines (141 loc) · 4.67 KB
/
Copy pathcommand_docker_test.go
File metadata and controls
176 lines (141 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//go:build docker
// +build docker
package command
import (
"os"
"sort"
"testing"
"github.com/stretchr/testify/assert"
)
// TestNsenterCommandWrapper is an integration-level test for nsenterCommandWrapper.
// It injects statFn (to control which /proc/1/ns/* files appear present) and verifies:
// - -T is never present in the assembled command (time namespace is never joined)
// - namespace flags from statFn are included when present
// - absent namespace flags are excluded
// - the setpriv/nsenter prefix ordering is unchanged
// - the user command appears at the end
//
//nolint:paralleltest
func TestNsenterCommandWrapper(t *testing.T) {
origStatFn := statFn
t.Cleanup(func() {
statFn = origStatFn
})
// presentNSFiles is the set of /proc/1/ns/* files that statFn will report as present.
// We choose a deterministic subset: mnt, net, pid.
presentNSFiles := map[string]bool{
"/proc/1/ns/mnt": true,
"/proc/1/ns/net": true,
"/proc/1/ns/pid": true,
}
// statFn stub: /usr/bin/nsenter always exists; only the listed ns files exist.
statFn = func(path string) (os.FileInfo, error) {
if path == "/usr/bin/nsenter" {
return nil, nil
}
if presentNSFiles[path] {
return nil, nil
}
return nil, os.ErrNotExist
}
// nsFlags that must always appear (from the present map above).
expectedNSFlags := []string{"-m", "-n", "-p"}
t.Run("present ns flags included and -T never present", func(t *testing.T) {
cmd, err := nsenterCommandWrapper(1000, 1000, []uint32{1000}, "/home/user", "/bin/sh")
assert.NoError(t, err)
// -T must never be present.
assert.NotContains(t, cmd, "-T")
// All namespace flags from statFn must be present.
for _, flag := range expectedNSFlags {
assert.Contains(t, cmd, flag)
}
// Flags for absent namespaces must NOT be present.
for _, absent := range []string{"-u", "-i", "-C"} {
assert.NotContains(t, cmd, absent)
}
// setpriv/nsenter prefix ordering: /bin/setpriv must come first,
// /usr/bin/nsenter must follow.
setprivIdx := indexOf(cmd, "/bin/setpriv")
nsenterIdx := indexOf(cmd, "/usr/bin/nsenter")
assert.NotEqual(t, -1, setprivIdx, "/bin/setpriv must be present")
assert.NotEqual(t, -1, nsenterIdx, "/usr/bin/nsenter must be present")
assert.Less(t, setprivIdx, nsenterIdx, "/bin/setpriv must precede /usr/bin/nsenter")
// The user command must appear at the end.
assert.Equal(t, "/bin/sh", cmd[len(cmd)-1])
})
t.Run("statFn controls which ns flags appear", func(t *testing.T) {
// Override statFn so only net is present.
statFn = func(path string) (os.FileInfo, error) {
if path == "/usr/bin/nsenter" || path == "/proc/1/ns/net" {
return nil, nil
}
return nil, os.ErrNotExist
}
cmd, err := nsenterCommandWrapper(1000, 1000, []uint32{1000}, "/home/user", "/bin/bash")
assert.NoError(t, err)
assert.Contains(t, cmd, "-n")
assert.NotContains(t, cmd, "-T")
for _, absent := range []string{"-m", "-u", "-i", "-p", "-C"} {
assert.NotContains(t, cmd, absent)
}
})
t.Run("multiple ns flags from statFn — no -T", func(t *testing.T) {
// Override statFn so mnt and uts are present.
statFn = func(path string) (os.FileInfo, error) {
if path == "/usr/bin/nsenter" || path == "/proc/1/ns/mnt" || path == "/proc/1/ns/uts" {
return nil, nil
}
return nil, os.ErrNotExist
}
cmd, err := nsenterCommandWrapper(1000, 1000, []uint32{1000}, "/home/user", "/bin/bash")
assert.NoError(t, err)
assert.Contains(t, cmd, "-m")
assert.Contains(t, cmd, "-u")
assert.NotContains(t, cmd, "-T")
for _, absent := range []string{"-i", "-n", "-p", "-C"} {
assert.NotContains(t, cmd, absent)
}
})
}
// indexOf returns the index of target in slice, or -1 if not found.
func indexOf(slice []string, target string) int {
for i, s := range slice {
if s == target {
return i
}
}
return -1
}
func TestNsenterArgs(t *testing.T) {
t.Run("all flags in present are forwarded unchanged", func(t *testing.T) {
present := map[string]string{
"mnt": "-m",
"uts": "-u",
"ipc": "-i",
"net": "-n",
"pid": "-p",
"cgroup": "-C",
}
args := nsenterArgs(present)
got := make([]string, len(args))
copy(got, args)
sort.Strings(got)
expected := []string{"-C", "-i", "-m", "-n", "-p", "-u"}
assert.Equal(t, expected, got)
})
t.Run("-T never appears regardless of input", func(t *testing.T) {
present := map[string]string{
"mnt": "-m",
"net": "-n",
}
args := nsenterArgs(present)
assert.NotContains(t, args, "-T")
assert.Contains(t, args, "-m")
assert.Contains(t, args, "-n")
})
t.Run("empty present returns empty slice", func(t *testing.T) {
present := map[string]string{}
args := nsenterArgs(present)
assert.Empty(t, args)
})
}