Skip to content
Open
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
14 changes: 14 additions & 0 deletions docs/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,20 @@ <h3 class="mt1 f6 lh-title" id="sandbox.test">
</p>
</div>
</li>
<li>
<div>
<h3 class="mt1 f6 lh-title" id="sandbox.remote">
Remote <span class="normal">(bool)</span>
</h3>

<p>
Enables sandboxing for remotely executed actions. This requires an external
sandbox tool to be configured via the <a href="#sandbox.tool"><code class="code">Tool</code></a>
option, which the remote worker will invoke to wrap the action. Defaults to
<code class="code">False</code>.
</p>
</div>
</li>
<li>
<div>
<h3 class="mt1 f6 lh-title" id="sandbox.dir">
Expand Down
1 change: 1 addition & 0 deletions src/core/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ type Configuration struct {
Namespace string `help:"Set to 'always', to namespace all actions. Set to 'sandbox' to namespace only when sandboxing the build action. Defaults to 'never', under the assumption the sandbox tool will handle its own namespacing. If set, user namespacing will be enabled for all rules. Mount and network will only be enabled if the rule is to be sandboxed."`
Build bool `help:"True to sandbox individual build actions, which isolates them from network access and some aspects of the filesystem. Currently only works on Linux." var:"BUILD_SANDBOX"`
Test bool `help:"True to sandbox individual tests, which isolates them from network access, IPC and some aspects of the filesystem. Currently only works on Linux." var:"TEST_SANDBOX"`
Remote bool `help:"True to enable sandboxing for remotely executed actions. Requires an external sandbox tool to be configured via the Tool option." var:"REMOTE_SANDBOX"`
ExcludeableTargets []BuildLabel `help:"If set, only targets that match these wildcards will be allowed to opt out of the sandbox"`
} `help:"A config section describing settings relating to sandboxing of build actions."`
Remote struct {
Expand Down
43 changes: 35 additions & 8 deletions src/remote/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (c *Client) buildCommand(target *core.BuildTarget, inputRoot *pb.Directory,
Arguments: []string{
"fetch", strings.Join(target.AllURLs(state), " "), "verify", strings.Join(target.Hashes, " "),
},
EnvironmentVariables: c.buildEnv(target, map[string]string{}, false),
EnvironmentVariables: c.buildEnv(target, map[string]string{}, process.NoSandbox),
OutputPaths: outs,
}, nil
}
Expand All @@ -128,8 +128,8 @@ func (c *Client) buildCommand(target *core.BuildTarget, inputRoot *pb.Directory,
cmd, err := core.ReplaceSequences(state, target, cmd)
return &pb.Command{
Platform: c.targetPlatformProperties(target),
Arguments: process.BashCommand(c.shellPath, commandPrefixBuilder.String()+cmd, state.Config.Build.ExitOnError),
EnvironmentVariables: c.buildEnv(target, c.stampedBuildEnvironment(state, target, inputRoot, stamp, isTest || isRun), target.Sandbox),
Arguments: c.sandboxArgs(target.Sandbox, process.BashCommand(c.shellPath, commandPrefixBuilder.String()+cmd, state.Config.Build.ExitOnError)),
EnvironmentVariables: c.buildEnv(target, c.stampedBuildEnvironment(state, target, inputRoot, stamp, isTest || isRun), process.NewSandboxConfig(target.Sandbox, target.Sandbox)),
OutputPaths: outs,
}, err
}
Expand Down Expand Up @@ -168,8 +168,8 @@ func (c *Client) buildTestCommand(state *core.BuildState, target *core.BuildTarg
},
},
},
Arguments: process.BashCommand(c.shellPath, commandPrefix+cmd, state.Config.Build.ExitOnError),
EnvironmentVariables: c.buildEnv(nil, core.TestEnvironment(state, target, ".", run), target.Test.Sandbox),
Arguments: c.sandboxArgs(target.Test.Sandbox, process.BashCommand(c.shellPath, commandPrefix+cmd, state.Config.Build.ExitOnError)),
EnvironmentVariables: c.buildEnv(nil, core.TestEnvironment(state, target, ".", run), process.NewSandboxConfig(target.Test.Sandbox, target.Test.Sandbox)),
OutputPaths: paths,
}, err
}
Expand All @@ -183,7 +183,7 @@ func (c *Client) buildRunCommand(state *core.BuildState, target *core.BuildTarge
return &pb.Command{
Platform: c.platform,
Arguments: outs,
EnvironmentVariables: c.buildEnv(target, core.GeneralBuildEnvironment(state), false),
EnvironmentVariables: c.buildEnv(target, core.GeneralBuildEnvironment(state), process.NoSandbox),
}, nil
}

Expand Down Expand Up @@ -573,10 +573,37 @@ func reallyTranslateOS(os string) string {
}
}

// sandboxArgs prepends the configured external sandbox tool to the given argument list,
// matching what local execution does in exec_linux.go for the non-plz-sandbox case.
// Returns args unchanged if sandboxing is disabled or no external tool is configured.
func (c *Client) sandboxArgs(sandbox bool, args []string) []string {
if !sandbox || !c.state.Config.Sandbox.Remote {
return args
}
tool := c.state.Config.Sandbox.Tool
if tool == "" {
// Built-in plz sandbox re-execs into the local plz binary; not supported remotely.
return args
}
return append([]string{tool}, args...)
}

// buildEnv translates the set of environment variables for this target to a proto.
func (c *Client) buildEnv(target *core.BuildTarget, env core.BuildEnv, sandbox bool) []*pb.Command_EnvironmentVariable {
if sandbox {
func (c *Client) buildEnv(target *core.BuildTarget, env core.BuildEnv, sandbox process.SandboxConfig) []*pb.Command_EnvironmentVariable {
if sandbox != process.NoSandbox && c.state.Config.Sandbox.Remote {
env["SANDBOX"] = "true"
if c.state.Config.Sandbox.Tool != "" {
shareNetwork := "1"
if sandbox.Network {
shareNetwork = "0"
}
shareMount := "1"
if sandbox.Mount {
shareMount = "0"
}
env["SHARE_NETWORK"] = shareNetwork
env["SHARE_MOUNT"] = shareMount
}
}
if target != nil && target.IsBinary {
env["_BINARY"] = "true"
Expand Down
Loading