diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/plugin/discovery')
8 files changed, 463 insertions, 272 deletions
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/error.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/error.go index df855a7..729e970 100644 --- a/vendor/github.com/hashicorp/terraform/plugin/discovery/error.go +++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/error.go | |||
@@ -22,9 +22,43 @@ const ErrorNoSuitableVersion = Error("no suitable version is available") | |||
22 | // version of Terraform. | 22 | // version of Terraform. |
23 | const ErrorNoVersionCompatible = Error("no available version is compatible with this version of Terraform") | 23 | const ErrorNoVersionCompatible = Error("no available version is compatible with this version of Terraform") |
24 | 24 | ||
25 | // ErrorVersionIncompatible indicates that all of the versions within the | ||
26 | // constraints are not compatible with the current version of Terrafrom, though | ||
27 | // there does exist a version outside of the constaints that is compatible. | ||
28 | const ErrorVersionIncompatible = Error("incompatible provider version") | ||
29 | |||
25 | // ErrorNoSuchProvider indicates that no provider exists with a name given | 30 | // ErrorNoSuchProvider indicates that no provider exists with a name given |
26 | const ErrorNoSuchProvider = Error("no provider exists with the given name") | 31 | const ErrorNoSuchProvider = Error("no provider exists with the given name") |
27 | 32 | ||
33 | // ErrorNoVersionCompatibleWithPlatform indicates that all of the available | ||
34 | // versions that otherwise met constraints are not compatible with the | ||
35 | // requested platform | ||
36 | const ErrorNoVersionCompatibleWithPlatform = Error("no available version is compatible for the requested platform") | ||
37 | |||
38 | // ErrorMissingChecksumVerification indicates that either the provider | ||
39 | // distribution is missing the SHA256SUMS file or the checksum file does | ||
40 | // not contain a checksum for the binary plugin | ||
41 | const ErrorMissingChecksumVerification = Error("unable to verify checksum") | ||
42 | |||
43 | // ErrorChecksumVerification indicates that the current checksum of the | ||
44 | // provider plugin has changed since the initial release and is not trusted | ||
45 | // to download | ||
46 | const ErrorChecksumVerification = Error("unexpected plugin checksum") | ||
47 | |||
48 | // ErrorSignatureVerification indicates that the digital signature for a | ||
49 | // provider distribution could not be verified for one of the following | ||
50 | // reasons: missing signature file, missing public key, or the signature | ||
51 | // was not signed by any known key for the publisher | ||
52 | const ErrorSignatureVerification = Error("unable to verify signature") | ||
53 | |||
54 | // ErrorServiceUnreachable indicates that the network was unable to connect | ||
55 | // to the registry service | ||
56 | const ErrorServiceUnreachable = Error("registry service is unreachable") | ||
57 | |||
58 | // ErrorPublicRegistryUnreachable indicates that the network was unable to connect | ||
59 | // to the public registry in particular, so we can show a link to the statuspage | ||
60 | const ErrorPublicRegistryUnreachable = Error("registry service is unreachable, check https://status.hashicorp.com/ for status updates") | ||
61 | |||
28 | func (err Error) Error() string { | 62 | func (err Error) Error() string { |
29 | return string(err) | 63 | return string(err) |
30 | } | 64 | } |
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/get.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/get.go index 815640f..b1d01fb 100644 --- a/vendor/github.com/hashicorp/terraform/plugin/discovery/get.go +++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/get.go | |||
@@ -13,28 +13,27 @@ import ( | |||
13 | "strconv" | 13 | "strconv" |
14 | "strings" | 14 | "strings" |
15 | 15 | ||
16 | "golang.org/x/net/html" | 16 | "github.com/hashicorp/errwrap" |
17 | |||
18 | getter "github.com/hashicorp/go-getter" | 17 | getter "github.com/hashicorp/go-getter" |
19 | multierror "github.com/hashicorp/go-multierror" | 18 | multierror "github.com/hashicorp/go-multierror" |
20 | "github.com/hashicorp/terraform/httpclient" | 19 | "github.com/hashicorp/terraform/httpclient" |
20 | "github.com/hashicorp/terraform/registry" | ||
21 | "github.com/hashicorp/terraform/registry/regsrc" | ||
22 | "github.com/hashicorp/terraform/registry/response" | ||
23 | "github.com/hashicorp/terraform/svchost/disco" | ||
24 | "github.com/hashicorp/terraform/tfdiags" | ||
25 | tfversion "github.com/hashicorp/terraform/version" | ||
21 | "github.com/mitchellh/cli" | 26 | "github.com/mitchellh/cli" |
22 | ) | 27 | ) |
23 | 28 | ||
24 | // Releases are located by parsing the html listing from releases.hashicorp.com. | 29 | // Releases are located by querying the terraform registry. |
25 | // | ||
26 | // The URL for releases follows the pattern: | ||
27 | // https://releases.hashicorp.com/terraform-provider-name/<x.y.z>/terraform-provider-name_<x.y.z>_<os>_<arch>.<ext> | ||
28 | // | ||
29 | // The plugin protocol version will be saved with the release and returned in | ||
30 | // the header X-TERRAFORM_PROTOCOL_VERSION. | ||
31 | 30 | ||
32 | const protocolVersionHeader = "x-terraform-protocol-version" | 31 | const protocolVersionHeader = "x-terraform-protocol-version" |
33 | 32 | ||
34 | var releaseHost = "https://releases.hashicorp.com" | ||
35 | |||
36 | var httpClient *http.Client | 33 | var httpClient *http.Client |
37 | 34 | ||
35 | var errVersionNotFound = errors.New("version not found") | ||
36 | |||
38 | func init() { | 37 | func init() { |
39 | httpClient = httpclient.New() | 38 | httpClient = httpclient.New() |
40 | 39 | ||
@@ -50,7 +49,7 @@ func init() { | |||
50 | // An Installer maintains a local cache of plugins by downloading plugins | 49 | // An Installer maintains a local cache of plugins by downloading plugins |
51 | // from an online repository. | 50 | // from an online repository. |
52 | type Installer interface { | 51 | type Installer interface { |
53 | Get(name string, req Constraints) (PluginMeta, error) | 52 | Get(name string, req Constraints) (PluginMeta, tfdiags.Diagnostics, error) |
54 | PurgeUnused(used map[string]PluginMeta) (removed PluginMetaSet, err error) | 53 | PurgeUnused(used map[string]PluginMeta) (removed PluginMetaSet, err error) |
55 | } | 54 | } |
56 | 55 | ||
@@ -79,6 +78,13 @@ type ProviderInstaller struct { | |||
79 | SkipVerify bool | 78 | SkipVerify bool |
80 | 79 | ||
81 | Ui cli.Ui // Ui for output | 80 | Ui cli.Ui // Ui for output |
81 | |||
82 | // Services is a required *disco.Disco, which may have services and | ||
83 | // credentials pre-loaded. | ||
84 | Services *disco.Disco | ||
85 | |||
86 | // registry client | ||
87 | registry *registry.Client | ||
82 | } | 88 | } |
83 | 89 | ||
84 | // Get is part of an implementation of type Installer, and attempts to download | 90 | // Get is part of an implementation of type Installer, and attempts to download |
@@ -100,96 +106,170 @@ type ProviderInstaller struct { | |||
100 | // are produced under the assumption that if presented to the user they will | 106 | // are produced under the assumption that if presented to the user they will |
101 | // be presented alongside context about what is being installed, and thus the | 107 | // be presented alongside context about what is being installed, and thus the |
102 | // error messages do not redundantly include such information. | 108 | // error messages do not redundantly include such information. |
103 | func (i *ProviderInstaller) Get(provider string, req Constraints) (PluginMeta, error) { | 109 | func (i *ProviderInstaller) Get(provider string, req Constraints) (PluginMeta, tfdiags.Diagnostics, error) { |
104 | versions, err := i.listProviderVersions(provider) | 110 | var diags tfdiags.Diagnostics |
111 | |||
112 | // a little bit of initialization. | ||
113 | if i.OS == "" { | ||
114 | i.OS = runtime.GOOS | ||
115 | } | ||
116 | if i.Arch == "" { | ||
117 | i.Arch = runtime.GOARCH | ||
118 | } | ||
119 | if i.registry == nil { | ||
120 | i.registry = registry.NewClient(i.Services, nil) | ||
121 | } | ||
122 | |||
123 | // get a full listing of versions for the requested provider | ||
124 | allVersions, err := i.listProviderVersions(provider) | ||
125 | |||
105 | // TODO: return multiple errors | 126 | // TODO: return multiple errors |
106 | if err != nil { | 127 | if err != nil { |
107 | return PluginMeta{}, err | 128 | log.Printf("[DEBUG] %s", err) |
129 | if registry.IsServiceUnreachable(err) { | ||
130 | registryHost, err := i.hostname() | ||
131 | if err == nil && registryHost == regsrc.PublicRegistryHost.Raw { | ||
132 | return PluginMeta{}, diags, ErrorPublicRegistryUnreachable | ||
133 | } | ||
134 | return PluginMeta{}, diags, ErrorServiceUnreachable | ||
135 | } | ||
136 | if registry.IsServiceNotProvided(err) { | ||
137 | return PluginMeta{}, diags, err | ||
138 | } | ||
139 | return PluginMeta{}, diags, ErrorNoSuchProvider | ||
108 | } | 140 | } |
109 | 141 | ||
110 | if len(versions) == 0 { | 142 | // Add any warnings from the response to diags |
111 | return PluginMeta{}, ErrorNoSuitableVersion | 143 | for _, warning := range allVersions.Warnings { |
144 | hostname, err := i.hostname() | ||
145 | if err != nil { | ||
146 | return PluginMeta{}, diags, err | ||
147 | } | ||
148 | diag := tfdiags.SimpleWarning(fmt.Sprintf("%s: %s", hostname, warning)) | ||
149 | diags = diags.Append(diag) | ||
112 | } | 150 | } |
113 | 151 | ||
114 | versions = allowedVersions(versions, req) | 152 | if len(allVersions.Versions) == 0 { |
153 | return PluginMeta{}, diags, ErrorNoSuitableVersion | ||
154 | } | ||
155 | providerSource := allVersions.ID | ||
156 | |||
157 | // Filter the list of plugin versions to those which meet the version constraints | ||
158 | versions := allowedVersions(allVersions, req) | ||
115 | if len(versions) == 0 { | 159 | if len(versions) == 0 { |
116 | return PluginMeta{}, ErrorNoSuitableVersion | 160 | return PluginMeta{}, diags, ErrorNoSuitableVersion |
117 | } | 161 | } |
118 | 162 | ||
119 | // sort them newest to oldest | 163 | // sort them newest to oldest. The newest version wins! |
120 | Versions(versions).Sort() | 164 | response.ProviderVersionCollection(versions).Sort() |
121 | 165 | ||
122 | // Ensure that our installation directory exists | 166 | // if the chosen provider version does not support the requested platform, |
123 | err = os.MkdirAll(i.Dir, os.ModePerm) | 167 | // filter the list of acceptable versions to those that support that platform |
124 | if err != nil { | 168 | if err := i.checkPlatformCompatibility(versions[0]); err != nil { |
125 | return PluginMeta{}, fmt.Errorf("failed to create plugin dir %s: %s", i.Dir, err) | 169 | versions = i.platformCompatibleVersions(versions) |
170 | if len(versions) == 0 { | ||
171 | return PluginMeta{}, diags, ErrorNoVersionCompatibleWithPlatform | ||
172 | } | ||
126 | } | 173 | } |
127 | 174 | ||
128 | // take the first matching plugin we find | 175 | // we now have a winning platform-compatible version |
129 | for _, v := range versions { | 176 | versionMeta := versions[0] |
130 | url := i.providerURL(provider, v.String()) | 177 | v := VersionStr(versionMeta.Version).MustParse() |
131 | 178 | ||
132 | if !i.SkipVerify { | 179 | // check protocol compatibility |
133 | sha256, err := i.getProviderChecksum(provider, v.String()) | 180 | if err := i.checkPluginProtocol(versionMeta); err != nil { |
134 | if err != nil { | 181 | closestMatch, err := i.findClosestProtocolCompatibleVersion(allVersions.Versions) |
135 | return PluginMeta{}, err | 182 | if err != nil { |
136 | } | 183 | // No operation here if we can't find a version with compatible protocol |
184 | return PluginMeta{}, diags, err | ||
185 | } | ||
137 | 186 | ||
138 | // add the checksum parameter for go-getter to verify the download for us. | 187 | // Prompt version suggestion to UI based on closest protocol match |
139 | if sha256 != "" { | 188 | var errMsg string |
140 | url = url + "?checksum=sha256:" + sha256 | 189 | closestVersion := VersionStr(closestMatch.Version).MustParse() |
141 | } | 190 | if v.NewerThan(closestVersion) { |
191 | errMsg = providerProtocolTooNew | ||
192 | } else { | ||
193 | errMsg = providerProtocolTooOld | ||
142 | } | 194 | } |
143 | 195 | ||
144 | log.Printf("[DEBUG] fetching provider info for %s version %s", provider, v) | 196 | constraintStr := req.String() |
145 | if checkPlugin(url, i.PluginProtocolVersion) { | 197 | if constraintStr == "" { |
146 | i.Ui.Info(fmt.Sprintf("- Downloading plugin for provider %q (%s)...", provider, v.String())) | 198 | constraintStr = "(any version)" |
147 | log.Printf("[DEBUG] getting provider %q version %q", provider, v) | 199 | } |
148 | err := i.install(provider, v, url) | ||
149 | if err != nil { | ||
150 | return PluginMeta{}, err | ||
151 | } | ||
152 | 200 | ||
153 | // Find what we just installed | 201 | return PluginMeta{}, diags, errwrap.Wrap(ErrorVersionIncompatible, fmt.Errorf(fmt.Sprintf( |
154 | // (This is weird, because go-getter doesn't directly return | 202 | errMsg, provider, v.String(), tfversion.String(), |
155 | // information about what was extracted, and we just extracted | 203 | closestVersion.String(), closestVersion.MinorUpgradeConstraintStr(), constraintStr))) |
156 | // the archive directly into a shared dir here.) | 204 | } |
157 | log.Printf("[DEBUG] looking for the %s %s plugin we just installed", provider, v) | ||
158 | metas := FindPlugins("provider", []string{i.Dir}) | ||
159 | log.Printf("[DEBUG] all plugins found %#v", metas) | ||
160 | metas, _ = metas.ValidateVersions() | ||
161 | metas = metas.WithName(provider).WithVersion(v) | ||
162 | log.Printf("[DEBUG] filtered plugins %#v", metas) | ||
163 | if metas.Count() == 0 { | ||
164 | // This should never happen. Suggests that the release archive | ||
165 | // contains an executable file whose name doesn't match the | ||
166 | // expected convention. | ||
167 | return PluginMeta{}, fmt.Errorf( | ||
168 | "failed to find installed plugin version %s; this is a bug in Terraform and should be reported", | ||
169 | v, | ||
170 | ) | ||
171 | } | ||
172 | 205 | ||
173 | if metas.Count() > 1 { | 206 | downloadURLs, err := i.listProviderDownloadURLs(providerSource, versionMeta.Version) |
174 | // This should also never happen, and suggests that a | 207 | providerURL := downloadURLs.DownloadURL |
175 | // particular version was re-released with a different | 208 | |
176 | // executable filename. We consider releases as immutable, so | 209 | if !i.SkipVerify { |
177 | // this is an error. | 210 | // Terraform verifies the integrity of a provider release before downloading |
178 | return PluginMeta{}, fmt.Errorf( | 211 | // the plugin binary. The digital signature (SHA256SUMS.sig) on the |
179 | "multiple plugins installed for version %s; this is a bug in Terraform and should be reported", | 212 | // release distribution (SHA256SUMS) is verified with the public key of the |
180 | v, | 213 | // publisher provided in the Terraform Registry response, ensuring that |
181 | ) | 214 | // everything is as intended by the publisher. The checksum of the provider |
182 | } | 215 | // plugin is expected in the SHA256SUMS file and is double checked to match |
216 | // the checksum of the original published release to the Registry. This | ||
217 | // enforces immutability of releases between the Registry and the plugin's | ||
218 | // host location. Lastly, the integrity of the binary is verified upon | ||
219 | // download matches the Registry and signed checksum. | ||
220 | sha256, err := i.getProviderChecksum(downloadURLs) | ||
221 | if err != nil { | ||
222 | return PluginMeta{}, diags, err | ||
223 | } | ||
183 | 224 | ||
184 | // By now we know we have exactly one meta, and so "Newest" will | 225 | // add the checksum parameter for go-getter to verify the download for us. |
185 | // return that one. | 226 | if sha256 != "" { |
186 | return metas.Newest(), nil | 227 | providerURL = providerURL + "?checksum=sha256:" + sha256 |
187 | } | 228 | } |
229 | } | ||
230 | |||
231 | printedProviderName := fmt.Sprintf("%q (%s)", provider, providerSource) | ||
232 | i.Ui.Info(fmt.Sprintf("- Downloading plugin for provider %s %s...", printedProviderName, versionMeta.Version)) | ||
233 | log.Printf("[DEBUG] getting provider %s version %q", printedProviderName, versionMeta.Version) | ||
234 | err = i.install(provider, v, providerURL) | ||
235 | if err != nil { | ||
236 | return PluginMeta{}, diags, err | ||
237 | } | ||
238 | |||
239 | // Find what we just installed | ||
240 | // (This is weird, because go-getter doesn't directly return | ||
241 | // information about what was extracted, and we just extracted | ||
242 | // the archive directly into a shared dir here.) | ||
243 | log.Printf("[DEBUG] looking for the %s %s plugin we just installed", provider, versionMeta.Version) | ||
244 | metas := FindPlugins("provider", []string{i.Dir}) | ||
245 | log.Printf("[DEBUG] all plugins found %#v", metas) | ||
246 | metas, _ = metas.ValidateVersions() | ||
247 | metas = metas.WithName(provider).WithVersion(v) | ||
248 | log.Printf("[DEBUG] filtered plugins %#v", metas) | ||
249 | if metas.Count() == 0 { | ||
250 | // This should never happen. Suggests that the release archive | ||
251 | // contains an executable file whose name doesn't match the | ||
252 | // expected convention. | ||
253 | return PluginMeta{}, diags, fmt.Errorf( | ||
254 | "failed to find installed plugin version %s; this is a bug in Terraform and should be reported", | ||
255 | versionMeta.Version, | ||
256 | ) | ||
257 | } | ||
188 | 258 | ||
189 | log.Printf("[INFO] incompatible ProtocolVersion for %s version %s", provider, v) | 259 | if metas.Count() > 1 { |
260 | // This should also never happen, and suggests that a | ||
261 | // particular version was re-released with a different | ||
262 | // executable filename. We consider releases as immutable, so | ||
263 | // this is an error. | ||
264 | return PluginMeta{}, diags, fmt.Errorf( | ||
265 | "multiple plugins installed for version %s; this is a bug in Terraform and should be reported", | ||
266 | versionMeta.Version, | ||
267 | ) | ||
190 | } | 268 | } |
191 | 269 | ||
192 | return PluginMeta{}, ErrorNoVersionCompatible | 270 | // By now we know we have exactly one meta, and so "Newest" will |
271 | // return that one. | ||
272 | return metas.Newest(), diags, nil | ||
193 | } | 273 | } |
194 | 274 | ||
195 | func (i *ProviderInstaller) install(provider string, version Version, url string) error { | 275 | func (i *ProviderInstaller) install(provider string, version Version, url string) error { |
@@ -215,6 +295,14 @@ func (i *ProviderInstaller) install(provider string, version Version, url string | |||
215 | // normal resolution machinery can find it. | 295 | // normal resolution machinery can find it. |
216 | filename := filepath.Base(cached) | 296 | filename := filepath.Base(cached) |
217 | targetPath := filepath.Join(i.Dir, filename) | 297 | targetPath := filepath.Join(i.Dir, filename) |
298 | // check if the target dir exists, and create it if not | ||
299 | var err error | ||
300 | if _, StatErr := os.Stat(i.Dir); os.IsNotExist(StatErr) { | ||
301 | err = os.MkdirAll(i.Dir, 0700) | ||
302 | } | ||
303 | if err != nil { | ||
304 | return err | ||
305 | } | ||
218 | 306 | ||
219 | log.Printf("[DEBUG] installing %s %s to %s from local cache %s", provider, version, targetPath, cached) | 307 | log.Printf("[DEBUG] installing %s %s to %s from local cache %s", provider, version, targetPath, cached) |
220 | 308 | ||
@@ -280,7 +368,6 @@ func (i *ProviderInstaller) install(provider string, version Version, url string | |||
280 | return err | 368 | return err |
281 | } | 369 | } |
282 | } | 370 | } |
283 | |||
284 | return nil | 371 | return nil |
285 | } | 372 | } |
286 | 373 | ||
@@ -316,182 +403,222 @@ func (i *ProviderInstaller) PurgeUnused(used map[string]PluginMeta) (PluginMetaS | |||
316 | return removed, errs | 403 | return removed, errs |
317 | } | 404 | } |
318 | 405 | ||
319 | // Plugins are referred to by the short name, but all URLs and files will use | 406 | func (i *ProviderInstaller) getProviderChecksum(resp *response.TerraformProviderPlatformLocation) (string, error) { |
320 | // the full name prefixed with terraform-<plugin_type>- | 407 | // Get SHA256SUMS file. |
321 | func (i *ProviderInstaller) providerName(name string) string { | 408 | shasums, err := getFile(resp.ShasumsURL) |
322 | return "terraform-provider-" + name | 409 | if err != nil { |
323 | } | 410 | log.Printf("[ERROR] error fetching checksums from %q: %s", resp.ShasumsURL, err) |
411 | return "", ErrorMissingChecksumVerification | ||
412 | } | ||
324 | 413 | ||
325 | func (i *ProviderInstaller) providerFileName(name, version string) string { | 414 | // Get SHA256SUMS.sig file. |
326 | os := i.OS | 415 | signature, err := getFile(resp.ShasumsSignatureURL) |
327 | arch := i.Arch | 416 | if err != nil { |
328 | if os == "" { | 417 | log.Printf("[ERROR] error fetching checksums signature from %q: %s", resp.ShasumsSignatureURL, err) |
329 | os = runtime.GOOS | 418 | return "", ErrorSignatureVerification |
330 | } | 419 | } |
331 | if arch == "" { | 420 | |
332 | arch = runtime.GOARCH | 421 | // Verify the GPG signature returned from the Registry. |
422 | asciiArmor := resp.SigningKeys.GPGASCIIArmor() | ||
423 | signer, err := verifySig(shasums, signature, asciiArmor) | ||
424 | if err != nil { | ||
425 | log.Printf("[ERROR] error verifying signature: %s", err) | ||
426 | return "", ErrorSignatureVerification | ||
333 | } | 427 | } |
334 | return fmt.Sprintf("%s_%s_%s_%s.zip", i.providerName(name), version, os, arch) | ||
335 | } | ||
336 | 428 | ||
337 | // providerVersionsURL returns the path to the released versions directory for the provider: | 429 | // Also verify the GPG signature against the HashiCorp public key. This is |
338 | // https://releases.hashicorp.com/terraform-provider-name/ | 430 | // a temporary additional check until a more robust key verification |
339 | func (i *ProviderInstaller) providerVersionsURL(name string) string { | 431 | // process is added in a future release. |
340 | return releaseHost + "/" + i.providerName(name) + "/" | 432 | _, err = verifySig(shasums, signature, HashicorpPublicKey) |
341 | } | 433 | if err != nil { |
434 | log.Printf("[ERROR] error verifying signature against HashiCorp public key: %s", err) | ||
435 | return "", ErrorSignatureVerification | ||
436 | } | ||
342 | 437 | ||
343 | // providerURL returns the full path to the provider file, using the current OS | 438 | // Display identity for GPG key which succeeded verifying the signature. |
344 | // and ARCH: | 439 | // This could also be used to display to the user with i.Ui.Info(). |
345 | // .../terraform-provider-name_<x.y.z>/terraform-provider-name_<x.y.z>_<os>_<arch>.<ext> | 440 | identities := []string{} |
346 | func (i *ProviderInstaller) providerURL(name, version string) string { | 441 | for k := range signer.Identities { |
347 | return fmt.Sprintf("%s%s/%s", i.providerVersionsURL(name), version, i.providerFileName(name, version)) | 442 | identities = append(identities, k) |
348 | } | 443 | } |
444 | identity := strings.Join(identities, ", ") | ||
445 | log.Printf("[DEBUG] verified GPG signature with key from %s", identity) | ||
446 | |||
447 | // Extract checksum for this os/arch platform binary and verify against Registry | ||
448 | checksum := checksumForFile(shasums, resp.Filename) | ||
449 | if checksum == "" { | ||
450 | log.Printf("[ERROR] missing checksum for %s from source %s", resp.Filename, resp.ShasumsURL) | ||
451 | return "", ErrorMissingChecksumVerification | ||
452 | } else if checksum != resp.Shasum { | ||
453 | log.Printf("[ERROR] unexpected checksum for %s from source %q", resp.Filename, resp.ShasumsURL) | ||
454 | return "", ErrorChecksumVerification | ||
455 | } | ||
349 | 456 | ||
350 | func (i *ProviderInstaller) providerChecksumURL(name, version string) string { | 457 | return checksum, nil |
351 | fileName := fmt.Sprintf("%s_%s_SHA256SUMS", i.providerName(name), version) | ||
352 | u := fmt.Sprintf("%s%s/%s", i.providerVersionsURL(name), version, fileName) | ||
353 | return u | ||
354 | } | 458 | } |
355 | 459 | ||
356 | func (i *ProviderInstaller) getProviderChecksum(name, version string) (string, error) { | 460 | func (i *ProviderInstaller) hostname() (string, error) { |
357 | checksums, err := getPluginSHA256SUMs(i.providerChecksumURL(name, version)) | 461 | provider := regsrc.NewTerraformProvider("", i.OS, i.Arch) |
462 | svchost, err := provider.SvcHost() | ||
358 | if err != nil { | 463 | if err != nil { |
359 | return "", err | 464 | return "", err |
360 | } | 465 | } |
361 | 466 | ||
362 | return checksumForFile(checksums, i.providerFileName(name, version)), nil | 467 | return svchost.ForDisplay(), nil |
363 | } | 468 | } |
364 | 469 | ||
365 | // Return the plugin version by making a HEAD request to the provided url. | 470 | // list all versions available for the named provider |
366 | // If the header is not present, we assume the latest version will be | 471 | func (i *ProviderInstaller) listProviderVersions(name string) (*response.TerraformProviderVersions, error) { |
367 | // compatible, and leave the check for discovery or execution. | 472 | provider := regsrc.NewTerraformProvider(name, i.OS, i.Arch) |
368 | func checkPlugin(url string, pluginProtocolVersion uint) bool { | 473 | versions, err := i.registry.TerraformProviderVersions(provider) |
369 | resp, err := httpClient.Head(url) | 474 | return versions, err |
370 | if err != nil { | 475 | } |
371 | log.Printf("[ERROR] error fetching plugin headers: %s", err) | ||
372 | return false | ||
373 | } | ||
374 | 476 | ||
375 | if resp.StatusCode != http.StatusOK { | 477 | func (i *ProviderInstaller) listProviderDownloadURLs(name, version string) (*response.TerraformProviderPlatformLocation, error) { |
376 | log.Println("[ERROR] non-200 status fetching plugin headers:", resp.Status) | 478 | urls, err := i.registry.TerraformProviderLocation(regsrc.NewTerraformProvider(name, i.OS, i.Arch), version) |
377 | return false | 479 | if urls == nil { |
480 | return nil, fmt.Errorf("No download urls found for provider %s", name) | ||
378 | } | 481 | } |
482 | return urls, err | ||
483 | } | ||
484 | |||
485 | // findClosestProtocolCompatibleVersion searches for the provider version with the closest protocol match. | ||
486 | // Prerelease versions are filtered. | ||
487 | func (i *ProviderInstaller) findClosestProtocolCompatibleVersion(versions []*response.TerraformProviderVersion) (*response.TerraformProviderVersion, error) { | ||
488 | // Loop through all the provider versions to find the earliest and latest | ||
489 | // versions that match the installer protocol to then select the closest of the two | ||
490 | var latest, earliest *response.TerraformProviderVersion | ||
491 | for _, version := range versions { | ||
492 | // Prereleases are filtered and will not be suggested | ||
493 | v, err := VersionStr(version.Version).Parse() | ||
494 | if err != nil || v.IsPrerelease() { | ||
495 | continue | ||
496 | } | ||
379 | 497 | ||
380 | proto := resp.Header.Get(protocolVersionHeader) | 498 | if err := i.checkPluginProtocol(version); err == nil { |
381 | if proto == "" { | 499 | if earliest == nil { |
382 | // The header isn't present, but we don't make this error fatal since | 500 | // Found the first provider version with compatible protocol |
383 | // the latest version will probably work. | 501 | earliest = version |
384 | log.Printf("[WARN] missing %s from: %s", protocolVersionHeader, url) | 502 | } |
385 | return true | 503 | // Update the latest protocol compatible version |
504 | latest = version | ||
505 | } | ||
506 | } | ||
507 | if earliest == nil { | ||
508 | // No compatible protocol was found for any version | ||
509 | return nil, ErrorNoVersionCompatible | ||
386 | } | 510 | } |
387 | 511 | ||
388 | protoVersion, err := strconv.Atoi(proto) | 512 | // Convert protocols to comparable types |
513 | protoString := strconv.Itoa(int(i.PluginProtocolVersion)) | ||
514 | protocolVersion, err := VersionStr(protoString).Parse() | ||
389 | if err != nil { | 515 | if err != nil { |
390 | log.Printf("[ERROR] invalid ProtocolVersion: %s", proto) | 516 | return nil, fmt.Errorf("invalid plugin protocol version: %q", i.PluginProtocolVersion) |
391 | return false | ||
392 | } | 517 | } |
393 | 518 | ||
394 | return protoVersion == int(pluginProtocolVersion) | 519 | earliestVersionProtocol, err := VersionStr(earliest.Protocols[0]).Parse() |
395 | } | ||
396 | |||
397 | // list the version available for the named plugin | ||
398 | func (i *ProviderInstaller) listProviderVersions(name string) ([]Version, error) { | ||
399 | versions, err := listPluginVersions(i.providerVersionsURL(name)) | ||
400 | if err != nil { | 520 | if err != nil { |
401 | // listPluginVersions returns a verbose error message indicating | ||
402 | // what was being accessed and what failed | ||
403 | return nil, err | 521 | return nil, err |
404 | } | 522 | } |
405 | return versions, nil | ||
406 | } | ||
407 | |||
408 | var errVersionNotFound = errors.New("version not found") | ||
409 | 523 | ||
410 | // take the list of available versions for a plugin, and filter out those that | 524 | // Compare installer protocol version with the first protocol listed of the earliest match |
411 | // don't fit the constraints. | 525 | // [A, B] where A is assumed the earliest compatible major version of the protocol pair |
412 | func allowedVersions(available []Version, required Constraints) []Version { | 526 | if protocolVersion.NewerThan(earliestVersionProtocol) { |
413 | var allowed []Version | 527 | // Provider protocols are too old, the closest version is the earliest compatible version |
414 | 528 | return earliest, nil | |
415 | for _, v := range available { | ||
416 | if required.Allows(v) { | ||
417 | allowed = append(allowed, v) | ||
418 | } | ||
419 | } | 529 | } |
420 | 530 | ||
421 | return allowed | 531 | // Provider protocols are too new, the closest version is the latest compatible version |
532 | return latest, nil | ||
422 | } | 533 | } |
423 | 534 | ||
424 | // return a list of the plugin versions at the given URL | 535 | func (i *ProviderInstaller) checkPluginProtocol(versionMeta *response.TerraformProviderVersion) error { |
425 | func listPluginVersions(url string) ([]Version, error) { | 536 | // TODO: should this be a different error? We should probably differentiate between |
426 | resp, err := httpClient.Get(url) | 537 | // no compatible versions and no protocol versions listed at all |
538 | if len(versionMeta.Protocols) == 0 { | ||
539 | return fmt.Errorf("no plugin protocol versions listed") | ||
540 | } | ||
541 | |||
542 | protoString := strconv.Itoa(int(i.PluginProtocolVersion)) | ||
543 | protocolVersion, err := VersionStr(protoString).Parse() | ||
427 | if err != nil { | 544 | if err != nil { |
428 | // http library produces a verbose error message that includes the | 545 | return fmt.Errorf("invalid plugin protocol version: %q", i.PluginProtocolVersion) |
429 | // URL being accessed, etc. | 546 | } |
430 | return nil, err | 547 | protocolConstraint, err := protocolVersion.MinorUpgradeConstraintStr().Parse() |
548 | if err != nil { | ||
549 | // This should not fail if the preceding function succeeded. | ||
550 | return fmt.Errorf("invalid plugin protocol version: %q", protocolVersion.String()) | ||
431 | } | 551 | } |
432 | defer resp.Body.Close() | ||
433 | 552 | ||
434 | if resp.StatusCode != http.StatusOK { | 553 | for _, p := range versionMeta.Protocols { |
435 | body, _ := ioutil.ReadAll(resp.Body) | 554 | proPro, err := VersionStr(p).Parse() |
436 | log.Printf("[ERROR] failed to fetch plugin versions from %s\n%s\n%s", url, resp.Status, body) | 555 | if err != nil { |
437 | 556 | // invalid protocol reported by the registry. Move along. | |
438 | switch resp.StatusCode { | 557 | log.Printf("[WARN] invalid provider protocol version %q found in the registry", versionMeta.Version) |
439 | case http.StatusNotFound, http.StatusForbidden: | 558 | continue |
440 | // These are treated as indicative of the given name not being | 559 | } |
441 | // a valid provider name at all. | 560 | // success! |
442 | return nil, ErrorNoSuchProvider | 561 | if protocolConstraint.Allows(proPro) { |
443 | 562 | return nil | |
444 | default: | ||
445 | // All other errors are assumed to be operational problems. | ||
446 | return nil, fmt.Errorf("error accessing %s: %s", url, resp.Status) | ||
447 | } | 563 | } |
448 | |||
449 | } | 564 | } |
450 | 565 | ||
451 | body, err := html.Parse(resp.Body) | 566 | return ErrorNoVersionCompatible |
452 | if err != nil { | 567 | } |
453 | log.Fatal(err) | 568 | |
569 | // REVIEWER QUESTION (again): this ends up swallowing a bunch of errors from | ||
570 | // checkPluginProtocol. Do they need to be percolated up better, or would | ||
571 | // debug messages would suffice in these situations? | ||
572 | func (i *ProviderInstaller) findPlatformCompatibleVersion(versions []*response.TerraformProviderVersion) (*response.TerraformProviderVersion, error) { | ||
573 | for _, version := range versions { | ||
574 | if err := i.checkPlatformCompatibility(version); err == nil { | ||
575 | return version, nil | ||
576 | } | ||
454 | } | 577 | } |
455 | 578 | ||
456 | names := []string{} | 579 | return nil, ErrorNoVersionCompatibleWithPlatform |
580 | } | ||
457 | 581 | ||
458 | // all we need to do is list links on the directory listing page that look like plugins | 582 | // platformCompatibleVersions returns a list of provider versions that are |
459 | var f func(*html.Node) | 583 | // compatible with the requested platform. |
460 | f = func(n *html.Node) { | 584 | func (i *ProviderInstaller) platformCompatibleVersions(versions []*response.TerraformProviderVersion) []*response.TerraformProviderVersion { |
461 | if n.Type == html.ElementNode && n.Data == "a" { | 585 | var v []*response.TerraformProviderVersion |
462 | c := n.FirstChild | 586 | for _, version := range versions { |
463 | if c != nil && c.Type == html.TextNode && strings.HasPrefix(c.Data, "terraform-") { | 587 | if err := i.checkPlatformCompatibility(version); err == nil { |
464 | names = append(names, c.Data) | 588 | v = append(v, version) |
465 | return | ||
466 | } | ||
467 | } | ||
468 | for c := n.FirstChild; c != nil; c = c.NextSibling { | ||
469 | f(c) | ||
470 | } | 589 | } |
471 | } | 590 | } |
472 | f(body) | 591 | return v |
592 | } | ||
473 | 593 | ||
474 | return versionsFromNames(names), nil | 594 | func (i *ProviderInstaller) checkPlatformCompatibility(versionMeta *response.TerraformProviderVersion) error { |
595 | if len(versionMeta.Platforms) == 0 { | ||
596 | return fmt.Errorf("no supported provider platforms listed") | ||
597 | } | ||
598 | for _, p := range versionMeta.Platforms { | ||
599 | if p.Arch == i.Arch && p.OS == i.OS { | ||
600 | return nil | ||
601 | } | ||
602 | } | ||
603 | return fmt.Errorf("version %s does not support the requested platform %s_%s", versionMeta.Version, i.OS, i.Arch) | ||
475 | } | 604 | } |
476 | 605 | ||
477 | // parse the list of directory names into a sorted list of available versions | 606 | // take the list of available versions for a plugin, and filter out those that |
478 | func versionsFromNames(names []string) []Version { | 607 | // don't fit the constraints. |
479 | var versions []Version | 608 | func allowedVersions(available *response.TerraformProviderVersions, required Constraints) []*response.TerraformProviderVersion { |
480 | for _, name := range names { | 609 | var allowed []*response.TerraformProviderVersion |
481 | parts := strings.SplitN(name, "_", 2) | ||
482 | if len(parts) == 2 && parts[1] != "" { | ||
483 | v, err := VersionStr(parts[1]).Parse() | ||
484 | if err != nil { | ||
485 | // filter invalid versions scraped from the page | ||
486 | log.Printf("[WARN] invalid version found for %q: %s", name, err) | ||
487 | continue | ||
488 | } | ||
489 | 610 | ||
490 | versions = append(versions, v) | 611 | for _, v := range available.Versions { |
612 | version, err := VersionStr(v.Version).Parse() | ||
613 | if err != nil { | ||
614 | log.Printf("[WARN] invalid version found for %q: %s", available.ID, err) | ||
615 | continue | ||
616 | } | ||
617 | if required.Allows(version) { | ||
618 | allowed = append(allowed, v) | ||
491 | } | 619 | } |
492 | } | 620 | } |
493 | 621 | return allowed | |
494 | return versions | ||
495 | } | 622 | } |
496 | 623 | ||
497 | func checksumForFile(sums []byte, name string) string { | 624 | func checksumForFile(sums []byte, name string) string { |
@@ -504,27 +631,6 @@ func checksumForFile(sums []byte, name string) string { | |||
504 | return "" | 631 | return "" |
505 | } | 632 | } |
506 | 633 | ||
507 | // fetch the SHA256SUMS file provided, and verify its signature. | ||
508 | func getPluginSHA256SUMs(sumsURL string) ([]byte, error) { | ||
509 | sigURL := sumsURL + ".sig" | ||
510 | |||
511 | sums, err := getFile(sumsURL) | ||
512 | if err != nil { | ||
513 | return nil, fmt.Errorf("error fetching checksums: %s", err) | ||
514 | } | ||
515 | |||
516 | sig, err := getFile(sigURL) | ||
517 | if err != nil { | ||
518 | return nil, fmt.Errorf("error fetching checksums signature: %s", err) | ||
519 | } | ||
520 | |||
521 | if err := verifySig(sums, sig); err != nil { | ||
522 | return nil, err | ||
523 | } | ||
524 | |||
525 | return sums, nil | ||
526 | } | ||
527 | |||
528 | func getFile(url string) ([]byte, error) { | 634 | func getFile(url string) ([]byte, error) { |
529 | resp, err := httpClient.Get(url) | 635 | resp, err := httpClient.Get(url) |
530 | if err != nil { | 636 | if err != nil { |
@@ -543,6 +649,41 @@ func getFile(url string) ([]byte, error) { | |||
543 | return data, nil | 649 | return data, nil |
544 | } | 650 | } |
545 | 651 | ||
546 | func GetReleaseHost() string { | 652 | // providerProtocolTooOld is a message sent to the CLI UI if the provider's |
547 | return releaseHost | 653 | // supported protocol versions are too old for the user's version of terraform, |
548 | } | 654 | // but an older version of the provider is compatible. |
655 | const providerProtocolTooOld = ` | ||
656 | [reset][bold][red]Provider %q v%s is not compatible with Terraform %s.[reset][red] | ||
657 | |||
658 | Provider version %s is the earliest compatible version. Select it with | ||
659 | the following version constraint: | ||
660 | |||
661 | version = %q | ||
662 | |||
663 | Terraform checked all of the plugin versions matching the given constraint: | ||
664 | %s | ||
665 | |||
666 | Consult the documentation for this provider for more information on | ||
667 | compatibility between provider and Terraform versions. | ||
668 | ` | ||
669 | |||
670 | // providerProtocolTooNew is a message sent to the CLI UI if the provider's | ||
671 | // supported protocol versions are too new for the user's version of terraform, | ||
672 | // and the user could either upgrade terraform or choose an older version of the | ||
673 | // provider | ||
674 | const providerProtocolTooNew = ` | ||
675 | [reset][bold][red]Provider %q v%s is not compatible with Terraform %s.[reset][red] | ||
676 | |||
677 | Provider version %s is the latest compatible version. Select it with | ||
678 | the following constraint: | ||
679 | |||
680 | version = %q | ||
681 | |||
682 | Terraform checked all of the plugin versions matching the given constraint: | ||
683 | %s | ||
684 | |||
685 | Consult the documentation for this provider for more information on | ||
686 | compatibility between provider and Terraform versions. | ||
687 | |||
688 | Alternatively, upgrade to the latest version of Terraform for compatibility with newer provider releases. | ||
689 | ` | ||
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/hashicorp.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/hashicorp.go new file mode 100644 index 0000000..4622ca0 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/hashicorp.go | |||
@@ -0,0 +1,34 @@ | |||
1 | package discovery | ||
2 | |||
3 | // HashicorpPublicKey is the HashiCorp public key, also available at | ||
4 | // https://www.hashicorp.com/security | ||
5 | const HashicorpPublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- | ||
6 | Version: GnuPG v1 | ||
7 | |||
8 | mQENBFMORM0BCADBRyKO1MhCirazOSVwcfTr1xUxjPvfxD3hjUwHtjsOy/bT6p9f | ||
9 | W2mRPfwnq2JB5As+paL3UGDsSRDnK9KAxQb0NNF4+eVhr/EJ18s3wwXXDMjpIifq | ||
10 | fIm2WyH3G+aRLTLPIpscUNKDyxFOUbsmgXAmJ46Re1fn8uKxKRHbfa39aeuEYWFA | ||
11 | 3drdL1WoUngvED7f+RnKBK2G6ZEpO+LDovQk19xGjiMTtPJrjMjZJ3QXqPvx5wca | ||
12 | KSZLr4lMTuoTI/ZXyZy5bD4tShiZz6KcyX27cD70q2iRcEZ0poLKHyEIDAi3TM5k | ||
13 | SwbbWBFd5RNPOR0qzrb/0p9ksKK48IIfH2FvABEBAAG0K0hhc2hpQ29ycCBTZWN1 | ||
14 | cml0eSA8c2VjdXJpdHlAaGFzaGljb3JwLmNvbT6JATgEEwECACIFAlMORM0CGwMG | ||
15 | CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEFGFLYc0j/xMyWIIAIPhcVqiQ59n | ||
16 | Jc07gjUX0SWBJAxEG1lKxfzS4Xp+57h2xxTpdotGQ1fZwsihaIqow337YHQI3q0i | ||
17 | SqV534Ms+j/tU7X8sq11xFJIeEVG8PASRCwmryUwghFKPlHETQ8jJ+Y8+1asRydi | ||
18 | psP3B/5Mjhqv/uOK+Vy3zAyIpyDOMtIpOVfjSpCplVRdtSTFWBu9Em7j5I2HMn1w | ||
19 | sJZnJgXKpybpibGiiTtmnFLOwibmprSu04rsnP4ncdC2XRD4wIjoyA+4PKgX3sCO | ||
20 | klEzKryWYBmLkJOMDdo52LttP3279s7XrkLEE7ia0fXa2c12EQ0f0DQ1tGUvyVEW | ||
21 | WmJVccm5bq25AQ0EUw5EzQEIANaPUY04/g7AmYkOMjaCZ6iTp9hB5Rsj/4ee/ln9 | ||
22 | wArzRO9+3eejLWh53FoN1rO+su7tiXJA5YAzVy6tuolrqjM8DBztPxdLBbEi4V+j | ||
23 | 2tK0dATdBQBHEh3OJApO2UBtcjaZBT31zrG9K55D+CrcgIVEHAKY8Cb4kLBkb5wM | ||
24 | skn+DrASKU0BNIV1qRsxfiUdQHZfSqtp004nrql1lbFMLFEuiY8FZrkkQ9qduixo | ||
25 | mTT6f34/oiY+Jam3zCK7RDN/OjuWheIPGj/Qbx9JuNiwgX6yRj7OE1tjUx6d8g9y | ||
26 | 0H1fmLJbb3WZZbuuGFnK6qrE3bGeY8+AWaJAZ37wpWh1p0cAEQEAAYkBHwQYAQIA | ||
27 | CQUCUw5EzQIbDAAKCRBRhS2HNI/8TJntCAClU7TOO/X053eKF1jqNW4A1qpxctVc | ||
28 | z8eTcY8Om5O4f6a/rfxfNFKn9Qyja/OG1xWNobETy7MiMXYjaa8uUx5iFy6kMVaP | ||
29 | 0BXJ59NLZjMARGw6lVTYDTIvzqqqwLxgliSDfSnqUhubGwvykANPO+93BBx89MRG | ||
30 | unNoYGXtPlhNFrAsB1VR8+EyKLv2HQtGCPSFBhrjuzH3gxGibNDDdFQLxxuJWepJ | ||
31 | EK1UbTS4ms0NgZ2Uknqn1WRU1Ki7rE4sTy68iZtWpKQXZEJa0IGnuI2sSINGcXCJ | ||
32 | oEIgXTMyCILo34Fa/C6VCm2WBgz9zZO8/rHIiQm1J5zqz0DrDwKBUM9C | ||
33 | =LYpS | ||
34 | -----END PGP PUBLIC KEY BLOCK-----` | ||
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go index 181ea1f..3a99289 100644 --- a/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go +++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go | |||
@@ -63,7 +63,7 @@ func (s PluginMetaSet) WithName(name string) PluginMetaSet { | |||
63 | // WithVersion returns the subset of metas that have the given version. | 63 | // WithVersion returns the subset of metas that have the given version. |
64 | // | 64 | // |
65 | // This should be used only with the "valid" result from ValidateVersions; | 65 | // This should be used only with the "valid" result from ValidateVersions; |
66 | // it will ignore any plugin metas that have a invalid version strings. | 66 | // it will ignore any plugin metas that have invalid version strings. |
67 | func (s PluginMetaSet) WithVersion(version Version) PluginMetaSet { | 67 | func (s PluginMetaSet) WithVersion(version Version) PluginMetaSet { |
68 | ns := make(PluginMetaSet) | 68 | ns := make(PluginMetaSet) |
69 | for p := range s { | 69 | for p := range s { |
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/requirements.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/requirements.go index 75430fd..0466ab2 100644 --- a/vendor/github.com/hashicorp/terraform/plugin/discovery/requirements.go +++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/requirements.go | |||
@@ -4,6 +4,12 @@ import ( | |||
4 | "bytes" | 4 | "bytes" |
5 | ) | 5 | ) |
6 | 6 | ||
7 | // PluginInstallProtocolVersion is the protocol version TF-core | ||
8 | // supports to communicate with servers, and is used to resolve | ||
9 | // plugin discovery with terraform registry, in addition to | ||
10 | // any specified plugin version constraints | ||
11 | const PluginInstallProtocolVersion = 5 | ||
12 | |||
7 | // PluginRequirements describes a set of plugins (assumed to be of a consistent | 13 | // PluginRequirements describes a set of plugins (assumed to be of a consistent |
8 | // kind) that are required to exist and have versions within the given | 14 | // kind) that are required to exist and have versions within the given |
9 | // corresponding sets. | 15 | // corresponding sets. |
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/signature.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/signature.go index b6686a5..7bbae50 100644 --- a/vendor/github.com/hashicorp/terraform/plugin/discovery/signature.go +++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/signature.go | |||
@@ -2,7 +2,6 @@ package discovery | |||
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "bytes" | 4 | "bytes" |
5 | "log" | ||
6 | "strings" | 5 | "strings" |
7 | 6 | ||
8 | "golang.org/x/crypto/openpgp" | 7 | "golang.org/x/crypto/openpgp" |
@@ -10,44 +9,11 @@ import ( | |||
10 | 9 | ||
11 | // Verify the data using the provided openpgp detached signature and the | 10 | // Verify the data using the provided openpgp detached signature and the |
12 | // embedded hashicorp public key. | 11 | // embedded hashicorp public key. |
13 | func verifySig(data, sig []byte) error { | 12 | func verifySig(data, sig []byte, armor string) (*openpgp.Entity, error) { |
14 | el, err := openpgp.ReadArmoredKeyRing(strings.NewReader(hashiPublicKey)) | 13 | el, err := openpgp.ReadArmoredKeyRing(strings.NewReader(armor)) |
15 | if err != nil { | 14 | if err != nil { |
16 | log.Fatal(err) | 15 | return nil, err |
17 | } | 16 | } |
18 | 17 | ||
19 | _, err = openpgp.CheckDetachedSignature(el, bytes.NewReader(data), bytes.NewReader(sig)) | 18 | return openpgp.CheckDetachedSignature(el, bytes.NewReader(data), bytes.NewReader(sig)) |
20 | return err | ||
21 | } | 19 | } |
22 | |||
23 | // this is the public key that signs the checksums file for releases. | ||
24 | const hashiPublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- | ||
25 | Version: GnuPG v1 | ||
26 | |||
27 | mQENBFMORM0BCADBRyKO1MhCirazOSVwcfTr1xUxjPvfxD3hjUwHtjsOy/bT6p9f | ||
28 | W2mRPfwnq2JB5As+paL3UGDsSRDnK9KAxQb0NNF4+eVhr/EJ18s3wwXXDMjpIifq | ||
29 | fIm2WyH3G+aRLTLPIpscUNKDyxFOUbsmgXAmJ46Re1fn8uKxKRHbfa39aeuEYWFA | ||
30 | 3drdL1WoUngvED7f+RnKBK2G6ZEpO+LDovQk19xGjiMTtPJrjMjZJ3QXqPvx5wca | ||
31 | KSZLr4lMTuoTI/ZXyZy5bD4tShiZz6KcyX27cD70q2iRcEZ0poLKHyEIDAi3TM5k | ||
32 | SwbbWBFd5RNPOR0qzrb/0p9ksKK48IIfH2FvABEBAAG0K0hhc2hpQ29ycCBTZWN1 | ||
33 | cml0eSA8c2VjdXJpdHlAaGFzaGljb3JwLmNvbT6JATgEEwECACIFAlMORM0CGwMG | ||
34 | CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEFGFLYc0j/xMyWIIAIPhcVqiQ59n | ||
35 | Jc07gjUX0SWBJAxEG1lKxfzS4Xp+57h2xxTpdotGQ1fZwsihaIqow337YHQI3q0i | ||
36 | SqV534Ms+j/tU7X8sq11xFJIeEVG8PASRCwmryUwghFKPlHETQ8jJ+Y8+1asRydi | ||
37 | psP3B/5Mjhqv/uOK+Vy3zAyIpyDOMtIpOVfjSpCplVRdtSTFWBu9Em7j5I2HMn1w | ||
38 | sJZnJgXKpybpibGiiTtmnFLOwibmprSu04rsnP4ncdC2XRD4wIjoyA+4PKgX3sCO | ||
39 | klEzKryWYBmLkJOMDdo52LttP3279s7XrkLEE7ia0fXa2c12EQ0f0DQ1tGUvyVEW | ||
40 | WmJVccm5bq25AQ0EUw5EzQEIANaPUY04/g7AmYkOMjaCZ6iTp9hB5Rsj/4ee/ln9 | ||
41 | wArzRO9+3eejLWh53FoN1rO+su7tiXJA5YAzVy6tuolrqjM8DBztPxdLBbEi4V+j | ||
42 | 2tK0dATdBQBHEh3OJApO2UBtcjaZBT31zrG9K55D+CrcgIVEHAKY8Cb4kLBkb5wM | ||
43 | skn+DrASKU0BNIV1qRsxfiUdQHZfSqtp004nrql1lbFMLFEuiY8FZrkkQ9qduixo | ||
44 | mTT6f34/oiY+Jam3zCK7RDN/OjuWheIPGj/Qbx9JuNiwgX6yRj7OE1tjUx6d8g9y | ||
45 | 0H1fmLJbb3WZZbuuGFnK6qrE3bGeY8+AWaJAZ37wpWh1p0cAEQEAAYkBHwQYAQIA | ||
46 | CQUCUw5EzQIbDAAKCRBRhS2HNI/8TJntCAClU7TOO/X053eKF1jqNW4A1qpxctVc | ||
47 | z8eTcY8Om5O4f6a/rfxfNFKn9Qyja/OG1xWNobETy7MiMXYjaa8uUx5iFy6kMVaP | ||
48 | 0BXJ59NLZjMARGw6lVTYDTIvzqqqwLxgliSDfSnqUhubGwvykANPO+93BBx89MRG | ||
49 | unNoYGXtPlhNFrAsB1VR8+EyKLv2HQtGCPSFBhrjuzH3gxGibNDDdFQLxxuJWepJ | ||
50 | EK1UbTS4ms0NgZ2Uknqn1WRU1Ki7rE4sTy68iZtWpKQXZEJa0IGnuI2sSINGcXCJ | ||
51 | oEIgXTMyCILo34Fa/C6VCm2WBgz9zZO8/rHIiQm1J5zqz0DrDwKBUM9C | ||
52 | =LYpS | ||
53 | -----END PGP PUBLIC KEY BLOCK-----` | ||
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/version.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/version.go index 8fad58d..4311d51 100644 --- a/vendor/github.com/hashicorp/terraform/plugin/discovery/version.go +++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/version.go | |||
@@ -55,6 +55,11 @@ func (v Version) Equal(other Version) bool { | |||
55 | return v.raw.Equal(other.raw) | 55 | return v.raw.Equal(other.raw) |
56 | } | 56 | } |
57 | 57 | ||
58 | // IsPrerelease determines if version is a prerelease | ||
59 | func (v Version) IsPrerelease() bool { | ||
60 | return v.raw.Prerelease() != "" | ||
61 | } | ||
62 | |||
58 | // MinorUpgradeConstraintStr returns a ConstraintStr that would permit | 63 | // MinorUpgradeConstraintStr returns a ConstraintStr that would permit |
59 | // minor upgrades relative to the receiving version. | 64 | // minor upgrades relative to the receiving version. |
60 | func (v Version) MinorUpgradeConstraintStr() ConstraintStr { | 65 | func (v Version) MinorUpgradeConstraintStr() ConstraintStr { |
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/version_set.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/version_set.go index 0aefd75..de02f5e 100644 --- a/vendor/github.com/hashicorp/terraform/plugin/discovery/version_set.go +++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/version_set.go | |||
@@ -36,6 +36,11 @@ type Constraints struct { | |||
36 | raw version.Constraints | 36 | raw version.Constraints |
37 | } | 37 | } |
38 | 38 | ||
39 | // NewConstraints creates a Constraints based on a version.Constraints. | ||
40 | func NewConstraints(c version.Constraints) Constraints { | ||
41 | return Constraints{c} | ||
42 | } | ||
43 | |||
39 | // AllVersions is a Constraints containing all versions | 44 | // AllVersions is a Constraints containing all versions |
40 | var AllVersions Constraints | 45 | var AllVersions Constraints |
41 | 46 | ||