Skip to content

Commit c9902bf

Browse files
authored
batches: improve handling of non-root steps (#886)
This changes the default for `src batch exec` (used by SSBC) to run all step containers as root, and adds a flag to `src batch apply` and `src batch preview` to optionally do the same thing. Fixes sourcegraph/sourcegraph#41836.
1 parent e77731f commit c9902bf

File tree

5 files changed

+23
-0
lines changed

5 files changed

+23
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ All notable changes to `src-cli` are documented in this file.
1313

1414
### Added
1515

16+
- Batch specs being run locally with `src batch preview` or `src batch apply` can now be run with the `-run-as-root` flag, which will run all step containers as root instead of the default user for the image. This is off by default. [#886](https://github.com/sourcegraph/src-cli/pull/886)
17+
1618
### Changed
1719

20+
- Batch specs being run from the server using this version of `src-cli` now run all step containers as root, rather than as the default user for the image. [#886](https://github.com/sourcegraph/src-cli/pull/886)
21+
1822
### Fixed
1923

2024
### Removed

cmd/src/batch_common.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type batchExecuteFlags struct {
8585
workspace string
8686
cleanArchives bool
8787
skipErrors bool
88+
runAsRoot bool
8889

8990
// EXPERIMENTAL
9091
textOnly bool
@@ -152,6 +153,11 @@ func newBatchExecuteFlags(flagSet *flag.FlagSet, cacheDir, tempDir string) *batc
152153

153154
flagSet.BoolVar(verbose, "v", false, "print verbose output")
154155

156+
flagSet.BoolVar(
157+
&caf.runAsRoot, "run-as-root", false,
158+
"If true, forces all step containers to run as root.",
159+
)
160+
155161
return caf
156162
}
157163

@@ -382,6 +388,7 @@ func executeBatchSpec(ctx context.Context, ui ui.ExecUI, opts executeBatchSpecOp
382388
Timeout: opts.flags.timeout,
383389
TempDir: opts.flags.tempDir,
384390
GlobalEnv: os.Environ(),
391+
ForceRoot: opts.flags.runAsRoot,
385392
},
386393
Logger: logManager,
387394
Cache: executor.NewDiskCache(opts.flags.cacheDir),

cmd/src/batch_exec.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const (
3333
type executorModeFlags struct {
3434
timeout time.Duration
3535
file string
36+
runAsImageUser bool
3637
tempDir string
3738
repoDir string
3839
workspaceFilesDir string
@@ -42,6 +43,7 @@ func newExecutorModeFlags(flagSet *flag.FlagSet) (f *executorModeFlags) {
4243
f = &executorModeFlags{}
4344
flagSet.DurationVar(&f.timeout, "timeout", 60*time.Minute, "The maximum duration a single batch spec step can take.")
4445
flagSet.StringVar(&f.file, "f", "", "The workspace execution input file to read.")
46+
flagSet.BoolVar(&f.runAsImageUser, "run-as-image-user", false, "True to run step containers as the default image user; if false or omitted, containers are always run as root.")
4547
flagSet.StringVar(&f.tempDir, "tmp", "", "Directory for storing temporary data.")
4648
flagSet.StringVar(&f.repoDir, "repo", "", "Path of the checked out repo on disk.")
4749
flagSet.StringVar(&f.workspaceFilesDir, "workspaceFiles", "", "Path of workspace files on disk.")
@@ -208,6 +210,7 @@ func executeBatchSpecInWorkspaces(ctx context.Context, flags *executorModeFlags)
208210
GlobalEnv: globalEnv,
209211
RepoArchive: &repozip.NoopArchive{},
210212
UI: taskExecUI.StepsExecutionUI(task),
213+
ForceRoot: !flags.runAsImageUser,
211214
}
212215
results, err := executor.RunSteps(ctx, opts)
213216

internal/batches/executor/executor.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ type NewExecutorOpts struct {
6868
TempDir string
6969
IsRemote bool
7070
GlobalEnv []string
71+
ForceRoot bool
7172
}
7273

7374
type executor struct {
@@ -178,6 +179,7 @@ func (x *executor) do(ctx context.Context, task *Task, ui TaskExecutionUI) (err
178179
Timeout: x.opts.Timeout,
179180
RepoArchive: repoArchive,
180181
WorkingDirectory: x.opts.WorkingDirectory,
182+
ForceRoot: x.opts.ForceRoot,
181183

182184
UI: ui.StepsExecutionUI(task),
183185
}

internal/batches/executor/run_steps.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ type RunStepsOpts struct {
5151
// GlobalEnv is the os.Environ() for the execution. We don't read from os.Environ()
5252
// directly to allow injecting variables and hiding others.
5353
GlobalEnv []string
54+
// ForceRoot forces Docker containers to be run as root:root, rather than
55+
// whatever the image's default user and group are.
56+
ForceRoot bool
5457
}
5558

5659
func RunSteps(ctx context.Context, opts *RunStepsOpts) (stepResults []execution.AfterStepResult, err error) {
@@ -317,6 +320,10 @@ func executeSingleStep(
317320
"--mount", fmt.Sprintf("type=bind,source=%s,target=%s,ro", runScriptFile, containerTemp),
318321
}, workspaceOpts...)
319322

323+
if opts.ForceRoot {
324+
args = append(args, "--user", "0:0")
325+
}
326+
320327
for target, source := range filesToMount {
321328
args = append(args, "--mount", fmt.Sprintf("type=bind,source=%s,target=%s,ro", source.Name(), target))
322329
}

0 commit comments

Comments
 (0)