Skip to content

Commit

Permalink
feat!: gate privileged images behind trusted repos (#391)
Browse files Browse the repository at this point in the history
  • Loading branch information
plyr4 committed Nov 9, 2022
1 parent a400390 commit 88acdef
Show file tree
Hide file tree
Showing 13 changed files with 801 additions and 27 deletions.
28 changes: 15 additions & 13 deletions cmd/vela-worker/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,21 @@ func (w *Worker) exec(index int) error {
//
// https://godoc.org/github.com/go-vela/worker/executor#New
_executor, err := executor.New(&executor.Setup{
Logger: logger,
Mock: w.Config.Mock,
Driver: w.Config.Executor.Driver,
LogMethod: w.Config.Executor.LogMethod,
MaxLogSize: w.Config.Executor.MaxLogSize,
Client: w.VelaClient,
Hostname: w.Config.API.Address.Hostname(),
Runtime: w.Runtime,
Build: item.Build,
Pipeline: item.Pipeline.Sanitize(w.Config.Runtime.Driver),
Repo: item.Repo,
User: item.User,
Version: v.Semantic(),
Logger: logger,
Mock: w.Config.Mock,
Driver: w.Config.Executor.Driver,
LogMethod: w.Config.Executor.LogMethod,
MaxLogSize: w.Config.Executor.MaxLogSize,
EnforceTrustedRepos: w.Config.Executor.EnforceTrustedRepos,
PrivilegedImages: w.Config.Runtime.PrivilegedImages,
Client: w.VelaClient,
Hostname: w.Config.API.Address.Hostname(),
Runtime: w.Runtime,
Build: item.Build,
Pipeline: item.Pipeline.Sanitize(w.Config.Runtime.Driver),
Repo: item.Repo,
User: item.User,
Version: v.Semantic(),
})

// add the executor to the worker
Expand Down
7 changes: 4 additions & 3 deletions cmd/vela-worker/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,10 @@ func run(c *cli.Context) error {
CheckIn: c.Duration("checkIn"),
// executor configuration
Executor: &executor.Setup{
Driver: c.String("executor.driver"),
LogMethod: c.String("executor.log_method"),
MaxLogSize: c.Uint("executor.max_log_size"),
Driver: c.String("executor.driver"),
LogMethod: c.String("executor.log_method"),
MaxLogSize: c.Uint("executor.max_log_size"),
EnforceTrustedRepos: c.Bool("executor.enforce-trusted-repos"),
},
// logger configuration
Logger: &Logger{
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ services:
VELA_LOG_LEVEL: trace
VELA_RUNTIME_DRIVER: docker
VELA_RUNTIME_PRIVILEGED_IMAGES: 'target/vela-docker'
VELA_EXECUTOR_ENFORCE_TRUSTED_REPOS: 'true'
VELA_SERVER_ADDR: 'http://server:8080'
VELA_SERVER_SECRET: 'zB7mrKDTZqNeNTD8z47yG4DHywspAh'
WORKER_ADDR: 'http://worker:8080'
Expand Down
7 changes: 7 additions & 0 deletions executor/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,11 @@ var Flags = []cli.Flag{
Name: "executor.max_log_size",
Usage: "maximum log size (in bytes)",
},
&cli.BoolFlag{
EnvVars: []string{"VELA_EXECUTOR_ENFORCE_TRUSTED_REPOS", "EXECUTOR_ENFORCE_TRUSTED_REPOS"},
FilePath: "/vela/executor/enforce_trusted_repos",
Name: "executor.enforce-trusted-repos",
Usage: "enforce trusted repo restrictions for privileged images",
Value: true,
},
}
70 changes: 70 additions & 0 deletions executor/linux/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import (
"golang.org/x/sync/errgroup"

"github.com/go-vela/types/constants"
"github.com/go-vela/types/library"
"github.com/go-vela/worker/internal/build"
"github.com/go-vela/worker/internal/image"
"github.com/go-vela/worker/internal/step"
)

Expand Down Expand Up @@ -42,6 +44,74 @@ func (c *client) CreateBuild(ctx context.Context) error {
return fmt.Errorf("unable to upload build state: %w", c.err)
}

// before setting up the build, enforce repo.trusted is set for pipelines containing privileged images
// this configuration is set as an executor flag
if c.enforceTrustedRepos {
// check if pipeline steps contain privileged images
// assume no privileged images are in use
containsPrivilegedImages := false

// group steps services and stages together
containers := c.pipeline.Steps

containers = append(containers, c.pipeline.Services...)
for _, stage := range c.pipeline.Stages {
containers = append(containers, stage.Steps...)
}

for _, container := range containers {
// TODO: remove hardcoded reference
if container.Image == "#init" {
continue
}

for _, pattern := range c.privilegedImages {
privileged, err := image.IsPrivilegedImage(container.Image, pattern)
if err != nil {
return fmt.Errorf("could not verify if image %s is privileged", container.Image)
}

if privileged {
containsPrivilegedImages = true
}
}
}

// check if this build should be denied
if (containsPrivilegedImages) && !(c.repo != nil && c.repo.GetTrusted()) {
// deny the build, clean build/steps, and return error
// populate the build error
e := "build denied, repo must be trusted in order to run privileged images"
c.build.SetError(e)
// set the build status to error
c.build.SetStatus(constants.StatusError)

steps := c.pipeline.Steps
for _, stage := range c.pipeline.Stages {
steps = append(containers, stage.Steps...)
}

// update all preconfigured steps to the correct status
for _, s := range steps {
// extract step
step := library.StepFromBuildContainer(c.build, s)
// status to use for preconfigured steps that are not ran
status := constants.StatusKilled
// set step status
step.SetStatus(status)
// send API call to update the step
//nolint:contextcheck // ignore passing context
_, _, err := c.Vela.Step.Update(c.repo.GetOrg(), c.repo.GetName(), c.build.GetNumber(), step)
if err != nil {
// only log any step update errors to allow the return err to run
c.Logger.Errorf("unable to update step %s to status %s: %s", s.Name, status, err.Error())
}
}

return fmt.Errorf("build containing privileged images %s/%d denied, repo is not trusted", c.repo.GetFullName(), c.build.GetNumber())
}
}

// setup the runtime build
c.err = c.Runtime.SetupBuild(ctx, c.pipeline)
if c.err != nil {
Expand Down

0 comments on commit 88acdef

Please sign in to comment.