From 6b4d359737fcd37f1175ce126ffc1fb6d98953ed Mon Sep 17 00:00:00 2001 From: Joseph Benden Date: Fri, 4 Jun 2021 09:06:59 -0700 Subject: [PATCH] Add support for container kernel capabilities (#716) This patch adds two new command-line flags to specify one or more kernel capabilities to add or remove from the workflow containers. The command-line flag `--container-cap-add` allows for adding specific capabilities on the workflow containers; where as, The command-line flag `--container-cap-drop` allows for removing specific capabilities on the workflow containers. This was developed to specifically be able to add `SYS_PTRACE` to a workflow I maintain. It involves using this capability to monitor a make build, to then build a compilation database. Signed-off-by: Joseph Benden --- cmd/input.go | 2 ++ cmd/root.go | 4 ++++ pkg/container/docker_run.go | 10 ++++++---- pkg/runner/run_context.go | 2 +- pkg/runner/runner.go | 2 ++ pkg/runner/step_context.go | 4 ++-- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/cmd/input.go b/cmd/input.go index 3a91014..6cde2f0 100644 --- a/cmd/input.go +++ b/cmd/input.go @@ -32,6 +32,8 @@ type Input struct { noWorkflowRecurse bool useGitIgnore bool githubInstance string + containerCapAdd []string + containerCapDrop []string } func (i *Input) resolve(path string) string { diff --git a/cmd/root.go b/cmd/root.go index 05dbd72..bfde168 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -50,6 +50,8 @@ func Execute(ctx context.Context, version string) { rootCmd.Flags().BoolVar(&input.privileged, "privileged", false, "use privileged mode") rootCmd.Flags().StringVar(&input.usernsMode, "userns", "", "user namespace to use") rootCmd.Flags().BoolVar(&input.useGitIgnore, "use-gitignore", true, "Controls whether paths specified in .gitignore should be copied into container") + rootCmd.Flags().StringArrayVarP(&input.containerCapAdd, "container-cap-add", "", []string{}, "kernel capabilities to add to the workflow containers (e.g. --container-cap-add SYS_PTRACE)") + rootCmd.Flags().StringArrayVarP(&input.containerCapDrop, "container-cap-drop", "", []string{}, "kernel capabilities to remove from the workflow containers (e.g. --container-cap-drop SYS_PTRACE)") rootCmd.PersistentFlags().StringVarP(&input.actor, "actor", "a", "nektos/act", "user that triggered the event") rootCmd.PersistentFlags().StringVarP(&input.workflowsPath, "workflows", "W", "./.github/workflows/", "path to workflow file(s)") rootCmd.PersistentFlags().BoolVarP(&input.noWorkflowRecurse, "no-recurse", "", false, "Flag to disable running workflows from subdirectories of specified path in '--workflows'/'-W' flag") @@ -259,6 +261,8 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str ContainerDaemonSocket: input.containerDaemonSocket, UseGitIgnore: input.useGitIgnore, GitHubInstance: input.githubInstance, + ContainerCapAdd: input.containerCapAdd, + ContainerCapDrop: input.containerCapDrop, } r, err := runner.New(config) if err != nil { diff --git a/pkg/container/docker_run.go b/pkg/container/docker_run.go index 87f9f11..b050d3d 100644 --- a/pkg/container/docker_run.go +++ b/pkg/container/docker_run.go @@ -63,7 +63,7 @@ type FileEntry struct { // Container for managing docker run containers type Container interface { - Create() common.Executor + Create(capAdd []string, capDrop []string) common.Executor Copy(destPath string, files ...*FileEntry) common.Executor CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor Pull(forcePull bool) common.Executor @@ -100,14 +100,14 @@ func supportsContainerImagePlatform(cli *client.Client) bool { return constraint.Check(sv) } -func (cr *containerReference) Create() common.Executor { +func (cr *containerReference) Create(capAdd []string, capDrop []string) common.Executor { return common. NewDebugExecutor("%sdocker create image=%s platform=%s entrypoint=%+q cmd=%+q", logPrefix, cr.input.Image, cr.input.Platform, cr.input.Entrypoint, cr.input.Cmd). Then( common.NewPipelineExecutor( cr.connect(), cr.find(), - cr.create(), + cr.create(capAdd, capDrop), ).IfNot(common.Dryrun), ) } @@ -274,7 +274,7 @@ func (cr *containerReference) remove() common.Executor { } } -func (cr *containerReference) create() common.Executor { +func (cr *containerReference) create(capAdd []string, capDrop []string) common.Executor { return func(ctx context.Context) error { if cr.id != "" { return nil @@ -315,6 +315,8 @@ func (cr *containerReference) create() common.Executor { } } resp, err := cr.cli.ContainerCreate(ctx, config, &container.HostConfig{ + CapAdd: capAdd, + CapDrop: capDrop, Binds: input.Binds, Mounts: mounts, NetworkMode: container.NetworkMode(input.NetworkMode), diff --git a/pkg/runner/run_context.go b/pkg/runner/run_context.go index 26500c8..5c52cf3 100755 --- a/pkg/runner/run_context.go +++ b/pkg/runner/run_context.go @@ -148,7 +148,7 @@ func (rc *RunContext) startJobContainer() common.Executor { return common.NewPipelineExecutor( rc.JobContainer.Pull(rc.Config.ForcePull), rc.stopJobContainer(), - rc.JobContainer.Create(), + rc.JobContainer.Create(rc.Config.ContainerCapAdd, rc.Config.ContainerCapDrop), rc.JobContainer.Start(false), rc.JobContainer.UpdateFromEnv("/etc/environment", &rc.Env), rc.JobContainer.Exec([]string{"mkdir", "-m", "0777", "-p", ActPath}, rc.Env, "root"), diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 9d8b6f9..cf76d9d 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -40,6 +40,8 @@ type Config struct { ContainerDaemonSocket string // Path to Docker daemon socket UseGitIgnore bool // controls if paths in .gitignore should not be copied into container, default true GitHubInstance string // GitHub instance to use, default "github.com" + ContainerCapAdd []string // list of kernel capabilities to add to the containers + ContainerCapDrop []string // list of kernel capabilities to remove from the containers } // Resolves the equivalent host path inside the container diff --git a/pkg/runner/step_context.go b/pkg/runner/step_context.go index eeb822b..690614a 100644 --- a/pkg/runner/step_context.go +++ b/pkg/runner/step_context.go @@ -299,7 +299,7 @@ func (sc *StepContext) runUsesContainer() common.Executor { return common.NewPipelineExecutor( stepContainer.Pull(rc.Config.ForcePull), stepContainer.Remove().IfBool(!rc.Config.ReuseContainers), - stepContainer.Create(), + stepContainer.Create(rc.Config.ContainerCapAdd, rc.Config.ContainerCapDrop), stepContainer.Start(true), ).Finally( stepContainer.Remove().IfBool(!rc.Config.ReuseContainers), @@ -517,7 +517,7 @@ func (sc *StepContext) execAsDocker(ctx context.Context, action *model.Action, a prepImage, stepContainer.Pull(rc.Config.ForcePull), stepContainer.Remove().IfBool(!rc.Config.ReuseContainers), - stepContainer.Create(), + stepContainer.Create(rc.Config.ContainerCapAdd, rc.Config.ContainerCapDrop), stepContainer.Start(true), ).Finally( stepContainer.Remove().IfBool(!rc.Config.ReuseContainers),