diff --git a/command/init.go b/command/init.go index 70cfabaee..6c5dd0a8e 100644 --- a/command/init.go +++ b/command/init.go @@ -532,6 +532,11 @@ func (c *InitCommand) getProviders(earlyConfig *earlyconfig.Config, state *state case err == discovery.ErrorNoVersionCompatible: // Generic version incompatible msg c.Ui.Error(fmt.Sprintf(errProviderIncompatible, provider, constraint)) + case err == discovery.ErrorSignatureVerification: + c.Ui.Error(fmt.Sprintf(errSignatureVerification, provider)) + case err == discovery.ErrorChecksumVerification, + err == discovery.ErrorMissingChecksumVerification: + c.Ui.Error(fmt.Sprintf(errChecksumVerification, provider)) default: c.Ui.Error(fmt.Sprintf(errProviderInstallError, provider, err.Error(), DefaultPluginVendorDir)) } @@ -928,7 +933,7 @@ const errProviderInstallError = ` Terraform analyses the configuration and state and automatically downloads plugins for the providers used. However, when attempting to download this -plugin an unexpected error occured. +plugin an unexpected error occurred. This may be caused if for some reason Terraform is unable to reach the plugin repository. The repository may be unreachable if access is blocked @@ -959,3 +964,18 @@ by -plugin-dir on the command line, or in the following directory if custom plugin directories are not set: %[2]s ` + +const errChecksumVerification = ` +[reset][bold][red]Error verifying checksum for provider %[1]q[reset][red] +The checksum for provider distribution from the Terraform Registry +did not match the source. This may mean that the distributed files +were changed after this version was released to the Registry. +` + +const errSignatureVerification = ` +[reset][bold][red]Error verifying GPG signature for provider %[1]q[reset][red] +Terraform was unable to verify the GPG signature of the downloaded provider +files using the keys downloaded from the Terraform Registry. This may mean that +the publisher of the provider removed the key it was signed with, or that the +distributed files were changed after this version was released. +` diff --git a/plugin/discovery/error.go b/plugin/discovery/error.go index 6ca8b60aa..c0b503067 100644 --- a/plugin/discovery/error.go +++ b/plugin/discovery/error.go @@ -35,6 +35,22 @@ const ErrorNoSuchProvider = Error("no provider exists with the given name") // 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") + func (err Error) Error() string { return string(err) } diff --git a/plugin/discovery/get.go b/plugin/discovery/get.go index 5e0520e44..cc8acee6c 100644 --- a/plugin/discovery/get.go +++ b/plugin/discovery/get.go @@ -30,18 +30,6 @@ import ( const protocolVersionHeader = "x-terraform-protocol-version" -const gpgVerificationError = `GPG signature verification error: -Terraform was unable to verify the GPG signature of the downloaded provider -files using the keys downloaded from the Terraform Registry. This may mean that -the publisher of the provider removed the key it was signed with, or that the -distributed files were changed after this version was released.` - -const checksumVerificationError = `Checksum verification error: -The checksum for provider distribution %q from the Terraform Registry -did not match the source (%s). -This may mean that the distributed files were changed after this version -was released.` - var httpClient *http.Client var errVersionNotFound = errors.New("version not found") @@ -411,13 +399,15 @@ func (i *ProviderInstaller) getProviderChecksum(resp *response.TerraformProvider // Get SHA256SUMS file. shasums, err := getFile(resp.ShasumsURL) if err != nil { - return "", fmt.Errorf("error fetching checksums: %s", err) + 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 { - return "", fmt.Errorf("error fetching checksums signature: %s", err) + log.Printf("[ERROR] error fetching checksums signature from %q: %s", resp.ShasumsSignatureURL, err) + return "", ErrorSignatureVerification } // Verify the GPG signature returned from the Registry. @@ -425,7 +415,7 @@ func (i *ProviderInstaller) getProviderChecksum(resp *response.TerraformProvider signer, err := verifySig(shasums, signature, asciiArmor) if err != nil { log.Printf("[ERROR] error verifying signature: %s", err) - return "", fmt.Errorf(gpgVerificationError) + return "", ErrorSignatureVerification } // Also verify the GPG signature against the HashiCorp public key. This is @@ -434,7 +424,7 @@ func (i *ProviderInstaller) getProviderChecksum(resp *response.TerraformProvider _, err = verifySig(shasums, signature, HashicorpPublicKey) if err != nil { log.Printf("[ERROR] error verifying signature against HashiCorp public key: %s", err) - return "", fmt.Errorf(gpgVerificationError) + return "", ErrorSignatureVerification } // Display identity for GPG key which succeeded verifying the signature. @@ -448,8 +438,12 @@ func (i *ProviderInstaller) getProviderChecksum(resp *response.TerraformProvider // Extract checksum for this os/arch platform binary and verify against Registry checksum := checksumForFile(shasums, resp.Filename) - if checksum == "" || checksum != resp.Shasum { - return "", fmt.Errorf(checksumVerificationError, resp.Filename, resp.ShasumsURL) + 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