Skip to content

Commit 5217fea

Browse files
committed
Modify language for reporting signing state
Be more explicit about the signing status of fetched plugins and provide documentation about the different signing options.
1 parent f82700b commit 5217fea

File tree

7 files changed

+67
-25
lines changed

7 files changed

+67
-25
lines changed

command/init.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,18 @@ func (c *InitCommand) getProviders(earlyConfig *earlyconfig.Config, state *state
519519

520520
c.Ui.Info(fmt.Sprintf("- Installed %s v%s (%s)%s", provider.ForDisplay(), version, authResult, warning))
521521
},
522+
ProvidersFetched: func(authResults map[addrs.Provider]*getproviders.PackageAuthenticationResult) {
523+
thirdPartySigned := false
524+
for _, authResult := range authResults {
525+
if authResult.ThirdPartySigned() {
526+
thirdPartySigned = true
527+
break
528+
}
529+
}
530+
if thirdPartySigned {
531+
c.Ui.Info(fmt.Sprintf("\nYou have initialized providers which are signed by third parties, you can read more about Terraform's signature verification: https://www.terraform.io/docs/signing.html"))
532+
}
533+
},
522534
}
523535

524536
mode := providercache.InstallNewProvidersOnly

internal/getproviders/package_authentication.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,29 @@ type PackageAuthenticationResult struct {
3737

3838
func (t *PackageAuthenticationResult) String() string {
3939
if t == nil {
40-
return "unauthenticated"
40+
return "unsigned"
4141
}
4242
return []string{
4343
"verified checksum",
44-
"official provider",
45-
"partner provider",
46-
"community provider",
44+
"signed by HashiCorp",
45+
"signed by trusted partner",
46+
"self-signed",
4747
}[t.result]
4848
}
4949

50+
// ThirdPartySigned returns whether the package was authenticated as signed by a party
51+
// other than HashiCorp.
52+
func (t *PackageAuthenticationResult) ThirdPartySigned() bool {
53+
if t == nil {
54+
return false
55+
}
56+
if t.result == partnerProvider || t.result == communityProvider {
57+
return true
58+
}
59+
60+
return false
61+
}
62+
5063
// SigningKey represents a key used to sign packages from a registry, along
5164
// with an optional trust signature from the registry operator. These are
5265
// both in ASCII armored OpenPGP format.

internal/providercache/installer.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ NeedProvider:
260260

261261
// Step 3: For each provider version we've decided we need to install,
262262
// install its package into our target cache (possibly via the global cache).
263-
targetPlatform := i.targetDir.targetPlatform // we inherit this to behave correctly in unit tests
263+
authResults := map[addrs.Provider]*getproviders.PackageAuthenticationResult{} // record auth results for all successfully fetched providers
264+
targetPlatform := i.targetDir.targetPlatform // we inherit this to behave correctly in unit tests
264265
for provider, version := range need {
265266
if i.globalCacheDir != nil {
266267
// Step 3a: If our global cache already has this version available then
@@ -399,12 +400,18 @@ NeedProvider:
399400
continue
400401
}
401402
}
403+
authResults[provider] = authResult
402404
selected[provider] = version
403405
if cb := evts.FetchPackageSuccess; cb != nil {
404406
cb(provider, version, new.PackageDir, authResult)
405407
}
406408
}
407409

410+
// Emit final event for fetching if any were successfully fetched
411+
if cb := evts.ProvidersFetched; cb != nil && len(authResults) > 0 {
412+
cb(authResults)
413+
}
414+
408415
// We'll remember our selections in a lock file inside the target directory,
409416
// so callers can recover those exact selections later by calling
410417
// SelectedPackages on the same installer.

internal/providercache/installer_events.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ type InstallerEvents struct {
107107
FetchPackageRetry func(provider addrs.Provider, version getproviders.Version, err error)
108108
FetchPackageFailure func(provider addrs.Provider, version getproviders.Version, err error)
109109

110+
// The ProvidersFetched event is called after all fetch operations if at
111+
// least one provider was fetched successfully.
112+
ProvidersFetched func(authResults map[addrs.Provider]*getproviders.PackageAuthenticationResult)
113+
110114
// HashPackageFailure is called if the installer is unable to determine
111115
// the hash of the contents of an installed package after installation.
112116
// In that case, the selection will not be recorded in the target cache
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
layout: "registry"
3+
page_title: "Plugin Signing"
4+
sidebar_current: "docs-plugins-signing"
5+
description: |-
6+
Terraform plugin signing trust levels
7+
---
8+
9+
# Plugin Signing
10+
11+
There are four levels of signing and programattic authentication for plugins in Terraform:
12+
13+
* **Signed by HashiCorp** - are built, signed, and supported by HashiCorp. Official provider plugins can
14+
typically be used without specifying provider source information in your Terraform configuration.
15+
* **Signed by Trusted Partners** - are built, signed, and supported by a third party. HashiCorp has
16+
verified the ownership of the private key and we provide a chain of trust to the CLI to verify this
17+
programatically. To use partner providers in your Terraform configuration, you need to specify the
18+
provider source, typically this is the namespace and name to download from the registry.
19+
* **Self-signed** - are built, signed, and supported by a third party. HashiCorp does not provide a verification or chain of trust for the signing. You will want to obtain and validate fingerprints manually if you want to ensure you are using a binary you can trust.
20+
* **Unsigned** - Terraform does support fetching and using unsigned binaries, but you should take extreme care when doing so as no programatic authentication is performed on the downloaded binary.
21+
22+
Usage of plugins from the registry is subject to the Registry's [Terms of Use](https://registry.terraform.io/terms).

website/docs/registry/providers/tiers.html.md

Lines changed: 0 additions & 20 deletions
This file was deleted.

website/layouts/docs.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,10 @@
424424
<a href="/docs/plugins/basics.html">Basics</a>
425425
</li>
426426

427+
<li<%= sidebar_current("docs-plugins-signing") %>>
428+
<a href="/docs/plugins/signing.html">Signing</a>
429+
</li>
430+
427431
<li<%= sidebar_current("docs-plugins-provider") %>>
428432
<a href="/docs/plugins/provider.html">Provider</a>
429433
</li>

0 commit comments

Comments
 (0)