Skip to content

Commit 8418667

Browse files
authored
Merge pull request #107 from sipsma/jailbin
Support providing a different jailer binary.
2 parents a864c3c + 5ccde80 commit 8418667

File tree

2 files changed

+145
-114
lines changed

2 files changed

+145
-114
lines changed

jailer.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ type JailerConfig struct {
6666
// with the jailer is mostly Firecracker specific.
6767
ExecFile string
6868

69+
// JailerBinary specifies the jailer binary to be used for setting up the
70+
// Firecracker VM jail. If the value contains no path separators, it will
71+
// use the PATH environment variable to get the absolute path of the binary.
72+
// If the value contains path separators, the value will be used directly
73+
// to exec the jailer. This follows the same conventions as Golang's
74+
// os/exec.Command.
75+
//
76+
// If not specified it defaults to "jailer".
77+
JailerBinary string
78+
6979
// ChrootBaseDir represents the base folder where chroot jails are built. The
7080
// default is /srv/jailer
7181
ChrootBaseDir string
@@ -321,6 +331,14 @@ func jail(ctx context.Context, m *Machine, cfg *Config) error {
321331
WithStdout(stdout).
322332
WithStderr(stderr)
323333

334+
if jailerBinary := cfg.JailerCfg.JailerBinary; jailerBinary != "" {
335+
builder = builder.WithBin(jailerBinary)
336+
}
337+
338+
if netNS := cfg.JailerCfg.NetNS; netNS != "" {
339+
builder = builder.WithNetNS(netNS)
340+
}
341+
324342
if stdin := cfg.JailerCfg.Stdin; stdin != nil {
325343
builder = builder.WithStdin(stdin)
326344
}

jailer_test.go

Lines changed: 127 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -7,74 +7,106 @@ import (
77
"testing"
88
)
99

10-
func TestJailerBuilder(t *testing.T) {
11-
cases := []struct {
12-
name string
13-
jailerCfg JailerConfig
14-
expectedArgs []string
15-
jailerBin string
16-
}{
17-
{
18-
name: "required fields",
19-
jailerCfg: JailerConfig{
20-
ID: "my-test-id",
21-
UID: Int(123),
22-
GID: Int(100),
23-
NumaNode: Int(0),
24-
ExecFile: "/path/to/firecracker",
25-
},
26-
expectedArgs: []string{
27-
defaultJailerBin,
28-
"--id",
29-
"my-test-id",
30-
"--uid",
31-
"123",
32-
"--gid",
33-
"100",
34-
"--exec-file",
35-
"/path/to/firecracker",
36-
"--node",
37-
"0",
38-
"--seccomp-level",
39-
"0",
40-
},
10+
var testCases = []struct {
11+
name string
12+
jailerCfg JailerConfig
13+
expectedArgs []string
14+
expectedSockPath string
15+
}{
16+
{
17+
name: "required fields",
18+
jailerCfg: JailerConfig{
19+
ID: "my-test-id",
20+
UID: Int(123),
21+
GID: Int(100),
22+
NumaNode: Int(0),
23+
ChrootStrategy: NewNaiveChrootStrategy("path", "kernel-image-path"),
24+
ExecFile: "/path/to/firecracker",
4125
},
42-
{
43-
name: "optional fields",
44-
jailerBin: "foo",
45-
jailerCfg: JailerConfig{
46-
ID: "my-test-id",
47-
UID: Int(123),
48-
GID: Int(100),
49-
NumaNode: Int(1),
50-
ExecFile: "/path/to/firecracker",
51-
NetNS: "/net/namespace",
52-
ChrootBaseDir: "/tmp",
53-
SeccompLevel: SeccompLevelAdvanced,
54-
},
55-
expectedArgs: []string{
56-
"foo",
57-
"--id",
58-
"my-test-id",
59-
"--uid",
60-
"123",
61-
"--gid",
62-
"100",
63-
"--exec-file",
64-
"/path/to/firecracker",
65-
"--node",
66-
"1",
67-
"--chroot-base-dir",
68-
"/tmp",
69-
"--netns",
70-
"/net/namespace",
71-
"--seccomp-level",
72-
"2",
73-
},
26+
expectedArgs: []string{
27+
defaultJailerBin,
28+
"--id",
29+
"my-test-id",
30+
"--uid",
31+
"123",
32+
"--gid",
33+
"100",
34+
"--exec-file",
35+
"/path/to/firecracker",
36+
"--node",
37+
"0",
38+
"--seccomp-level",
39+
"0",
7440
},
75-
}
41+
expectedSockPath: filepath.Join(defaultJailerPath, "my-test-id", rootfsFolderName, "api.socket"),
42+
},
43+
{
44+
name: "other jailer binary name",
45+
jailerCfg: JailerConfig{
46+
ID: "my-test-id",
47+
UID: Int(123),
48+
GID: Int(100),
49+
NumaNode: Int(0),
50+
ChrootStrategy: NewNaiveChrootStrategy("path", "kernel-image-path"),
51+
ExecFile: "/path/to/firecracker",
52+
JailerBinary: "imprisoner",
53+
},
54+
expectedArgs: []string{
55+
"imprisoner",
56+
"--id",
57+
"my-test-id",
58+
"--uid",
59+
"123",
60+
"--gid",
61+
"100",
62+
"--exec-file",
63+
"/path/to/firecracker",
64+
"--node",
65+
"0",
66+
"--seccomp-level",
67+
"0",
68+
},
69+
expectedSockPath: filepath.Join(defaultJailerPath, "my-test-id", rootfsFolderName, "api.socket"),
70+
},
71+
{
72+
name: "optional fields",
73+
jailerCfg: JailerConfig{
74+
ID: "my-test-id",
75+
UID: Int(123),
76+
GID: Int(100),
77+
NumaNode: Int(1),
78+
ChrootStrategy: NewNaiveChrootStrategy("path", "kernel-image-path"),
79+
ExecFile: "/path/to/firecracker",
80+
NetNS: "/net/namespace",
81+
ChrootBaseDir: "/tmp",
82+
SeccompLevel: SeccompLevelAdvanced,
83+
JailerBinary: "/path/to/the/jailer",
84+
},
85+
expectedArgs: []string{
86+
"/path/to/the/jailer",
87+
"--id",
88+
"my-test-id",
89+
"--uid",
90+
"123",
91+
"--gid",
92+
"100",
93+
"--exec-file",
94+
"/path/to/firecracker",
95+
"--node",
96+
"1",
97+
"--chroot-base-dir",
98+
"/tmp",
99+
"--netns",
100+
"/net/namespace",
101+
"--seccomp-level",
102+
"2",
103+
},
104+
expectedSockPath: filepath.Join("/tmp", "firecracker", "my-test-id", rootfsFolderName, "api.socket"),
105+
},
106+
}
76107

77-
for _, c := range cases {
108+
func TestJailerBuilder(t *testing.T) {
109+
for _, c := range testCases {
78110
t.Run(c.name, func(t *testing.T) {
79111
b := NewJailerCommandBuilder().
80112
WithID(c.jailerCfg.ID).
@@ -84,8 +116,8 @@ func TestJailerBuilder(t *testing.T) {
84116
WithSeccompLevel(c.jailerCfg.SeccompLevel).
85117
WithExecFile(c.jailerCfg.ExecFile)
86118

87-
if len(c.jailerBin) > 0 {
88-
b = b.WithBin(c.jailerBin)
119+
if len(c.jailerCfg.JailerBinary) > 0 {
120+
b = b.WithBin(c.jailerCfg.JailerBinary)
89121
}
90122

91123
if len(c.jailerCfg.ChrootBaseDir) > 0 {
@@ -109,56 +141,37 @@ func TestJailerBuilder(t *testing.T) {
109141
}
110142

111143
func TestJail(t *testing.T) {
112-
m := &Machine{
113-
Handlers: Handlers{
114-
FcInit: defaultFcInitHandlerList,
115-
},
116-
}
117-
cfg := &Config{
118-
JailerCfg: JailerConfig{
119-
ID: "test-id",
120-
UID: Int(123),
121-
GID: Int(456),
122-
NumaNode: Int(0),
123-
ExecFile: "/path/to/firecracker",
124-
ChrootStrategy: NewNaiveChrootStrategy("path", "kernel-image-path"),
125-
},
126-
}
127-
jail(context.Background(), m, cfg)
128-
129-
expectedArgs := []string{
130-
defaultJailerBin,
131-
"--id",
132-
"test-id",
133-
"--uid",
134-
"123",
135-
"--gid",
136-
"456",
137-
"--exec-file",
138-
"/path/to/firecracker",
139-
"--node",
140-
"0",
141-
"--seccomp-level",
142-
"0",
143-
}
144+
for _, c := range testCases {
145+
t.Run(c.name, func(t *testing.T) {
146+
m := &Machine{
147+
Handlers: Handlers{
148+
FcInit: defaultFcInitHandlerList,
149+
},
150+
}
151+
cfg := &Config{
152+
JailerCfg: c.jailerCfg,
153+
}
154+
jail(context.Background(), m, cfg)
144155

145-
if e, a := expectedArgs, m.cmd.Args; !reflect.DeepEqual(e, a) {
146-
t.Errorf("expected args %v, but received %v", e, a)
147-
}
156+
if e, a := c.expectedArgs, m.cmd.Args; !reflect.DeepEqual(e, a) {
157+
t.Errorf("expected args %v, but received %v", e, a)
158+
}
148159

149-
if e, a := filepath.Join(defaultJailerPath, cfg.JailerCfg.ID, rootfsFolderName, "api.socket"), cfg.SocketPath; e != a {
150-
t.Errorf("expected socket path %q, but received %q", e, a)
151-
}
160+
if e, a := c.expectedSockPath, cfg.SocketPath; e != a {
161+
t.Errorf("expected socket path %q, but received %q", e, a)
162+
}
152163

153-
foundJailerHandler := false
154-
for _, handler := range m.Handlers.FcInit.list {
155-
if handler.Name == LinkFilesToRootFSHandlerName {
156-
foundJailerHandler = true
157-
break
158-
}
159-
}
164+
foundJailerHandler := false
165+
for _, handler := range m.Handlers.FcInit.list {
166+
if handler.Name == LinkFilesToRootFSHandlerName {
167+
foundJailerHandler = true
168+
break
169+
}
170+
}
160171

161-
if !foundJailerHandler {
162-
t.Errorf("did not find link files handler")
172+
if !foundJailerHandler {
173+
t.Errorf("did not find link files handler")
174+
}
175+
})
163176
}
164177
}

0 commit comments

Comments
 (0)