Skip to content

Commit

Permalink
feat(runtime/docker): add drop kernel capabilities option to runtime …
Browse files Browse the repository at this point in the history
…flags (#454)

* capabilities

* docker compose revert + opencontainers version

* revert lots of go mod stuff

* fix copy pasta and add a test in opts
  • Loading branch information
ecrupper authored Apr 6, 2023
1 parent 41812a9 commit c76c2e4
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 8 deletions.
1 change: 1 addition & 0 deletions cmd/vela-worker/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func (w *Worker) exec(index int) error {
PodsTemplateName: w.Config.Runtime.PodsTemplateName,
PodsTemplateFile: w.Config.Runtime.PodsTemplateFile,
PrivilegedImages: w.Config.Runtime.PrivilegedImages,
DropCapabilities: w.Config.Runtime.DropCapabilities,
})
if err != nil {
return err
Expand Down
1 change: 1 addition & 0 deletions cmd/vela-worker/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func run(c *cli.Context) error {
PodsTemplateFile: c.Path("runtime.pods-template-file"),
HostVolumes: c.StringSlice("runtime.volumes"),
PrivilegedImages: c.StringSlice("runtime.privileged-images"),
DropCapabilities: c.StringSlice("runtime.drop-capabilities"),
},
// queue configuration
Queue: &queue.Setup{
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ require (
github.com/spf13/afero v1.9.4 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.2 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
Expand All @@ -106,7 +108,7 @@ require (
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/oauth2 v0.5.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
Expand Down
9 changes: 6 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,11 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
Expand Down Expand Up @@ -589,8 +592,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
Expand Down
2 changes: 1 addition & 1 deletion runtime/docker/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func (c *client) RunContainer(ctx context.Context, ctn *pipeline.Container, b *p
// allocate new container config from pipeline container
containerConf := ctnConfig(ctn)
// allocate new host config with volume data
hostConf := hostConfig(c.Logger, b.ID, ctn.Ulimits, c.config.Volumes)
hostConf := hostConfig(c.Logger, b.ID, ctn.Ulimits, c.config.Volumes, c.config.DropCapabilities)
// allocate new network config with container name
networkConf := netConfig(b.ID, ctn.Name)

Expand Down
2 changes: 2 additions & 0 deletions runtime/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ type config struct {
Images []string
// specifies a list of host volumes to use for the Docker client
Volumes []string
// specifies a list of kernel capabilities to drop for each Docker container
DropCapabilities []string
}

type client struct {
Expand Down
12 changes: 12 additions & 0 deletions runtime/docker/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,15 @@ func WithPrivilegedImages(images []string) ClientOpt {
return nil
}
}

// WithDropCapabilities sets the kernel capabilities to drop from each container in the runtime client for Docker.
func WithDropCapabilities(caps []string) ClientOpt {
return func(c *client) error {
c.Logger.Trace("configuring dropped capabilities in docker runtime client")

// set the runtime dropped kernel capabilities in the docker client
c.config.DropCapabilities = caps

return nil
}
}
37 changes: 37 additions & 0 deletions runtime/docker/opts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,40 @@ func TestDocker_ClientOpt_WithLogger(t *testing.T) {
})
}
}

func TestDocker_ClientOpt_WithDropCapabilities(t *testing.T) {
// setup tests
tests := []struct {
name string
caps []string
want []string
}{
{
name: "defined",
caps: []string{"CAP_CHOWN", "CAP_DAC_OVERRIDE"},
want: []string{"CAP_CHOWN", "CAP_DAC_OVERRIDE"},
},
{
name: "empty",
caps: []string{},
want: []string{},
},
}

// run tests
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
_service, err := New(
WithDropCapabilities(test.caps),
)

if err != nil {
t.Errorf("WithDropCapabilities returned err: %v", err)
}

if !reflect.DeepEqual(_service.config.DropCapabilities, test.want) {
t.Errorf("WithDropCapabilities is %v, want %v", _service.config.DropCapabilities, test.want)
}
})
}
}
3 changes: 2 additions & 1 deletion runtime/docker/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (c *client) RemoveVolume(ctx context.Context, b *pipeline.Build) error {

// hostConfig is a helper function to generate the host config
// with Ulimit and volume specifications for a container.
func hostConfig(logger *logrus.Entry, id string, ulimits pipeline.UlimitSlice, volumes []string) *container.HostConfig {
func hostConfig(logger *logrus.Entry, id string, ulimits pipeline.UlimitSlice, volumes []string, dropCaps []string) *container.HostConfig {
logger.Tracef("creating mount for default volume %s", id)

// create default mount for pipeline volume
Expand Down Expand Up @@ -146,5 +146,6 @@ func hostConfig(logger *logrus.Entry, id string, ulimits pipeline.UlimitSlice, v
Mounts: mounts,
// https://pkg.go.dev/github.com/docker/docker/api/types/container#Resources.Ulimits
Resources: resources,
CapDrop: dropCaps,
}
}
6 changes: 6 additions & 0 deletions runtime/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,10 @@ var Flags = []cli.Flag{
Name: "runtime.volumes",
Usage: "list of host volumes to mount for the runtime",
},
&cli.StringSliceFlag{
EnvVars: []string{"VELA_RUNTIME_DROP_CAPABILITIES", "RUNTIME_DROP_CAPABILITIES"},
FilePath: "/vela/runtime/drop_capabilities",
Name: "runtime.drop-capabilities",
Usage: "list of kernel capabilities to drop from container privileges (only used by Docker)",
},
}
24 changes: 23 additions & 1 deletion runtime/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ package runtime

import (
"fmt"
"strings"

"github.com/go-vela/worker/runtime/docker"
"github.com/go-vela/worker/runtime/kubernetes"

"github.com/docker/docker/oci/caps"

"github.com/go-vela/types/constants"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -42,6 +45,8 @@ type Setup struct {
PodsTemplateFile string
// specifies a list of privileged images to use for the runtime client
PrivilegedImages []string
// specifies a list of kernel capabilities to drop from container (only used by Docker)
DropCapabilities []string
}

// Docker creates and returns a Vela engine capable of
Expand All @@ -53,6 +58,7 @@ func (s *Setup) Docker() (Engine, error) {
docker.WithHostVolumes(s.HostVolumes),
docker.WithPrivilegedImages(s.PrivilegedImages),
docker.WithLogger(s.Logger),
docker.WithDropCapabilities(s.DropCapabilities),
}

if s.Mock {
Expand Down Expand Up @@ -108,7 +114,23 @@ func (s *Setup) Validate() error {
// process the secret driver being provided
switch s.Driver {
case constants.DriverDocker:
break
// check to make sure drop capabilities is configured correctly
if len(s.DropCapabilities) != 0 {
for _, configCap := range s.DropCapabilities {
valid := false

for _, validCap := range caps.GetAllCapabilities() {
if strings.EqualFold(configCap, validCap) {
valid = true
break
}
}

if !valid {
return fmt.Errorf("invalid capability %s provided in RUNTIME_DROP_CAPABILITIES", configCap)
}
}
}
case constants.DriverKubernetes:
// check if a runtime namespace was provided
if len(s.Namespace) == 0 {
Expand Down
11 changes: 10 additions & 1 deletion runtime/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,16 @@ func TestRuntime_Validate(t *testing.T) {
name: "docker driver",
failure: false,
setup: &Setup{
Driver: constants.DriverDocker,
Driver: constants.DriverDocker,
DropCapabilities: []string{"CAP_DAC_OVERRIDE"},
},
},
{
name: "docker driver bad cap",
failure: true,
setup: &Setup{
Driver: constants.DriverDocker,
DropCapabilities: []string{"BAD"},
},
},
{
Expand Down

0 comments on commit c76c2e4

Please sign in to comment.