From 8b279b6f34abd7bc492f1d2e5e6818a7ce75c8eb Mon Sep 17 00:00:00 2001 From: Alisdair McDiarmid Date: Thu, 28 May 2020 15:11:04 -0400 Subject: [PATCH] plugin/discovery: Remove dead code Provider installation is now handled in the internal/getproviders package instead. --- plugin/discovery/error.go | 64 -- plugin/discovery/get.go | 693 ---------------- plugin/discovery/get_test.go | 778 ------------------ plugin/discovery/hashicorp.go | 34 - plugin/discovery/signature.go | 19 - plugin/discovery/testdata/hashicorp.asc | 30 - ...terraform-provider-badsig_0.1.0_SHA256SUMS | 12 - ...aform-provider-badsig_0.1.0_SHA256SUMS.sig | Bin 287 -> 0 bytes ...rraform-provider-template_0.1.0_SHA256SUMS | 12 - ...orm-provider-template_0.1.0_SHA256SUMS.sig | Bin 287 -> 0 bytes 10 files changed, 1642 deletions(-) delete mode 100644 plugin/discovery/error.go delete mode 100644 plugin/discovery/get.go delete mode 100644 plugin/discovery/get_test.go delete mode 100644 plugin/discovery/hashicorp.go delete mode 100644 plugin/discovery/signature.go delete mode 100644 plugin/discovery/testdata/hashicorp.asc delete mode 100644 plugin/discovery/testdata/terraform-provider-badsig_0.1.0_SHA256SUMS delete mode 100644 plugin/discovery/testdata/terraform-provider-badsig_0.1.0_SHA256SUMS.sig delete mode 100644 plugin/discovery/testdata/terraform-provider-template_0.1.0_SHA256SUMS delete mode 100644 plugin/discovery/testdata/terraform-provider-template_0.1.0_SHA256SUMS.sig diff --git a/plugin/discovery/error.go b/plugin/discovery/error.go deleted file mode 100644 index 729e97099..000000000 --- a/plugin/discovery/error.go +++ /dev/null @@ -1,64 +0,0 @@ -package discovery - -// Error is a type used to describe situations that the caller must handle -// since they indicate some form of user error. -// -// The functions and methods that return these specialized errors indicate so -// in their documentation. The Error type should not itself be used directly, -// but rather errors should be compared using the == operator with the -// error constants in this package. -// -// Values of this type are _not_ used when the error being reported is an -// operational error (server unavailable, etc) or indicative of a bug in -// this package or its caller. -type Error string - -// ErrorNoSuitableVersion indicates that a suitable version (meeting given -// constraints) is not available. -const ErrorNoSuitableVersion = Error("no suitable version is available") - -// ErrorNoVersionCompatible indicates that all of the available versions -// that otherwise met constraints are not compatible with the current -// version of Terraform. -const ErrorNoVersionCompatible = Error("no available version is compatible with this version of Terraform") - -// ErrorVersionIncompatible indicates that all of the versions within the -// constraints are not compatible with the current version of Terrafrom, though -// there does exist a version outside of the constaints that is compatible. -const ErrorVersionIncompatible = Error("incompatible provider version") - -// ErrorNoSuchProvider indicates that no provider exists with a name given -const ErrorNoSuchProvider = Error("no provider exists with the given name") - -// ErrorNoVersionCompatibleWithPlatform indicates that all of the available -// versions that otherwise met constraints are not compatible with the -// requested platform -const ErrorNoVersionCompatibleWithPlatform = Error("no available version is compatible for the requested platform") - -// ErrorMissingChecksumVerification indicates that either the provider -// distribution is missing the SHA256SUMS file or the checksum file does -// not contain a checksum for the binary plugin -const ErrorMissingChecksumVerification = Error("unable to verify checksum") - -// ErrorChecksumVerification indicates that the current checksum of the -// provider plugin has changed since the initial release and is not trusted -// to download -const ErrorChecksumVerification = Error("unexpected plugin checksum") - -// ErrorSignatureVerification indicates that the digital signature for a -// provider distribution could not be verified for one of the following -// reasons: missing signature file, missing public key, or the signature -// was not signed by any known key for the publisher -const ErrorSignatureVerification = Error("unable to verify signature") - -// ErrorServiceUnreachable indicates that the network was unable to connect -// to the registry service -const ErrorServiceUnreachable = Error("registry service is unreachable") - -// ErrorPublicRegistryUnreachable indicates that the network was unable to connect -// to the public registry in particular, so we can show a link to the statuspage -const ErrorPublicRegistryUnreachable = Error("registry service is unreachable, check https://status.hashicorp.com/ for status updates") - -func (err Error) Error() string { - return string(err) -} diff --git a/plugin/discovery/get.go b/plugin/discovery/get.go deleted file mode 100644 index 7c63d4c84..000000000 --- a/plugin/discovery/get.go +++ /dev/null @@ -1,693 +0,0 @@ -package discovery - -import ( - "errors" - "fmt" - "io" - "io/ioutil" - "log" - "net/http" - "os" - "path/filepath" - "runtime" - "strconv" - "strings" - - "github.com/hashicorp/errwrap" - getter "github.com/hashicorp/go-getter" - multierror "github.com/hashicorp/go-multierror" - "github.com/hashicorp/terraform-svchost/disco" - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/httpclient" - "github.com/hashicorp/terraform/registry" - "github.com/hashicorp/terraform/registry/regsrc" - "github.com/hashicorp/terraform/registry/response" - "github.com/hashicorp/terraform/tfdiags" - tfversion "github.com/hashicorp/terraform/version" - "github.com/mitchellh/cli" -) - -// Releases are located by querying the terraform registry. - -const protocolVersionHeader = "x-terraform-protocol-version" - -var httpClient *http.Client - -var errVersionNotFound = errors.New("version not found") - -func init() { - httpClient = httpclient.New() - - httpGetter := &getter.HttpGetter{ - Client: httpClient, - Netrc: true, - } - - getter.Getters["http"] = httpGetter - getter.Getters["https"] = httpGetter -} - -// An Installer maintains a local cache of plugins by downloading plugins -// from an online repository. -type Installer interface { - Get(provider addrs.Provider, req Constraints) (PluginMeta, tfdiags.Diagnostics, error) - PurgeUnused(used map[string]PluginMeta) (removed PluginMetaSet, err error) -} - -// ProviderInstaller is an Installer implementation that knows how to -// download Terraform providers from the official HashiCorp releases service -// into a local directory. The files downloaded are compliant with the -// naming scheme expected by FindPlugins, so the target directory of a -// provider installer can be used as one of several plugin discovery sources. -type ProviderInstaller struct { - Dir string - - // Cache is used to access and update a local cache of plugins if non-nil. - // Can be nil to disable caching. - Cache PluginCache - - PluginProtocolVersion uint - - // OS and Arch specify the OS and architecture that should be used when - // installing plugins. These use the same labels as the runtime.GOOS and - // runtime.GOARCH variables respectively, and indeed the values of these - // are used as defaults if either of these is the empty string. - OS string - Arch string - - // Skip checksum and signature verification - SkipVerify bool - - Ui cli.Ui // Ui for output - - // Services is a required *disco.Disco, which may have services and - // credentials pre-loaded. - Services *disco.Disco - - // registry client - registry *registry.Client -} - -// Get is part of an implementation of type Installer, and attempts to download -// and install a Terraform provider matching the given constraints. -// -// This method may return one of a number of sentinel errors from this -// package to indicate issues that are likely to be resolvable via user action: -// -// ErrorNoSuchProvider: no provider with the given name exists in the repository. -// ErrorNoSuitableVersion: the provider exists but no available version matches constraints. -// ErrorNoVersionCompatible: a plugin was found within the constraints but it is -// incompatible with the current Terraform version. -// -// These errors should be recognized and handled as special cases by the caller -// to present a suitable user-oriented error message. -// -// All other errors indicate an internal problem that is likely _not_ solvable -// through user action, or at least not within Terraform's scope. Error messages -// are produced under the assumption that if presented to the user they will -// be presented alongside context about what is being installed, and thus the -// error messages do not redundantly include such information. -func (i *ProviderInstaller) Get(provider addrs.Provider, req Constraints) (PluginMeta, tfdiags.Diagnostics, error) { - var diags tfdiags.Diagnostics - - // a little bit of initialization. - if i.OS == "" { - i.OS = runtime.GOOS - } - if i.Arch == "" { - i.Arch = runtime.GOARCH - } - if i.registry == nil { - i.registry = registry.NewClient(i.Services, nil) - } - - // get a full listing of versions for the requested provider - allVersions, err := i.listProviderVersions(provider) - - // TODO: return multiple errors - if err != nil { - log.Printf("[DEBUG] %s", err) - if registry.IsServiceUnreachable(err) { - registryHost, err := i.hostname() - if err == nil && registryHost == regsrc.PublicRegistryHost.Raw { - return PluginMeta{}, diags, ErrorPublicRegistryUnreachable - } - return PluginMeta{}, diags, ErrorServiceUnreachable - } - if registry.IsServiceNotProvided(err) { - return PluginMeta{}, diags, err - } - return PluginMeta{}, diags, ErrorNoSuchProvider - } - - // Add any warnings from the response to diags - for _, warning := range allVersions.Warnings { - hostname, err := i.hostname() - if err != nil { - return PluginMeta{}, diags, err - } - diag := tfdiags.SimpleWarning(fmt.Sprintf("%s: %s", hostname, warning)) - diags = diags.Append(diag) - } - - if len(allVersions.Versions) == 0 { - return PluginMeta{}, diags, ErrorNoSuitableVersion - } - providerSource := allVersions.ID - - // Filter the list of plugin versions to those which meet the version constraints - versions := allowedVersions(allVersions, req) - if len(versions) == 0 { - return PluginMeta{}, diags, ErrorNoSuitableVersion - } - - // sort them newest to oldest. The newest version wins! - response.ProviderVersionCollection(versions).Sort() - - // if the chosen provider version does not support the requested platform, - // filter the list of acceptable versions to those that support that platform - if err := i.checkPlatformCompatibility(versions[0]); err != nil { - versions = i.platformCompatibleVersions(versions) - if len(versions) == 0 { - return PluginMeta{}, diags, ErrorNoVersionCompatibleWithPlatform - } - } - - // we now have a winning platform-compatible version - versionMeta := versions[0] - v := VersionStr(versionMeta.Version).MustParse() - - // check protocol compatibility - if err := i.checkPluginProtocol(versionMeta); err != nil { - closestMatch, err := i.findClosestProtocolCompatibleVersion(allVersions.Versions) - if err != nil { - // No operation here if we can't find a version with compatible protocol - return PluginMeta{}, diags, err - } - - // Prompt version suggestion to UI based on closest protocol match - var errMsg string - closestVersion := VersionStr(closestMatch.Version).MustParse() - if v.NewerThan(closestVersion) { - errMsg = providerProtocolTooNew - } else { - errMsg = providerProtocolTooOld - } - - constraintStr := req.String() - if constraintStr == "" { - constraintStr = "(any version)" - } - - return PluginMeta{}, diags, errwrap.Wrap(ErrorVersionIncompatible, fmt.Errorf(fmt.Sprintf( - errMsg, provider.LegacyString(), v.String(), tfversion.String(), - closestVersion.String(), closestVersion.MinorUpgradeConstraintStr(), constraintStr))) - } - - downloadURLs, err := i.listProviderDownloadURLs(providerSource, versionMeta.Version) - if err != nil { - return PluginMeta{}, diags, err - } - providerURL := downloadURLs.DownloadURL - - if !i.SkipVerify { - // Terraform verifies the integrity of a provider release before downloading - // the plugin binary. The digital signature (SHA256SUMS.sig) on the - // release distribution (SHA256SUMS) is verified with the public key of the - // publisher provided in the Terraform Registry response, ensuring that - // everything is as intended by the publisher. The checksum of the provider - // plugin is expected in the SHA256SUMS file and is double checked to match - // the checksum of the original published release to the Registry. This - // enforces immutability of releases between the Registry and the plugin's - // host location. Lastly, the integrity of the binary is verified upon - // download matches the Registry and signed checksum. - sha256, err := i.getProviderChecksum(downloadURLs) - if err != nil { - return PluginMeta{}, diags, err - } - - // add the checksum parameter for go-getter to verify the download for us. - if sha256 != "" { - providerURL = providerURL + "?checksum=sha256:" + sha256 - } - } - - printedProviderName := fmt.Sprintf("%q (%s)", provider.LegacyString(), providerSource) - i.Ui.Info(fmt.Sprintf("- Downloading plugin for provider %s %s...", printedProviderName, versionMeta.Version)) - log.Printf("[DEBUG] getting provider %s version %q", printedProviderName, versionMeta.Version) - err = i.install(provider, v, providerURL) - if err != nil { - return PluginMeta{}, diags, err - } - - // Find what we just installed - // (This is weird, because go-getter doesn't directly return - // information about what was extracted, and we just extracted - // the archive directly into a shared dir here.) - log.Printf("[DEBUG] looking for the %s %s plugin we just installed", provider.LegacyString(), versionMeta.Version) - metas := FindPlugins("provider", []string{i.Dir}) - log.Printf("[DEBUG] all plugins found %#v", metas) - metas, _ = metas.ValidateVersions() - metas = metas.WithName(provider.Type).WithVersion(v) - log.Printf("[DEBUG] filtered plugins %#v", metas) - if metas.Count() == 0 { - // This should never happen. Suggests that the release archive - // contains an executable file whose name doesn't match the - // expected convention. - return PluginMeta{}, diags, fmt.Errorf( - "failed to find installed plugin version %s; this is a bug in Terraform and should be reported", - versionMeta.Version, - ) - } - - if metas.Count() > 1 { - // This should also never happen, and suggests that a - // particular version was re-released with a different - // executable filename. We consider releases as immutable, so - // this is an error. - return PluginMeta{}, diags, fmt.Errorf( - "multiple plugins installed for version %s; this is a bug in Terraform and should be reported", - versionMeta.Version, - ) - } - - // By now we know we have exactly one meta, and so "Newest" will - // return that one. - return metas.Newest(), diags, nil -} - -func (i *ProviderInstaller) install(provider addrs.Provider, version Version, url string) error { - if i.Cache != nil { - log.Printf("[DEBUG] looking for provider %s %s in plugin cache", provider.LegacyString(), version) - cached := i.Cache.CachedPluginPath("provider", provider.Type, version) - if cached == "" { - log.Printf("[DEBUG] %s %s not yet in cache, so downloading %s", provider.LegacyString(), version, url) - err := getter.Get(i.Cache.InstallDir(), url) - if err != nil { - return err - } - // should now be in cache - cached = i.Cache.CachedPluginPath("provider", provider.Type, version) - if cached == "" { - // should never happen if the getter is behaving properly - // and the plugins are packaged properly. - return fmt.Errorf("failed to find downloaded plugin in cache %s", i.Cache.InstallDir()) - } - } - - // Link or copy the cached binary into our install dir so the - // normal resolution machinery can find it. - filename := filepath.Base(cached) - targetPath := filepath.Join(i.Dir, filename) - // check if the target dir exists, and create it if not - var err error - if _, StatErr := os.Stat(i.Dir); os.IsNotExist(StatErr) { - err = os.MkdirAll(i.Dir, 0700) - } - if err != nil { - return err - } - - log.Printf("[DEBUG] installing %s %s to %s from local cache %s", provider.LegacyString(), version, targetPath, cached) - - // Delete if we can. If there's nothing there already then no harm done. - // This is important because we can't create a link if there's - // already a file of the same name present. - // (any other error here we'll catch below when we try to write here) - os.Remove(targetPath) - - // We don't attempt linking on Windows because links are not - // comprehensively supported by all tools/apps in Windows and - // so we choose to be conservative to avoid creating any - // weird issues for Windows users. - linkErr := errors.New("link not supported for Windows") // placeholder error, never actually returned - if runtime.GOOS != "windows" { - // Try hard linking first. Hard links are preferable because this - // creates a self-contained directory that doesn't depend on the - // cache after install. - linkErr = os.Link(cached, targetPath) - - // If that failed, try a symlink. This _does_ depend on the cache - // after install, so the user must manage the cache more carefully - // in this case, but avoids creating redundant copies of the - // plugins on disk. - if linkErr != nil { - linkErr = os.Symlink(cached, targetPath) - } - } - - // If we still have an error then we'll try a copy as a fallback. - // In this case either the OS is Windows or the target filesystem - // can't support symlinks. - if linkErr != nil { - srcFile, err := os.Open(cached) - if err != nil { - return fmt.Errorf("failed to open cached plugin %s: %s", cached, err) - } - defer srcFile.Close() - - destFile, err := os.OpenFile(targetPath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, os.ModePerm) - if err != nil { - return fmt.Errorf("failed to create %s: %s", targetPath, err) - } - - _, err = io.Copy(destFile, srcFile) - if err != nil { - destFile.Close() - return fmt.Errorf("failed to copy cached plugin from %s to %s: %s", cached, targetPath, err) - } - - err = destFile.Close() - if err != nil { - return fmt.Errorf("error creating %s: %s", targetPath, err) - } - } - - // One way or another, by the time we get here we should have either - // a link or a copy of the cached plugin within i.Dir, as expected. - } else { - log.Printf("[DEBUG] plugin cache is disabled, so downloading %s %s from %s", provider.LegacyString(), version, url) - err := getter.Get(i.Dir, url) - if err != nil { - return err - } - } - return nil -} - -func (i *ProviderInstaller) PurgeUnused(used map[string]PluginMeta) (PluginMetaSet, error) { - purge := make(PluginMetaSet) - - present := FindPlugins("provider", []string{i.Dir}) - for meta := range present { - chosen, ok := used[meta.Name] - if !ok { - purge.Add(meta) - } - if chosen.Path != meta.Path { - purge.Add(meta) - } - } - - removed := make(PluginMetaSet) - var errs error - for meta := range purge { - path := meta.Path - err := os.Remove(path) - if err != nil { - errs = multierror.Append(errs, fmt.Errorf( - "failed to remove unused provider plugin %s: %s", - path, err, - )) - } else { - removed.Add(meta) - } - } - - return removed, errs -} - -func (i *ProviderInstaller) getProviderChecksum(resp *response.TerraformProviderPlatformLocation) (string, error) { - // Get SHA256SUMS file. - shasums, err := getFile(resp.ShasumsURL) - if err != nil { - log.Printf("[ERROR] error fetching checksums from %q: %s", resp.ShasumsURL, err) - return "", ErrorMissingChecksumVerification - } - - // Get SHA256SUMS.sig file. - signature, err := getFile(resp.ShasumsSignatureURL) - if err != nil { - log.Printf("[ERROR] error fetching checksums signature from %q: %s", resp.ShasumsSignatureURL, err) - return "", ErrorSignatureVerification - } - - // Verify the GPG signature returned from the Registry. - asciiArmor := resp.SigningKeys.GPGASCIIArmor() - signer, err := verifySig(shasums, signature, asciiArmor) - if err != nil { - log.Printf("[ERROR] error verifying signature: %s", err) - return "", ErrorSignatureVerification - } - - // Also verify the GPG signature against the HashiCorp public key. This is - // a temporary additional check until a more robust key verification - // process is added in a future release. - _, err = verifySig(shasums, signature, HashicorpPublicKey) - if err != nil { - log.Printf("[ERROR] error verifying signature against HashiCorp public key: %s", err) - return "", ErrorSignatureVerification - } - - // Display identity for GPG key which succeeded verifying the signature. - // This could also be used to display to the user with i.Ui.Info(). - identities := []string{} - for k := range signer.Identities { - identities = append(identities, k) - } - identity := strings.Join(identities, ", ") - log.Printf("[DEBUG] verified GPG signature with key from %s", identity) - - // Extract checksum for this os/arch platform binary and verify against Registry - checksum := checksumForFile(shasums, resp.Filename) - if checksum == "" { - log.Printf("[ERROR] missing checksum for %s from source %s", resp.Filename, resp.ShasumsURL) - return "", ErrorMissingChecksumVerification - } else if checksum != resp.Shasum { - log.Printf("[ERROR] unexpected checksum for %s from source %q", resp.Filename, resp.ShasumsURL) - return "", ErrorChecksumVerification - } - - return checksum, nil -} - -func (i *ProviderInstaller) hostname() (string, error) { - provider := regsrc.NewTerraformProvider("", i.OS, i.Arch) - svchost, err := provider.SvcHost() - if err != nil { - return "", err - } - - return svchost.ForDisplay(), nil -} - -// list all versions available for the named provider -func (i *ProviderInstaller) listProviderVersions(provider addrs.Provider) (*response.TerraformProviderVersions, error) { - req := regsrc.NewTerraformProvider(provider.Type, i.OS, i.Arch) - versions, err := i.registry.TerraformProviderVersions(req) - return versions, err -} - -func (i *ProviderInstaller) listProviderDownloadURLs(name, version string) (*response.TerraformProviderPlatformLocation, error) { - urls, err := i.registry.TerraformProviderLocation(regsrc.NewTerraformProvider(name, i.OS, i.Arch), version) - if urls == nil { - return nil, fmt.Errorf("No download urls found for provider %s", name) - } - return urls, err -} - -// findClosestProtocolCompatibleVersion searches for the provider version with the closest protocol match. -// Prerelease versions are filtered. -func (i *ProviderInstaller) findClosestProtocolCompatibleVersion(versions []*response.TerraformProviderVersion) (*response.TerraformProviderVersion, error) { - // Loop through all the provider versions to find the earliest and latest - // versions that match the installer protocol to then select the closest of the two - var latest, earliest *response.TerraformProviderVersion - for _, version := range versions { - // Prereleases are filtered and will not be suggested - v, err := VersionStr(version.Version).Parse() - if err != nil || v.IsPrerelease() { - continue - } - - if err := i.checkPluginProtocol(version); err == nil { - if earliest == nil { - // Found the first provider version with compatible protocol - earliest = version - } - // Update the latest protocol compatible version - latest = version - } - } - if earliest == nil { - // No compatible protocol was found for any version - return nil, ErrorNoVersionCompatible - } - - // Convert protocols to comparable types - protoString := strconv.Itoa(int(i.PluginProtocolVersion)) - protocolVersion, err := VersionStr(protoString).Parse() - if err != nil { - return nil, fmt.Errorf("invalid plugin protocol version: %q", i.PluginProtocolVersion) - } - - earliestVersionProtocol, err := VersionStr(earliest.Protocols[0]).Parse() - if err != nil { - return nil, err - } - - // Compare installer protocol version with the first protocol listed of the earliest match - // [A, B] where A is assumed the earliest compatible major version of the protocol pair - if protocolVersion.NewerThan(earliestVersionProtocol) { - // Provider protocols are too old, the closest version is the earliest compatible version - return earliest, nil - } - - // Provider protocols are too new, the closest version is the latest compatible version - return latest, nil -} - -func (i *ProviderInstaller) checkPluginProtocol(versionMeta *response.TerraformProviderVersion) error { - // TODO: should this be a different error? We should probably differentiate between - // no compatible versions and no protocol versions listed at all - if len(versionMeta.Protocols) == 0 { - return fmt.Errorf("no plugin protocol versions listed") - } - - protoString := strconv.Itoa(int(i.PluginProtocolVersion)) - protocolVersion, err := VersionStr(protoString).Parse() - if err != nil { - return fmt.Errorf("invalid plugin protocol version: %q", i.PluginProtocolVersion) - } - protocolConstraint, err := protocolVersion.MinorUpgradeConstraintStr().Parse() - if err != nil { - // This should not fail if the preceding function succeeded. - return fmt.Errorf("invalid plugin protocol version: %q", protocolVersion.String()) - } - - for _, p := range versionMeta.Protocols { - proPro, err := VersionStr(p).Parse() - if err != nil { - // invalid protocol reported by the registry. Move along. - log.Printf("[WARN] invalid provider protocol version %q found in the registry", versionMeta.Version) - continue - } - // success! - if protocolConstraint.Allows(proPro) { - return nil - } - } - - return ErrorNoVersionCompatible -} - -// REVIEWER QUESTION (again): this ends up swallowing a bunch of errors from -// checkPluginProtocol. Do they need to be percolated up better, or would -// debug messages would suffice in these situations? -func (i *ProviderInstaller) findPlatformCompatibleVersion(versions []*response.TerraformProviderVersion) (*response.TerraformProviderVersion, error) { - for _, version := range versions { - if err := i.checkPlatformCompatibility(version); err == nil { - return version, nil - } - } - - return nil, ErrorNoVersionCompatibleWithPlatform -} - -// platformCompatibleVersions returns a list of provider versions that are -// compatible with the requested platform. -func (i *ProviderInstaller) platformCompatibleVersions(versions []*response.TerraformProviderVersion) []*response.TerraformProviderVersion { - var v []*response.TerraformProviderVersion - for _, version := range versions { - if err := i.checkPlatformCompatibility(version); err == nil { - v = append(v, version) - } - } - return v -} - -func (i *ProviderInstaller) checkPlatformCompatibility(versionMeta *response.TerraformProviderVersion) error { - if len(versionMeta.Platforms) == 0 { - return fmt.Errorf("no supported provider platforms listed") - } - for _, p := range versionMeta.Platforms { - if p.Arch == i.Arch && p.OS == i.OS { - return nil - } - } - return fmt.Errorf("version %s does not support the requested platform %s_%s", versionMeta.Version, i.OS, i.Arch) -} - -// take the list of available versions for a plugin, and filter out those that -// don't fit the constraints. -func allowedVersions(available *response.TerraformProviderVersions, required Constraints) []*response.TerraformProviderVersion { - var allowed []*response.TerraformProviderVersion - - for _, v := range available.Versions { - version, err := VersionStr(v.Version).Parse() - if err != nil { - log.Printf("[WARN] invalid version found for %q: %s", available.ID, err) - continue - } - if required.Allows(version) { - allowed = append(allowed, v) - } - } - return allowed -} - -func checksumForFile(sums []byte, name string) string { - for _, line := range strings.Split(string(sums), "\n") { - parts := strings.Fields(line) - if len(parts) > 1 && parts[1] == name { - return parts[0] - } - } - return "" -} - -func getFile(url string) ([]byte, error) { - resp, err := httpClient.Get(url) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("%s", resp.Status) - } - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return data, err - } - return data, nil -} - -// providerProtocolTooOld is a message sent to the CLI UI if the provider's -// supported protocol versions are too old for the user's version of terraform, -// but an older version of the provider is compatible. -const providerProtocolTooOld = ` -[reset][bold][red]Provider %q v%s is not compatible with Terraform %s.[reset][red] - -Provider version %s is the earliest compatible version. Select it with -the following version constraint: - - version = %q - -Terraform checked all of the plugin versions matching the given constraint: - %s - -Consult the documentation for this provider for more information on -compatibility between provider and Terraform versions. -` - -// providerProtocolTooNew is a message sent to the CLI UI if the provider's -// supported protocol versions are too new for the user's version of terraform, -// and the user could either upgrade terraform or choose an older version of the -// provider -const providerProtocolTooNew = ` -[reset][bold][red]Provider %q v%s is not compatible with Terraform %s.[reset][red] - -Provider version %s is the latest compatible version. Select it with -the following constraint: - - version = %q - -Terraform checked all of the plugin versions matching the given constraint: - %s - -Consult the documentation for this provider for more information on -compatibility between provider and Terraform versions. - -Alternatively, upgrade to the latest version of Terraform for compatibility with newer provider releases. -` diff --git a/plugin/discovery/get_test.go b/plugin/discovery/get_test.go deleted file mode 100644 index 231551d63..000000000 --- a/plugin/discovery/get_test.go +++ /dev/null @@ -1,778 +0,0 @@ -package discovery - -import ( - "archive/zip" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "net/http/httptest" - "os" - "path/filepath" - "reflect" - "runtime" - "strings" - "testing" - - svchost "github.com/hashicorp/terraform-svchost" - "github.com/hashicorp/terraform-svchost/disco" - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/httpclient" - "github.com/hashicorp/terraform/registry" - "github.com/hashicorp/terraform/registry/response" - "github.com/hashicorp/terraform/version" - "github.com/mitchellh/cli" -) - -const testProviderFile = "test provider binary" - -func TestMain(m *testing.M) { - server := testReleaseServer() - l, err := net.Listen("tcp", "127.0.0.1:8080") - if err != nil { - log.Fatal(err) - } - - // NewUnstartedServer creates a listener. Close that listener and replace - // with the one we created. - server.Listener.Close() - server.Listener = l - server.Start() - defer server.Close() - - os.Exit(m.Run()) -} - -// return the directory listing for the "test" provider -func testListingHandler(w http.ResponseWriter, r *http.Request) { - parts := strings.Split(r.URL.Path, "/") - if len(parts) != 6 { - http.Error(w, "not found", http.StatusNotFound) - return - } - provider := parts[4] - if provider == "test" { - js, err := json.Marshal(versionList) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Write(js) - } - http.Error(w, ErrorNoSuchProvider.Error(), http.StatusNotFound) - return - -} - -// return the download URLs for the "test" provider -func testDownloadHandler(w http.ResponseWriter, r *http.Request) { - js, err := json.Marshal(downloadURLs) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Write(js) -} - -func testChecksumHandler(w http.ResponseWriter, r *http.Request) { - // this exact plugin has a signature and checksum file - if r.URL.Path == "/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS" { - http.ServeFile(w, r, "testdata/terraform-provider-template_0.1.0_SHA256SUMS") - return - } - if r.URL.Path == "/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig" { - http.ServeFile(w, r, "testdata/terraform-provider-template_0.1.0_SHA256SUMS.sig") - return - } - - // this this checksum file is corrupt and doesn't match the sig - if r.URL.Path == "/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS" { - http.ServeFile(w, r, "testdata/terraform-provider-badsig_0.1.0_SHA256SUMS") - return - } - if r.URL.Path == "/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS.sig" { - http.ServeFile(w, r, "testdata/terraform-provider-badsig_0.1.0_SHA256SUMS.sig") - return - } - - http.Error(w, "signtaure files not found", http.StatusNotFound) -} - -// returns a 200 for a valid provider url, using the patch number for the -// plugin protocol version. -func testHandler(w http.ResponseWriter, r *http.Request) { - if strings.HasSuffix(r.URL.Path, "/versions") { - testListingHandler(w, r) - return - } - - if strings.Contains(r.URL.Path, "/download") { - testDownloadHandler(w, r) - return - } - - parts := strings.Split(r.URL.Path, "/") - if len(parts) != 7 { - http.Error(w, "not found", http.StatusNotFound) - return - } - - // write a dummy file - z := zip.NewWriter(w) - fn := fmt.Sprintf("%s_v%s", parts[4], parts[5]) - f, err := z.Create(fn) - if err != nil { - panic(err) - } - io.WriteString(f, testProviderFile) - z.Close() -} - -func testReleaseServer() *httptest.Server { - handler := http.NewServeMux() - handler.HandleFunc("/v1/providers/-/", testHandler) - handler.HandleFunc("/v1/providers/terraform-providers/", testHandler) - handler.HandleFunc("/terraform-provider-template/", testChecksumHandler) - handler.HandleFunc("/terraform-provider-badsig/", testChecksumHandler) - handler.HandleFunc("/.well-known/terraform.json", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - io.WriteString(w, `{"modules.v1":"http://localhost/v1/modules/", "providers.v1":"http://localhost/v1/providers/"}`) - }) - - return httptest.NewUnstartedServer(handler) -} - -func TestVersionListing(t *testing.T) { - server := testReleaseServer() - server.Start() - defer server.Close() - - i := newProviderInstaller(server) - - allVersions, err := i.listProviderVersions(addrs.Provider{Type: "test"}) - - if err != nil { - t.Fatal(err) - } - - var versions []*response.TerraformProviderVersion - - for _, v := range allVersions.Versions { - versions = append(versions, v) - } - - response.ProviderVersionCollection(versions).Sort() - - expected := []*response.TerraformProviderVersion{ - {Version: "1.2.4"}, - {Version: "1.2.3"}, - {Version: "1.2.1"}, - } - - if len(versions) != len(expected) { - t.Fatalf("Received wrong number of versions. expected: %#v, got: %#v", expected, versions) - } - - for i, v := range versions { - if v.Version != expected[i].Version { - t.Fatalf("incorrect version: %#v, expected %#v", v, expected[i]) - } - } -} - -func TestCheckProtocolVersions(t *testing.T) { - tests := []struct { - VersionMeta *response.TerraformProviderVersion - Err bool - }{ - { - &response.TerraformProviderVersion{ - Protocols: []string{"1", "2"}, - }, - true, - }, - { - &response.TerraformProviderVersion{ - Protocols: []string{"4"}, - }, - false, - }, - { - &response.TerraformProviderVersion{ - Protocols: []string{"4.2"}, - }, - false, - }, - { - &response.TerraformProviderVersion{ - Protocols: []string{"4.0", "5.2"}, - }, - false, - }, - { - &response.TerraformProviderVersion{ - Protocols: []string{"5.0", "6.1"}, - }, - true, - }, - } - - server := testReleaseServer() - server.Start() - defer server.Close() - i := newProviderInstaller(server) - - for _, test := range tests { - err := i.checkPluginProtocol(test.VersionMeta) - if test.Err { - if err == nil { - t.Fatal("succeeded; want error") - } - } else if err != nil { - t.Fatalf("unexpected error: %s", err) - } - } -} - -func TestFindClosestProtocolCompatibleVersion(t *testing.T) { - testCases := []struct { - Name string - PluginProtocolVersion uint - ProviderVersions []*response.TerraformProviderVersion - ExpectedVersion string - Err bool - }{ - { - "no compatible version", - 5, - []*response.TerraformProviderVersion{ - &response.TerraformProviderVersion{ - Version: "1.0.0", - Protocols: []string{"4.0"}, - }, - }, - "", - true, - }, { - "equal, suggests latest", - 4, - []*response.TerraformProviderVersion{ - &response.TerraformProviderVersion{ - Version: "1.0.0", - Protocols: []string{"4.0"}, - }, - &response.TerraformProviderVersion{ - Version: "1.5.0", - Protocols: []string{"4.0"}, - }, - }, - "1.5.0", - false, - }, { - "provider protocol too old, suggests earliest", - 5, - []*response.TerraformProviderVersion{ - &response.TerraformProviderVersion{ - Version: "1.0.0", - Protocols: []string{"4.0"}, - }, - &response.TerraformProviderVersion{ - Version: "2.0.0", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "2.5.0", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "3.0.0", - Protocols: []string{"5.0"}, - }, - }, - "2.0.0", - false, - }, { - "provider protocol too new, suggests latest", - 4, - []*response.TerraformProviderVersion{ - &response.TerraformProviderVersion{ - Version: "1.0.0", - Protocols: []string{"4.0"}, - }, - &response.TerraformProviderVersion{ - Version: "2.0.0", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "2.5.0", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "3.0.0", - Protocols: []string{"5.0"}, - }, - }, - "2.5.0", - false, - }, { - "compatible prereleses are filtered", - 5, - []*response.TerraformProviderVersion{ - &response.TerraformProviderVersion{ - Version: "2.0.0-alpha", - Protocols: []string{"4.0", "5.0"}, - }, - }, - "", - true, - }, { - "suggests latest non-prerelease", - 4, - []*response.TerraformProviderVersion{ - &response.TerraformProviderVersion{ - Version: "2.0.0-alpha", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "2.0.0", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "2.5.0-pre", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "2.5.0", - Protocols: []string{"4.0", "5.0"}, - }, - }, - "2.5.0", - false, - }, { - "suggests earliest non-prerelease", - 5, - []*response.TerraformProviderVersion{ - &response.TerraformProviderVersion{ - Version: "2.0.0-alpha", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "2.0.0", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "2.6.0", - Protocols: []string{"4.0", "5.0"}, - }, - &response.TerraformProviderVersion{ - Version: "3.0.0", - Protocols: []string{"5.0"}, - }, - }, - "2.0.0", - false, - }, - } - - for _, tc := range testCases { - t.Run(tc.Name, func(t *testing.T) { - i := ProviderInstaller{ - Ui: cli.NewMockUi(), - PluginProtocolVersion: tc.PluginProtocolVersion, - } - - closestMatch, err := i.findClosestProtocolCompatibleVersion(tc.ProviderVersions) - if err != nil { - if !tc.Err { - t.Fatalf("unexpected error: %q", err) - } - return - } - if tc.ExpectedVersion != closestMatch.Version { - t.Errorf("Expected %q, got %q", tc.ExpectedVersion, closestMatch.Version) - } - }) - } -} - -func TestProviderInstallerGet(t *testing.T) { - server := testReleaseServer() - server.Start() - defer server.Close() - - tmpDir, err := ioutil.TempDir("", "tf-plugin") - if err != nil { - t.Fatal(err) - } - - defer os.RemoveAll(tmpDir) - - // attempt to use an incompatible protocol version - i := &ProviderInstaller{ - Dir: tmpDir, - PluginProtocolVersion: 5, - SkipVerify: true, - Ui: cli.NewMockUi(), - registry: registry.NewClient(Disco(server), nil), - } - - _, _, err = i.Get(addrs.NewLegacyProvider("test"), AllVersions) - - if err != ErrorNoVersionCompatibleWithPlatform { - t.Fatal("want error for incompatible version") - } - - i = &ProviderInstaller{ - Dir: tmpDir, - PluginProtocolVersion: 4, - SkipVerify: true, - Ui: cli.NewMockUi(), - registry: registry.NewClient(Disco(server), nil), - OS: "mockos", - Arch: "mockarch", - } - - { - _, _, err := i.Get(addrs.NewLegacyProvider("test"), ConstraintStr(">9.0.0").MustParse()) - if err != ErrorNoSuitableVersion { - t.Fatal("want error for mismatching constraints") - } - } - - { - provider := addrs.NewLegacyProvider("nonexist") - _, _, err := i.Get(provider, AllVersions) - if err != ErrorNoSuchProvider { - t.Fatal("want error for no such provider") - } - } - - gotMeta, _, err := i.Get(addrs.NewLegacyProvider("test"), AllVersions) - if err != nil { - t.Fatal(err) - } - - // we should have version 1.2.4 - dest := filepath.Join(tmpDir, "terraform-provider-test_v1.2.4") - - wantMeta := PluginMeta{ - Name: "test", - Version: VersionStr("1.2.4"), - Path: dest, - } - if !reflect.DeepEqual(gotMeta, wantMeta) { - t.Errorf("wrong result meta\ngot: %#v\nwant: %#v", gotMeta, wantMeta) - } - - f, err := ioutil.ReadFile(dest) - if err != nil { - t.Fatal(err) - } - - // provider should have been unzipped - if string(f) != testProviderFile { - t.Fatalf("test provider contains: %q", f) - } - -} - -// test that the provider installer can install plugins from a plugin cache dir -// into a target directory that does not exist. -// https://github.com/hashicorp/terraform/issues/20532 -func TestProviderInstallerGet_cache(t *testing.T) { - server := testReleaseServer() - server.Start() - defer server.Close() - - tmpDir, err := ioutil.TempDir("", "tf-plugin") - if err != nil { - t.Fatal(err) - } - - cache := NewLocalPluginCache(filepath.Join(tmpDir, "cache")) - targetDir := filepath.Join(tmpDir, "non-existant-dir") - - defer os.RemoveAll(tmpDir) - - i := &ProviderInstaller{ - Dir: targetDir, - Cache: cache, - PluginProtocolVersion: 4, - SkipVerify: true, - Ui: cli.NewMockUi(), - registry: registry.NewClient(Disco(server), nil), - OS: "mockos", - Arch: "mockarch", - } - - gotMeta, _, err := i.Get(addrs.NewLegacyProvider("test"), AllVersions) - if err != nil { - t.Fatal(err) - } - - // we should have version 1.2.4 - dest := filepath.Join(targetDir, "terraform-provider-test_v1.2.4") - - wantMeta := PluginMeta{ - Name: "test", - Version: VersionStr("1.2.4"), - Path: dest, - } - if !reflect.DeepEqual(gotMeta, wantMeta) { - t.Errorf("wrong result meta\ngot: %#v\nwant: %#v", gotMeta, wantMeta) - } - - f, err := ioutil.ReadFile(dest) - if err != nil { - t.Fatal(err) - } - - // provider should have been unzipped - if string(f) != testProviderFile { - t.Fatalf("test provider contains: %q", f) - } -} - -func TestProviderInstallerPurgeUnused(t *testing.T) { - server := testReleaseServer() - defer server.Close() - - tmpDir, err := ioutil.TempDir("", "tf-plugin") - if err != nil { - t.Fatal(err) - } - - defer os.RemoveAll(tmpDir) - - unwantedPath := filepath.Join(tmpDir, "terraform-provider-test_v0.0.1_x2") - wantedPath := filepath.Join(tmpDir, "terraform-provider-test_v1.2.3_x3") - - f, err := os.Create(unwantedPath) - if err != nil { - t.Fatal(err) - } - f.Close() - f, err = os.Create(wantedPath) - if err != nil { - t.Fatal(err) - } - f.Close() - - i := &ProviderInstaller{ - Dir: tmpDir, - PluginProtocolVersion: 3, - SkipVerify: true, - Ui: cli.NewMockUi(), - registry: registry.NewClient(Disco(server), nil), - } - purged, err := i.PurgeUnused(map[string]PluginMeta{ - "test": PluginMeta{ - Name: "test", - Version: VersionStr("1.2.3"), - Path: wantedPath, - }, - }) - if err != nil { - t.Fatal(err) - } - - if got, want := purged.Count(), 1; got != want { - t.Errorf("wrong purged count %d; want %d", got, want) - } - if got, want := purged.Newest().Path, unwantedPath; got != want { - t.Errorf("wrong purged path %s; want %s", got, want) - } - - files, err := ioutil.ReadDir(tmpDir) - if err != nil { - t.Fatal(err) - } - - gotFilenames := make([]string, len(files)) - for i, info := range files { - gotFilenames[i] = info.Name() - } - wantFilenames := []string{"terraform-provider-test_v1.2.3_x3"} - - if !reflect.DeepEqual(gotFilenames, wantFilenames) { - t.Errorf("wrong filenames after purge\ngot: %#v\nwant: %#v", gotFilenames, wantFilenames) - } -} - -// Test fetching a provider's checksum file while verifying its signature. -func TestProviderChecksum(t *testing.T) { - hashicorpKey, err := ioutil.ReadFile("testdata/hashicorp.asc") - if err != nil { - t.Fatal(err) - } - - tests := []struct { - Name string - Resp *response.TerraformProviderPlatformLocation - Err bool - }{ - { - "good", - &response.TerraformProviderPlatformLocation{ - Filename: "terraform-provider-template_0.1.0_darwin_amd64.zip", - Shasum: "3c3e7df78b1f0161a3f941c271d5501f7b5e5f2c53738e7a371459712f5d4726", - ShasumsURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS", - ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig", - SigningKeys: response.SigningKeyList{ - GPGKeys: []*response.GPGKey{ - &response.GPGKey{ - ASCIIArmor: string(hashicorpKey), - }, - }, - }, - }, - false, - }, - { - "bad", - &response.TerraformProviderPlatformLocation{ - Filename: "terraform-provider-template_0.1.0_darwin_amd64.zip", - ShasumsURL: "http://127.0.0.1:8080/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS", - ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS.sig", - SigningKeys: response.SigningKeyList{ - GPGKeys: []*response.GPGKey{ - &response.GPGKey{ - ASCIIArmor: string(hashicorpKey), - }, - }, - }, - }, - true, - }, - { - "no keys", - &response.TerraformProviderPlatformLocation{ - Filename: "terraform-provider-template_0.1.0_darwin_amd64.zip", - ShasumsURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS", - ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig", - SigningKeys: response.SigningKeyList{ - GPGKeys: []*response.GPGKey{}, - }, - }, - true, - }, - { - "mismatch checksum", - &response.TerraformProviderPlatformLocation{ - Filename: "terraform-provider-template_0.1.0_darwin_amd64.zip", - Shasum: "force mismatch", - ShasumsURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS", - ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig", - SigningKeys: response.SigningKeyList{ - GPGKeys: []*response.GPGKey{ - &response.GPGKey{ - ASCIIArmor: string(hashicorpKey), - }, - }, - }, - }, - true, - }, - { - "missing checksum for file", - &response.TerraformProviderPlatformLocation{ - Filename: "terraform-provider-template_0.1.0_darwin_amd64_missing_checksum.zip", - Shasum: "checksum", - ShasumsURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS", - ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig", - SigningKeys: response.SigningKeyList{ - GPGKeys: []*response.GPGKey{ - &response.GPGKey{ - ASCIIArmor: string(hashicorpKey), - }, - }, - }, - }, - true, - }, - } - - i := ProviderInstaller{} - - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - sha256sum, err := i.getProviderChecksum(test.Resp) - if test.Err { - if err == nil { - t.Fatal("succeeded; want error") - } - return - } else if err != nil { - t.Fatalf("unexpected error: %s", err) - } - - // get the expected checksum for our os/arch - sumData, err := ioutil.ReadFile("testdata/terraform-provider-template_0.1.0_SHA256SUMS") - if err != nil { - t.Fatal(err) - } - - expected := checksumForFile(sumData, test.Resp.Filename) - - if sha256sum != expected { - t.Fatalf("expected: %s\ngot %s\n", sha256sum, expected) - } - }) - } -} - -// newProviderInstaller returns a minimally-initialized ProviderInstaller -func newProviderInstaller(s *httptest.Server) ProviderInstaller { - return ProviderInstaller{ - registry: registry.NewClient(Disco(s), nil), - OS: runtime.GOOS, - Arch: runtime.GOARCH, - PluginProtocolVersion: 4, - } -} - -// Disco return a *disco.Disco mapping registry.terraform.io, localhost, -// localhost.localdomain, and example.com to the test server. -func Disco(s *httptest.Server) *disco.Disco { - services := map[string]interface{}{ - // Note that both with and without trailing slashes are supported behaviours - "modules.v1": fmt.Sprintf("%s/v1/modules", s.URL), - "providers.v1": fmt.Sprintf("%s/v1/providers", s.URL), - } - d := disco.New() - d.SetUserAgent(httpclient.TerraformUserAgent(version.String())) - - d.ForceHostServices(svchost.Hostname("registry.terraform.io"), services) - d.ForceHostServices(svchost.Hostname("localhost"), services) - d.ForceHostServices(svchost.Hostname("localhost.localdomain"), services) - d.ForceHostServices(svchost.Hostname("example.com"), services) - return d -} - -var versionList = response.TerraformProvider{ - ID: "terraform-providers/test", - Versions: []*response.TerraformProviderVersion{ - {Version: "1.2.1"}, - {Version: "1.2.3"}, - { - Version: "1.2.4", - Protocols: []string{"4"}, - Platforms: []*response.TerraformProviderPlatform{ - { - OS: "mockos", - Arch: "mockarch", - }, - }, - }, - }, -} - -var downloadURLs = response.TerraformProviderPlatformLocation{ - ShasumsURL: "https://registry.terraform.io/terraform-provider-template/1.2.4/terraform-provider-test_1.2.4_SHA256SUMS", - ShasumsSignatureURL: "https://registry.terraform.io/terraform-provider-template/1.2.4/terraform-provider-test_1.2.4_SHA256SUMS.sig", - Filename: "terraform-provider-template_1.2.4_darwin_amd64.zip", - DownloadURL: "http://127.0.0.1:8080/v1/providers/terraform-providers/terraform-provider-test/1.2.4/terraform-provider-test_1.2.4_darwin_amd64.zip", -} diff --git a/plugin/discovery/hashicorp.go b/plugin/discovery/hashicorp.go deleted file mode 100644 index 4622ca054..000000000 --- a/plugin/discovery/hashicorp.go +++ /dev/null @@ -1,34 +0,0 @@ -package discovery - -// HashicorpPublicKey is the HashiCorp public key, also available at -// https://www.hashicorp.com/security -const HashicorpPublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1 - -mQENBFMORM0BCADBRyKO1MhCirazOSVwcfTr1xUxjPvfxD3hjUwHtjsOy/bT6p9f -W2mRPfwnq2JB5As+paL3UGDsSRDnK9KAxQb0NNF4+eVhr/EJ18s3wwXXDMjpIifq -fIm2WyH3G+aRLTLPIpscUNKDyxFOUbsmgXAmJ46Re1fn8uKxKRHbfa39aeuEYWFA -3drdL1WoUngvED7f+RnKBK2G6ZEpO+LDovQk19xGjiMTtPJrjMjZJ3QXqPvx5wca -KSZLr4lMTuoTI/ZXyZy5bD4tShiZz6KcyX27cD70q2iRcEZ0poLKHyEIDAi3TM5k -SwbbWBFd5RNPOR0qzrb/0p9ksKK48IIfH2FvABEBAAG0K0hhc2hpQ29ycCBTZWN1 -cml0eSA8c2VjdXJpdHlAaGFzaGljb3JwLmNvbT6JATgEEwECACIFAlMORM0CGwMG -CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEFGFLYc0j/xMyWIIAIPhcVqiQ59n -Jc07gjUX0SWBJAxEG1lKxfzS4Xp+57h2xxTpdotGQ1fZwsihaIqow337YHQI3q0i -SqV534Ms+j/tU7X8sq11xFJIeEVG8PASRCwmryUwghFKPlHETQ8jJ+Y8+1asRydi -psP3B/5Mjhqv/uOK+Vy3zAyIpyDOMtIpOVfjSpCplVRdtSTFWBu9Em7j5I2HMn1w -sJZnJgXKpybpibGiiTtmnFLOwibmprSu04rsnP4ncdC2XRD4wIjoyA+4PKgX3sCO -klEzKryWYBmLkJOMDdo52LttP3279s7XrkLEE7ia0fXa2c12EQ0f0DQ1tGUvyVEW -WmJVccm5bq25AQ0EUw5EzQEIANaPUY04/g7AmYkOMjaCZ6iTp9hB5Rsj/4ee/ln9 -wArzRO9+3eejLWh53FoN1rO+su7tiXJA5YAzVy6tuolrqjM8DBztPxdLBbEi4V+j -2tK0dATdBQBHEh3OJApO2UBtcjaZBT31zrG9K55D+CrcgIVEHAKY8Cb4kLBkb5wM -skn+DrASKU0BNIV1qRsxfiUdQHZfSqtp004nrql1lbFMLFEuiY8FZrkkQ9qduixo -mTT6f34/oiY+Jam3zCK7RDN/OjuWheIPGj/Qbx9JuNiwgX6yRj7OE1tjUx6d8g9y -0H1fmLJbb3WZZbuuGFnK6qrE3bGeY8+AWaJAZ37wpWh1p0cAEQEAAYkBHwQYAQIA -CQUCUw5EzQIbDAAKCRBRhS2HNI/8TJntCAClU7TOO/X053eKF1jqNW4A1qpxctVc -z8eTcY8Om5O4f6a/rfxfNFKn9Qyja/OG1xWNobETy7MiMXYjaa8uUx5iFy6kMVaP -0BXJ59NLZjMARGw6lVTYDTIvzqqqwLxgliSDfSnqUhubGwvykANPO+93BBx89MRG -unNoYGXtPlhNFrAsB1VR8+EyKLv2HQtGCPSFBhrjuzH3gxGibNDDdFQLxxuJWepJ -EK1UbTS4ms0NgZ2Uknqn1WRU1Ki7rE4sTy68iZtWpKQXZEJa0IGnuI2sSINGcXCJ -oEIgXTMyCILo34Fa/C6VCm2WBgz9zZO8/rHIiQm1J5zqz0DrDwKBUM9C -=LYpS ------END PGP PUBLIC KEY BLOCK-----` diff --git a/plugin/discovery/signature.go b/plugin/discovery/signature.go deleted file mode 100644 index 7bbae50c3..000000000 --- a/plugin/discovery/signature.go +++ /dev/null @@ -1,19 +0,0 @@ -package discovery - -import ( - "bytes" - "strings" - - "golang.org/x/crypto/openpgp" -) - -// Verify the data using the provided openpgp detached signature and the -// embedded hashicorp public key. -func verifySig(data, sig []byte, armor string) (*openpgp.Entity, error) { - el, err := openpgp.ReadArmoredKeyRing(strings.NewReader(armor)) - if err != nil { - return nil, err - } - - return openpgp.CheckDetachedSignature(el, bytes.NewReader(data), bytes.NewReader(sig)) -} diff --git a/plugin/discovery/testdata/hashicorp.asc b/plugin/discovery/testdata/hashicorp.asc deleted file mode 100644 index 010c9271c..000000000 --- a/plugin/discovery/testdata/hashicorp.asc +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1 - -mQENBFMORM0BCADBRyKO1MhCirazOSVwcfTr1xUxjPvfxD3hjUwHtjsOy/bT6p9f -W2mRPfwnq2JB5As+paL3UGDsSRDnK9KAxQb0NNF4+eVhr/EJ18s3wwXXDMjpIifq -fIm2WyH3G+aRLTLPIpscUNKDyxFOUbsmgXAmJ46Re1fn8uKxKRHbfa39aeuEYWFA -3drdL1WoUngvED7f+RnKBK2G6ZEpO+LDovQk19xGjiMTtPJrjMjZJ3QXqPvx5wca -KSZLr4lMTuoTI/ZXyZy5bD4tShiZz6KcyX27cD70q2iRcEZ0poLKHyEIDAi3TM5k -SwbbWBFd5RNPOR0qzrb/0p9ksKK48IIfH2FvABEBAAG0K0hhc2hpQ29ycCBTZWN1 -cml0eSA8c2VjdXJpdHlAaGFzaGljb3JwLmNvbT6JATgEEwECACIFAlMORM0CGwMG -CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEFGFLYc0j/xMyWIIAIPhcVqiQ59n -Jc07gjUX0SWBJAxEG1lKxfzS4Xp+57h2xxTpdotGQ1fZwsihaIqow337YHQI3q0i -SqV534Ms+j/tU7X8sq11xFJIeEVG8PASRCwmryUwghFKPlHETQ8jJ+Y8+1asRydi -psP3B/5Mjhqv/uOK+Vy3zAyIpyDOMtIpOVfjSpCplVRdtSTFWBu9Em7j5I2HMn1w -sJZnJgXKpybpibGiiTtmnFLOwibmprSu04rsnP4ncdC2XRD4wIjoyA+4PKgX3sCO -klEzKryWYBmLkJOMDdo52LttP3279s7XrkLEE7ia0fXa2c12EQ0f0DQ1tGUvyVEW -WmJVccm5bq25AQ0EUw5EzQEIANaPUY04/g7AmYkOMjaCZ6iTp9hB5Rsj/4ee/ln9 -wArzRO9+3eejLWh53FoN1rO+su7tiXJA5YAzVy6tuolrqjM8DBztPxdLBbEi4V+j -2tK0dATdBQBHEh3OJApO2UBtcjaZBT31zrG9K55D+CrcgIVEHAKY8Cb4kLBkb5wM -skn+DrASKU0BNIV1qRsxfiUdQHZfSqtp004nrql1lbFMLFEuiY8FZrkkQ9qduixo -mTT6f34/oiY+Jam3zCK7RDN/OjuWheIPGj/Qbx9JuNiwgX6yRj7OE1tjUx6d8g9y -0H1fmLJbb3WZZbuuGFnK6qrE3bGeY8+AWaJAZ37wpWh1p0cAEQEAAYkBHwQYAQIA -CQUCUw5EzQIbDAAKCRBRhS2HNI/8TJntCAClU7TOO/X053eKF1jqNW4A1qpxctVc -z8eTcY8Om5O4f6a/rfxfNFKn9Qyja/OG1xWNobETy7MiMXYjaa8uUx5iFy6kMVaP -0BXJ59NLZjMARGw6lVTYDTIvzqqqwLxgliSDfSnqUhubGwvykANPO+93BBx89MRG -unNoYGXtPlhNFrAsB1VR8+EyKLv2HQtGCPSFBhrjuzH3gxGibNDDdFQLxxuJWepJ -EK1UbTS4ms0NgZ2Uknqn1WRU1Ki7rE4sTy68iZtWpKQXZEJa0IGnuI2sSINGcXCJ -oEIgXTMyCILo34Fa/C6VCm2WBgz9zZO8/rHIiQm1J5zqz0DrDwKBUM9C -=LYpS ------END PGP PUBLIC KEY BLOCK----- diff --git a/plugin/discovery/testdata/terraform-provider-badsig_0.1.0_SHA256SUMS b/plugin/discovery/testdata/terraform-provider-badsig_0.1.0_SHA256SUMS deleted file mode 100644 index bc9806023..000000000 --- a/plugin/discovery/testdata/terraform-provider-badsig_0.1.0_SHA256SUMS +++ /dev/null @@ -1,12 +0,0 @@ -XX3X7df78b1f0161a3f941c271d55X1f7b5e5f2c53738e7a37145XX12f5d4726 terraform-provider-template_0.1.0_darwin_amd64.zip -XXXXfe878e2dXb2ed0a7da1d0eb6X6Xe4703d3df93ebf22bc12aXf5X1bb38b7c terraform-provider-template_0.1.0_freebsd_386.zip -XXXX9268ebfX8Xb63e53b2a476cX21aXf18c52e303673e2219eXc0dcXcc25622 terraform-provider-template_0.1.0_freebsd_amd64.zip -XXXX0c5ef0X43X47ecf93c313aXd58b3X8b8df8a10d2fb5dbeX3f7ac2X81cee7 terraform-provider-template_0.1.0_freebsd_arm.zip -XXXfXXa6dX5ddbX6903c8733cX4b69893X4f088ceb96560c7Xc876df49Xce2f4 terraform-provider-template_0.1.0_linux_386.zip -XXX8bXX1Xe2e077X88a68e4aX271c49e2dX22b149f440ff7X362581ec11Xe380 terraform-provider-template_0.1.0_linux_amd64.zip -XXX0969XXb34e8fcXXf7653Xd8bb42654cbX49c1d3902d8X729d3b1792daX9fe terraform-provider-template_0.1.0_linux_arm.zip -XXX8eca7X33808ec5eX027X83c42824ac9c0Xf5a458299Xc9ae86f4a04d76X4b terraform-provider-template_0.1.0_openbsd_386.zip -XXX18466c1590fc3cceXeXd619b29d6ea4ec1X3aab976X9dc64d1f5652d5c4Xf terraform-provider-template_0.1.0_openbsd_amd64.zip -XXXe603de6fd57310175X842002c0cc53472c4Xf1cf5X8d306884009fd80d22X terraform-provider-template_0.1.0_solaris_amd64.zip -XXX7a87ae47c383991f31774be8dfb70b7786cfXf22X497fe2d8b48dfcfe5ca1 terraform-provider-template_0.1.0_windows_386.zip -XXf12267bf26a5754f740e28f445cf015e66f59aXXX681564ac45888ebd83ff0 terraform-provider-template_0.1.0_windows_amd64.zip diff --git a/plugin/discovery/testdata/terraform-provider-badsig_0.1.0_SHA256SUMS.sig b/plugin/discovery/testdata/terraform-provider-badsig_0.1.0_SHA256SUMS.sig deleted file mode 100644 index 30c9937caa31f28c075cf1eccf4b04f7af6ee61e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmV+)0pR|L0UQJX0RjL91p-+=;++5r2@p|*Er&FZ{7lQ@2mf96N;HM24A2ay#SxIR znT*xsWu>Lf>IAb-{-ygZLP!kRO))r1n2RL0dEpRFWz?# l>7L0X;fF|n^4mg(*Oj73h(dYfdsr+P1gDRxi_}k=(YAS%jdB10 diff --git a/plugin/discovery/testdata/terraform-provider-template_0.1.0_SHA256SUMS b/plugin/discovery/testdata/terraform-provider-template_0.1.0_SHA256SUMS deleted file mode 100644 index d5da59eb6..000000000 --- a/plugin/discovery/testdata/terraform-provider-template_0.1.0_SHA256SUMS +++ /dev/null @@ -1,12 +0,0 @@ -3c3e7df78b1f0161a3f941c271d5501f7b5e5f2c53738e7a371459712f5d4726 terraform-provider-template_0.1.0_darwin_amd64.zip -83fefe878e2dfb2ed0a7da1d0eb6e62e4703d3df93ebf22bc12a5f571bb38b7c terraform-provider-template_0.1.0_freebsd_386.zip -a19c9268ebf089b63e53b2a476cf21a4f18c52e303673e2219edc0dc8cc25622 terraform-provider-template_0.1.0_freebsd_amd64.zip -158b0c5ef0f43d47ecf93c313a6d58b398b8df8a10d2fb5dbed3f7ac2b81cee7 terraform-provider-template_0.1.0_freebsd_arm.zip -27ef86a6d15ddb46903c8733c84b69893e4f088ceb96560c76c876df49bce2f4 terraform-provider-template_0.1.0_linux_386.zip -7018b681ee2e077588a68e4a2271c49e2da22b149f440ff7a362581ec113e380 terraform-provider-template_0.1.0_linux_amd64.zip -c810969a5b34e8fc94f7653fd8bb42654cb449c1d3902d8f729d3b1792da99fe terraform-provider-template_0.1.0_linux_arm.zip -77b8eca7d33808ec5e1027d83c42824ac9c05f5a4582997c9ae86f4a04d7664b terraform-provider-template_0.1.0_openbsd_386.zip -d4d18466c1590fc3cce5efd619b29d6ea4ec113aab97639dc64d1f5652d5c4af terraform-provider-template_0.1.0_openbsd_amd64.zip -00be603de6fd573101757842002c0cc53472c44f1cf568d306884009fd80d224 terraform-provider-template_0.1.0_solaris_amd64.zip -2457a87ae47c383991f31774be8dfb70b7786cfef220497fe2d8b48dfcfe5ca1 terraform-provider-template_0.1.0_windows_386.zip -38f12267bf26a5754f740e28f445cf015e66f59a89b681564ac45888ebd83ff0 terraform-provider-template_0.1.0_windows_amd64.zip diff --git a/plugin/discovery/testdata/terraform-provider-template_0.1.0_SHA256SUMS.sig b/plugin/discovery/testdata/terraform-provider-template_0.1.0_SHA256SUMS.sig deleted file mode 100644 index 30c9937caa31f28c075cf1eccf4b04f7af6ee61e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmV+)0pR|L0UQJX0RjL91p-+=;++5r2@p|*Er&FZ{7lQ@2mf96N;HM24A2ay#SxIR znT*xsWu>Lf>IAb-{-ygZLP!kRO))r1n2RL0dEpRFWz?# l>7L0X;fF|n^4mg(*Oj73h(dYfdsr+P1gDRxi_}k=(YAS%jdB10