Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(runtime/docker): add drop kernel capabilities option to runtime flags #454

Merged
merged 6 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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