github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/allocrunner/taskrunner/getter/params.go (about) 1 package getter 2 3 import ( 4 "context" 5 "encoding/json" 6 "io" 7 "io/fs" 8 "strings" 9 "time" 10 11 "github.com/hashicorp/go-cleanhttp" 12 "github.com/hashicorp/go-getter" 13 "github.com/hashicorp/nomad/helper" 14 "golang.org/x/exp/maps" 15 "golang.org/x/exp/slices" 16 ) 17 18 // parameters is encoded by the Nomad client and decoded by the getter sub-process 19 // so it can know what to do. We use standard IO to pass configuration to achieve 20 // better control over input sanitization risks. 21 // e.g. https://www.opencve.io/cve/CVE-2022-41716 22 type parameters struct { 23 // Config 24 HTTPReadTimeout time.Duration `json:"http_read_timeout"` 25 HTTPMaxBytes int64 `json:"http_max_bytes"` 26 GCSTimeout time.Duration `json:"gcs_timeout"` 27 GitTimeout time.Duration `json:"git_timeout"` 28 HgTimeout time.Duration `json:"hg_timeout"` 29 S3Timeout time.Duration `json:"s3_timeout"` 30 DisableFilesystemIsolation bool `json:"disable_filesystem_isolation"` 31 SetEnvironmentVariables string `json:"set_environment_variables"` 32 33 // Artifact 34 Mode getter.ClientMode `json:"artifact_mode"` 35 Source string `json:"artifact_source"` 36 Destination string `json:"artifact_destination"` 37 Headers map[string][]string `json:"artifact_headers"` 38 39 // Task Environment 40 TaskDir string `json:"task_dir"` 41 } 42 43 func (p *parameters) reader() io.Reader { 44 b, err := json.Marshal(p) 45 if err != nil { 46 b = nil 47 } 48 return strings.NewReader(string(b)) 49 } 50 51 func (p *parameters) read(r io.Reader) error { 52 return json.NewDecoder(r).Decode(p) 53 } 54 55 // deadline returns an absolute deadline before the artifact download 56 // sub-process forcefully terminates. The default is 1/2 hour, unless one or 57 // more getter configurations is set higher. A 1 minute grace period is added 58 // so that an internal timeout has a moment to complete before the process is 59 // terminated via signal. 60 func (p *parameters) deadline() time.Duration { 61 const minimum = 30 * time.Minute 62 max := minimum 63 max = helper.Max(max, p.HTTPReadTimeout) 64 max = helper.Max(max, p.GCSTimeout) 65 max = helper.Max(max, p.GitTimeout) 66 max = helper.Max(max, p.HgTimeout) 67 max = helper.Max(max, p.S3Timeout) 68 return max + 1*time.Minute 69 } 70 71 // Equal returns whether p and o are the same. 72 func (p *parameters) Equal(o *parameters) bool { 73 if p == nil || o == nil { 74 return p == o 75 } 76 77 switch { 78 case p.HTTPReadTimeout != o.HTTPReadTimeout: 79 return false 80 case p.HTTPMaxBytes != o.HTTPMaxBytes: 81 return false 82 case p.GCSTimeout != o.GCSTimeout: 83 return false 84 case p.GitTimeout != o.GitTimeout: 85 return false 86 case p.HgTimeout != o.HgTimeout: 87 return false 88 case p.S3Timeout != o.S3Timeout: 89 return false 90 case p.DisableFilesystemIsolation != o.DisableFilesystemIsolation: 91 return false 92 case p.SetEnvironmentVariables != o.SetEnvironmentVariables: 93 return false 94 case p.Mode != o.Mode: 95 return false 96 case p.Source != o.Source: 97 return false 98 case p.Destination != o.Destination: 99 return false 100 case p.TaskDir != o.TaskDir: 101 return false 102 case !maps.EqualFunc(p.Headers, o.Headers, slices.Equal[string]): 103 return false 104 } 105 106 return true 107 } 108 109 const ( 110 // stop privilege escalation via setuid/setgid 111 // https://github.com/hashicorp/nomad/issues/6176 112 umask = fs.ModeSetuid | fs.ModeSetgid 113 ) 114 115 func (p *parameters) client(ctx context.Context) *getter.Client { 116 httpGetter := &getter.HttpGetter{ 117 Netrc: true, 118 Client: cleanhttp.DefaultClient(), 119 Header: p.Headers, 120 121 // Do not support the custom X-Terraform-Get header and 122 // associated logic. 123 XTerraformGetDisabled: true, 124 125 // Disable HEAD requests as they can produce corrupt files when 126 // retrying a download of a resource that has changed. 127 // hashicorp/go-getter#219 128 DoNotCheckHeadFirst: true, 129 130 // Read timeout for HTTP operations. Must be long enough to 131 // accommodate large/slow downloads. 132 ReadTimeout: p.HTTPReadTimeout, 133 134 // Maximum download size. Must be large enough to accommodate 135 // large downloads. 136 MaxBytes: p.HTTPMaxBytes, 137 } 138 return &getter.Client{ 139 Ctx: ctx, 140 Src: p.Source, 141 Dst: p.Destination, 142 Mode: p.Mode, 143 Umask: umask, 144 Insecure: false, 145 DisableSymlinks: true, 146 Getters: map[string]getter.Getter{ 147 "git": &getter.GitGetter{ 148 Timeout: p.GitTimeout, 149 }, 150 "hg": &getter.HgGetter{ 151 Timeout: p.HgTimeout, 152 }, 153 "gcs": &getter.GCSGetter{ 154 Timeout: p.GCSTimeout, 155 }, 156 "s3": &getter.S3Getter{ 157 Timeout: p.S3Timeout, 158 }, 159 "http": httpGetter, 160 "https": httpGetter, 161 }, 162 } 163 }