Skip to content

Commit b3b1fed

Browse files
authored
#44 Configurable linux capabilities (cap_add / cap_drop) (#45)
1 parent 70214eb commit b3b1fed

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,26 @@ config {
249249
}
250250
```
251251

252+
* **cap_add** - (Optional) A list of Linux capabilities as strings to pass to --cap-add.
253+
254+
```
255+
config {
256+
cap_add = [
257+
"SYS_TIME"
258+
]
259+
}
260+
```
261+
262+
* **cap_drop** - (Optional) A list of Linux capabilities as strings to pass to --cap-drop.
263+
264+
```
265+
config {
266+
cap_add = [
267+
"MKNOD"
268+
]
269+
}
270+
```
271+
252272
## Example job
253273

254274
```

config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ var (
5757
taskConfigSpec = hclspec.NewObject(map[string]*hclspec.Spec{
5858
"args": hclspec.NewAttr("args", "list(string)", false),
5959
"command": hclspec.NewAttr("command", "string", false),
60+
"cap_add": hclspec.NewAttr("cap_add", "list(string)", false),
61+
"cap_drop": hclspec.NewAttr("cap_drop", "list(string)", false),
6062
"entrypoint": hclspec.NewAttr("entrypoint", "string", false),
6163
"working_dir": hclspec.NewAttr("working_dir", "string", false),
6264
"hostname": hclspec.NewAttr("hostname", "string", false),
@@ -109,4 +111,6 @@ type TaskConfig struct {
109111
PortMap hclutils.MapStrInt `codec:"port_map"`
110112
Tmpfs []string `codec:"tmpfs"`
111113
Volumes []string `codec:"volumes"`
114+
CapAdd []string `codec:"cap_add"`
115+
CapDrop []string `codec:"cap_drop"`
112116
}

driver.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,8 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
431431
Volume: &allVolumes,
432432
Memory: &memoryLimit,
433433
CpuShares: &cpuShares,
434+
CapAdd: &driverConfig.CapAdd,
435+
CapDrop: &driverConfig.CapDrop,
434436
LogOpt: &logOpts,
435437
Hostname: &driverConfig.Hostname,
436438
Init: &driverConfig.Init,

driver_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,37 @@ func TestPodmanDriver_Tmpfs(t *testing.T) {
885885
require.Contains(t, tasklog, " tmpfs on /tmpdata2 type tmpfs ")
886886
}
887887

888+
// check default capabilities
889+
func TestPodmanDriver_DefaultCaps(t *testing.T) {
890+
taskCfg := newTaskConfig("", busyboxLongRunningCmd)
891+
inspectData := startDestroyInspect(t, taskCfg, "defaultcaps")
892+
893+
// a default container should not have SYS_TIME
894+
require.NotContains(t, inspectData.EffectiveCaps, "CAP_SYS_TIME")
895+
// a default container gets MKNOD cap
896+
require.Contains(t, inspectData.EffectiveCaps, "CAP_MKNOD")
897+
}
898+
899+
// check modified capabilities (CapAdd/CapDrop)
900+
func TestPodmanDriver_Caps(t *testing.T) {
901+
taskCfg := newTaskConfig("", busyboxLongRunningCmd)
902+
// cap_add = [
903+
// "SYS_TIME",
904+
// ]
905+
taskCfg.CapAdd = []string{"SYS_TIME"}
906+
// cap_drop = [
907+
// "MKNOD",
908+
// ]
909+
taskCfg.CapDrop = []string{"MKNOD"}
910+
911+
inspectData := startDestroyInspect(t, taskCfg, "caps")
912+
913+
// we added SYS_TIME, so we should see it in inspect
914+
require.Contains(t, inspectData.EffectiveCaps, "CAP_SYS_TIME")
915+
// we dropped CAP_MKNOD, so we should NOT see it in inspect
916+
require.NotContains(t, inspectData.EffectiveCaps, "CAP_MKNOD")
917+
}
918+
888919
// TestPodmanDriver_NetworkMode asserts we can specify different network modes
889920
// Default podman cni subnet 10.88.0.0/16
890921
func TestPodmanDriver_NetworkMode(t *testing.T) {
@@ -1029,3 +1060,42 @@ func getPodmanDriver(t *testing.T, harness *dtestutil.DriverHarness) *Driver {
10291060
require.True(t, ok)
10301061
return driver
10311062
}
1063+
1064+
// helper to start, destroy and inspect a long running container
1065+
func startDestroyInspect(t *testing.T, taskCfg TaskConfig, taskName string) iopodman.InspectContainerData {
1066+
if !tu.IsCI() {
1067+
t.Parallel()
1068+
}
1069+
1070+
task := &drivers.TaskConfig{
1071+
ID: uuid.Generate(),
1072+
Name: taskName,
1073+
AllocID: uuid.Generate(),
1074+
Resources: createBasicResources(),
1075+
}
1076+
require.NoError(t, task.EncodeConcreteDriverConfig(&taskCfg))
1077+
1078+
d := podmanDriverHarness(t, nil)
1079+
cleanup := d.MkAllocDir(task, true)
1080+
defer cleanup()
1081+
1082+
containerName := BuildContainerName(task)
1083+
1084+
_, _, err := d.StartTask(task)
1085+
require.NoError(t, err)
1086+
1087+
defer d.DestroyTask(task.ID, true)
1088+
1089+
// Attempt to wait
1090+
waitCh, err := d.WaitTask(context.Background(), task.ID)
1091+
require.NoError(t, err)
1092+
1093+
select {
1094+
case <-waitCh:
1095+
t.Fatalf("wait channel should not have received an exit result")
1096+
case <-time.After(time.Duration(tu.TestMultiplier()*2) * time.Second):
1097+
}
1098+
// inspect container to learn about the actual podman limits
1099+
inspectData := inspectContainer(t, containerName)
1100+
return inspectData
1101+
}

0 commit comments

Comments
 (0)