Verify Terraform binary archives
Hackers can gain access to your critical systems by tricking you into running an executable that includes malicious code. You can avoid this by verifying that HashiCorp created and signed the Terraform executable before you run it.
In this tutorial, you will download a version of the Terraform archive, and verify that no one has tampered with it since HashiCorp created it.
To install Terraform on your system, follow our installation tutorial. The steps in this tutorial will not replace the version of Terraform on your system, if any.
Prerequisites
You will need the following to complete this tutorial.
- The
curl
command line tool, to download files to your local machine. - The
gpg
command line tool, to import and verify HashiCorp's PGP key. - The
shasum
command line tool, to verify the checksum of your Terraform archive file. The shasum command is sometimes distributed along with thegpg
command, or as part of GNU coreutils.
Create a working directory
Make a temporary directory to save your work.
$ mkdir verify-terraform
Change into that directory.
$ cd verify-terraform
Create a temporary GPG configuration
Create a temporary GPG configuration directory and key so that you can follow this tutorial without affecting your personal GPG configuration. If you would rather use your real GPG configuration to verify the Terraform archive, skip this step.
First, configure gpg
to use a temporary directory to hold your configuration
and keys instead of the default directory.
$ export GNUPGHOME=./.gnupg
Next create a temporary personal key using a blank passphrase and example email address. You will use this personal key to sign HashiCorp's key in the next step.
$ gpg --quick-generate-key --batch --passphrase "" human@example.comgpg: directory '/Users/rnorwood/verify-terraform/./.gnupg' createdgpg: keybox '/Users/rnorwood/verify-terraform/./.gnupg/pubring.kbx' createdgpg: /Users/rnorwood/verify-terraform/./.gnupg/trustdb.gpg: trustdb createdgpg: key 33B7139B683F1365 marked as ultimately trustedgpg: directory '/Users/rnorwood/verify-terraform/./.gnupg/openpgp-revocs.d' createdgpg: revocation certificate stored as '/Users/rnorwood/verify-terraform/./.gnupg/openpgp-revocs.d/D17B8E66A0D8DADA4CD8F1E033B7139B683F1365.rev'
Warning
Do not use a blank passphrase or example email address for permanent GPG keys. You are doing so in this tutorial so that you can quickly generate an example key that you will not use for real work.
Download and import HashiCorp's public key
HashiCorp uses a public PGP key to sign certain files, including the checksums for Terraform archives. You can find HashiCorp's public keys on HashiCorp's security page, and HashiCorp also publishes them to Keybase.
Download HashiCorp's public keys from Keybase.io.
$ curl --remote-name https://keybase.io/hashicorp/pgp_keys.asc % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed100 7717 100 7717 0 0 30268 0 --:--:-- --:--:-- --:--:-- 30381
Import the keys into your GPG keychain.
$ gpg --import pgp_keys.ascgpg: key 34365D9472D7468F: public key "HashiCorp Security (hashicorp.com/security) <security@hashicorp.com>" importedgpg: Total number processed: 1gpg: imported: 1
Now sign the key with the temporary one you created in the last step. You can
compare this key ID to the one found on HashiCorp's security
page. Respond to the confirmation prompt
with a y
.
$ gpg --sign-key 34365D9472D7468F gpg: checking the trustdbgpg: marginals needed: 3 completes needed: 1 trust model: pgpgpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1ugpg: next trustdb check due at 2023-05-12pub rsa4096/34365D9472D7468F created: 2021-04-19 expires: 2026-04-18 usage: SC trust: unknown validity: unknownsub rsa4096/54422F612379BA9A created: 2021-04-19 expires: 2026-04-18 usage: Esub rsa4096/B0B441097685B676 created: 2021-04-19 expires: 2022-04-20 usage: Ssub rsa4096/C820C6D5CD27AB87 created: 2021-04-21 expires: 2026-04-20 usage: S[ unknown] (1). HashiCorp Security (hashicorp.com/security) <security@hashicorp.com> pub rsa4096/34365D9472D7468F created: 2021-04-19 expires: 2026-04-18 usage: SC trust: unknown validity: unknown Primary key fingerprint: C874 011F 0AB4 0511 0D02 1055 3436 5D94 72D7 468F HashiCorp Security (hashicorp.com/security) <security@hashicorp.com> This key is due to expire on 2026-04-18.Are you sure that you want to sign this key with yourkey "human@example.com" (33B7139B683F1365) Really sign? (y/N) y
Verify PGP key ID and fingerprint
Verify the public key ID and fingerprint with gpg
.
$ gpg --fingerprint --list-signatures "HashiCorp Security"gpg: checking the trustdbgpg: marginals needed: 3 completes needed: 1 trust model: pgpgpg: depth: 0 valid: 1 signed: 1 trust: 0-, 0q, 0n, 0m, 0f, 1ugpg: depth: 1 valid: 1 signed: 0 trust: 1-, 0q, 0n, 0m, 0f, 0ugpg: next trustdb check due at 2023-05-12pub rsa4096 2021-04-19 [SC] [expires: 2026-04-18] C874 011F 0AB4 0511 0D02 1055 3436 5D94 72D7 468Fuid [ full ] HashiCorp Security (hashicorp.com/security) <security@hashicorp.com>sig 3 34365D9472D7468F 2021-04-19 HashiCorp Security (hashicorp.com/security) <security@hashicorp.com>sig 33B7139B683F1365 2021-05-12 human@example.comsub rsa4096 2021-04-19 [E] [expires: 2026-04-18]sig 34365D9472D7468F 2021-04-19 HashiCorp Security (hashicorp.com/security) <security@hashicorp.com>sub rsa4096 2021-04-19 [S] [expires: 2022-04-20]sig 34365D9472D7468F 2021-04-20 HashiCorp Security (hashicorp.com/security) <security@hashicorp.com>sub rsa4096 2021-04-21 [S] [expires: 2026-04-20]sig 34365D9472D7468F 2021-04-21 HashiCorp Security (hashicorp.com/security) <security@hashicorp.com>
Verify that the fingerprint (C874 011F 0AB4 0511 0D02 1055 3436 5D94 72D7 468F
)
and key ID (34365D9472D7468F
) match those shown in the PGP Public Keys section
of our security page.
Download Terraform archive and checksums
Download an archive of the Terraform CLI from HashiCorp's release
server. You can follow these steps
with any Terraform release, but this tutorial uses the MacOS (darwin
) release
of Terraform v0.15.3 as an example.
$ curl --remote-name https://releases.hashicorp.com/terraform/0.15.3/terraform_0.15.3_darwin_amd64.zip % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed100 31.9M 100 31.9M 0 0 30.6M 0 0:00:01 0:00:01 --:--:-- 30.6M
Now download the SHA 256 checksums for this version of Terraform. This file contains checksums for each Terraform archive for this version.
$ curl --remote-name https://releases.hashicorp.com/terraform/0.15.3/terraform_0.15.3_SHA256SUMS % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed100 1292 100 1292 0 0 11962 0 --:--:-- --:--:-- --:--:-- 11962
Also download the checksum signature file. This file contains a signature of the checksums file, signed with HashiCorp's PGP key.
$ curl --remote-name https://releases.hashicorp.com/terraform/0.15.3/terraform_0.15.3_SHA256SUMS.sig % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed100 566 100 566 0 0 4376 0 --:--:-- --:--:-- --:--:-- 4387
HashiCorp releases these files along with the Terraform binary archives for each version.
Verify checksum and signature files
Verify that HashiCorp created the signature file using its private PGP key, and that no one has tampered with it since.
$ gpg --verify terraform_0.15.3_SHA256SUMS.sig terraform_0.15.3_SHA256SUMSgpg: Signature made Thu May 6 13:08:56 2021 CDTgpg: using RSA key B36CBA91A2C0730C435FC280B0B441097685B676gpg: Good signature from "HashiCorp Security (hashicorp.com/security) <security@hashicorp.com>" [full]
Note the line starting with gpg: Good signature...
. This line tells you that
the signature matches the HashiCorp's public key, which you downloaded from
Keybase. Since you signed HashiCorp's key with your personal key earlier in the
tutorial, gpg fully trusts HashiCorp's key.
Verify Terraform archive
Verify the SHA 256 checksum of the Terraform archive you downloaded.
$ shasum --algorithm 256 --check terraform_0.15.3_SHA256SUMSterraform_0.15.3_darwin_amd64.zip: OKshasum: terraform_0.15.3_freebsd_386.zip:terraform_0.15.3_freebsd_386.zip: FAILED open or readshasum: terraform_0.15.3_freebsd_amd64.zip: No such file or directoryterraform_0.15.3_freebsd_amd64.zip: FAILED open or readshasum: terraform_0.15.3_freebsd_arm.zip: No such file or directory## ...
The SHA256SUMS file contains checksums for each Terraform release archive file for the indicated version. For this tutorial, you only downloaded the darwin_amd64 (MacOS) release. The shasum command prints out an "OK" message for that file, and "No such file or directory" for the others.
Now you have verified that no one has tampered with the Terraform archive file since HashiCorp created it, because its checksum matches the one that HashiCorp provides. You also verified that no one tampered with the checksum file itself, since HashiCorp signed it with the appropriate key.
Unset GNUPGHOME environment variable
Unset the GNUPGHOME
environment variable that you configured earlier.
$ unset GNUPGHOME
Next steps
For more information on topics covered in this tutorial, check out the following resources.
Manage Terraform Versions as part of a team.
Review HashiCorp's security page for more information about security and HashiCorp products.