hashicorp / hc-install

Go module for downloading or locating HashiCorp binaries, verifying signatures and checksums, and asserting version constraints.

Home Page:https://pkg.go.dev/github.com/hashicorp/hc-install

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow specifying custom checksum verification logic

malt3 opened this issue · comments

I am using hc-install and terraform-exec and am pleased to see that terraform binary hashes are signed and the signature is checked when downloading terraform binaries.
For supply chain security, I would like to be able to pin expected hashes for terraform binaries (similar to terraform providers lock and the dependency lock file).

Hi @malt3
As for a "full-blown" lock file comparable to .terraform.lock.hcl - this is unlikely to be implemented as part of hc-install, mostly for the reasons outlined in the Readme, which could be summarised as "hc-install is a library, not a package manager".

This may feel vague as a statement and there is some room for interpretation, which we stepped into when implementing a CLI for hc-install, but we still aimed to keep it relatively flexible, rather than opinionated. The main idea remains that hc-install provides the "lego bricks" which others can build things out of - that may include version management a la tfenv, or even their own package manager, if they wish.


Side-stepping hc-install: Assuming you apply the same risk profile to other software which you install to wherever you install Terraform - How do you solve this problem for the other software within your environment? While I'm not familiar with Constellation, I'm guessing that in the context of that project, it's not a concern since it's the end-users of Constellation who have to deal with that. Correct me if I'm wrong here.

On that note, I wonder if treating Terraform the same way as the other dependencies would be beneficial to you? Then you could avoid hc-install entirely and just "trust whatever is installed on the filesystem" (as presumably you already trust other software there anyway) or use the fs.* sources exclusively to only discover existing installations, rather than install Terraform at runtime.

HashiCorp maintains various repositories for popular package managers, so installation of Terraform that way shouldn't be a burden for an operator who is already familiar with the process for other software.

If the above doesn't meet your requirements - I would appreciate if you could share the reasons or concerns.


Coming back to "hc-install as lego bricks": What we may be open to is expanding the API such that you can build some form of hash pinning / dependency lock file on top of it. It would probably come as an interface under product.Product, similar to GetVersion():

https://pkg.go.dev/github.com/hashicorp/hc-install@v0.4.0/product#Product

type VerifyChecksumFunc func(ctx context.Context, calculatedChecksum []byte) error

type Product struct {
	VerifyChecksum VerifyChecksumFunc

	// GetVersion represents how to obtain the version of the product
	// reflecting any output or CLI flag differences
	GetVersion func(ctx [context](https://pkg.go.dev/context).[Context](https://pkg.go.dev/context#Context), execPath [string](https://pkg.go.dev/builtin#string)) (*version.Version, [error](https://pkg.go.dev/builtin#error))

One assumption I'm making is that you'd verify the signature on your end, and store the checksums somewhere and then only compare those checksums via hc-install. i.e. Setting VerifyChecksum would imply that you are bypassing both the signature and checksum download and verification.

Another assumption here is that hc-install will download Terraform relevant for the GOOS and GOARCH and you're most likely to download an exact version of Terraform, so you know that too. We could however expand the interface to include all these details, e.g.

type VerifyChecksumFunc func(ctx context.Context, archiveReader io.Reader, os, arch string, version *version.Version) error

or we could attach that to the context.

Nothing is set in stone here, but before we go down this route of expanding the API I would like you to consider the other solution.

Thank you for this detailed response. Let me try to explain our concerns first.


With Constellation, we aim to make every operation done by our tools reproducible and verifiable for our users. We do this to build trust in our tools. If our software is open source, can be build in a reproducible way and we pin all of our binary dependencies with a hash, we can prevent many common supply chain attacks.


Regarding possible resolutions of the feature request you mentioned:

  • Side-stepping: If users of Constellation preinstall terraform, we can argue that they are responsible for the supply chain of the terraform binary. However, due to usability concerns, we would like to have a fallback in our CLI to install terraform if no suitable version is available. We also want to make only little assumptions over the user's environment (package manager) and want to follow the principle of least privilege. hc-install and terraform-exec are great abstractions to get very close to what we want.
  • Expanding the API: This is exactly what we are looking for. We can provide the hashes from our side even for every version and platform in a matrix configuration and hc-install verifies the downloaded files for us. I also believe that the library already implements hash verification and only needs a way for us to provide hashes.

Thanks again for the response. I would be happy to assist with further input, an attempt to implement this, testing or more.