artifact: add client toggle to disable filesystem isolation (#15503)

This PR adds the client config option for turning off filesystem isolation,
applicable on Linux systems where filesystem isolation is possible and
enabled by default.

```hcl
client{
  artifact {
    disable_filesystem_isolation = <bool:false>
  }
}
```

Closes #15496
This commit is contained in:
Seth Hoenig
2022-12-08 12:29:23 -06:00
committed by GitHub
parent 6732761d91
commit 990537e8ba
10 changed files with 216 additions and 177 deletions

View File

@@ -21,12 +21,13 @@ import (
// e.g. https://www.opencve.io/cve/CVE-2022-41716
type parameters struct {
// Config
HTTPReadTimeout time.Duration `json:"http_read_timeout"`
HTTPMaxBytes int64 `json:"http_max_bytes"`
GCSTimeout time.Duration `json:"gcs_timeout"`
GitTimeout time.Duration `json:"git_timeout"`
HgTimeout time.Duration `json:"hg_timeout"`
S3Timeout time.Duration `json:"s3_timeout"`
HTTPReadTimeout time.Duration `json:"http_read_timeout"`
HTTPMaxBytes int64 `json:"http_max_bytes"`
GCSTimeout time.Duration `json:"gcs_timeout"`
GitTimeout time.Duration `json:"git_timeout"`
HgTimeout time.Duration `json:"hg_timeout"`
S3Timeout time.Duration `json:"s3_timeout"`
DisableFilesystemIsolation bool `json:"disable_filesystem_isolation"`
// Artifact
Mode getter.ClientMode `json:"artifact_mode"`
@@ -85,6 +86,8 @@ func (p *parameters) Equal(o *parameters) bool {
return false
case p.S3Timeout != o.S3Timeout:
return false
case p.DisableFilesystemIsolation != o.DisableFilesystemIsolation:
return false
case p.Mode != o.Mode:
return false
case p.Source != o.Source:

View File

@@ -19,6 +19,7 @@ const paramsAsJSON = `
"git_timeout": 3000000000,
"hg_timeout": 4000000000,
"s3_timeout": 5000000000,
"disable_filesystem_isolation": true,
"artifact_mode": 2,
"artifact_source": "https://example.com/file.txt",
"artifact_destination": "local/out.txt",
@@ -29,12 +30,13 @@ const paramsAsJSON = `
}`
var paramsAsStruct = &parameters{
HTTPReadTimeout: 1 * time.Second,
HTTPMaxBytes: 2000,
GCSTimeout: 2 * time.Second,
GitTimeout: 3 * time.Second,
HgTimeout: 4 * time.Second,
S3Timeout: 5 * time.Second,
HTTPReadTimeout: 1 * time.Second,
HTTPMaxBytes: 2000,
GCSTimeout: 2 * time.Second,
GitTimeout: 3 * time.Second,
HgTimeout: 4 * time.Second,
S3Timeout: 5 * time.Second,
DisableFilesystemIsolation: true,
Mode: getter.ClientModeFile,
Source: "https://example.com/file.txt",

View File

@@ -39,20 +39,26 @@ func (s *Sandbox) Get(env interfaces.EnvReplacer, artifact *structs.TaskArtifact
dir := getTaskDir(env)
params := &parameters{
HTTPReadTimeout: s.ac.HTTPReadTimeout,
HTTPMaxBytes: s.ac.HTTPMaxBytes,
GCSTimeout: s.ac.GCSTimeout,
GitTimeout: s.ac.GitTimeout,
HgTimeout: s.ac.HgTimeout,
S3Timeout: s.ac.S3Timeout,
Mode: mode,
Source: source,
Destination: destination,
Headers: headers,
TaskDir: dir,
// downloader configuration
HTTPReadTimeout: s.ac.HTTPReadTimeout,
HTTPMaxBytes: s.ac.HTTPMaxBytes,
GCSTimeout: s.ac.GCSTimeout,
GitTimeout: s.ac.GitTimeout,
HgTimeout: s.ac.HgTimeout,
S3Timeout: s.ac.S3Timeout,
DisableFilesystemIsolation: s.ac.DisableFilesystemIsolation,
// artifact configuration
Mode: mode,
Source: source,
Destination: destination,
Headers: headers,
// task environment
TaskDir: dir,
}
if err = runCmd(params, s.logger); err != nil {
if err = s.runCmd(params); err != nil {
return err
}
return nil

View File

@@ -10,7 +10,6 @@ import (
"strings"
"github.com/hashicorp/go-getter"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/nomad/client/interfaces"
"github.com/hashicorp/nomad/helper/subproc"
"github.com/hashicorp/nomad/nomad/structs"
@@ -96,7 +95,7 @@ func getTaskDir(env interfaces.EnvReplacer) string {
return filepath.Dir(p)
}
func runCmd(env *parameters, logger hclog.Logger) error {
func (s *Sandbox) runCmd(env *parameters) error {
// find the nomad process
bin := subproc.Self()
@@ -115,13 +114,13 @@ func runCmd(env *parameters, logger hclog.Logger) error {
// start & wait for the subprocess to terminate
if err := cmd.Run(); err != nil {
subproc.Log(output, logger.Error)
subproc.Log(output, s.logger.Error)
return &Error{
URL: env.Source,
Err: fmt.Errorf("getter subprocess failed: %v", err),
Recoverable: true,
}
}
subproc.Log(output, logger.Debug)
subproc.Log(output, s.logger.Debug)
return nil
}

View File

@@ -30,10 +30,11 @@ func init() {
subproc.SetExpiration(ctx)
// sandbox the host filesystem for this process
dir := env.TaskDir
if err := lockdown(dir); err != nil {
subproc.Print("failed to sandbox getter process: %v", err)
return subproc.ExitFailure
if !env.DisableFilesystemIsolation {
if err := lockdown(env.TaskDir); err != nil {
subproc.Print("failed to sandbox %s process: %v", SubCommand, err)
return subproc.ExitFailure
}
}
// create the go-getter client