Terraform
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.com
gpg: directory '/Users/rnorwood/verify-terraform/./.gnupg' created
gpg: keybox '/Users/rnorwood/verify-terraform/./.gnupg/pubring.kbx' created
gpg: /Users/rnorwood/verify-terraform/./.gnupg/trustdb.gpg: trustdb created
gpg: key 33B7139B683F1365 marked as ultimately trusted
gpg: directory '/Users/rnorwood/verify-terraform/./.gnupg/openpgp-revocs.d' created
gpg: 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 Speed
100 7717 100 7717 0 0 30268 0 --:--:-- --:--:-- --:--:-- 30381
Import the keys into your GPG keychain.
$ gpg --import pgp_keys.asc
gpg: key 34365D9472D7468F: public key "HashiCorp Security (hashicorp.com/security) <security@hashicorp.com>" imported
gpg: Total number processed: 1
gpg: 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 trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2023-05-12
pub rsa4096/34365D9472D7468F
created: 2021-04-19 expires: 2026-04-18 usage: SC
trust: unknown validity: unknown
sub rsa4096/54422F612379BA9A
created: 2021-04-19 expires: 2026-04-18 usage: E
sub rsa4096/B0B441097685B676
created: 2021-04-19 expires: 2022-04-20 usage: S
sub 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 your
key "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 trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 1 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1 valid: 1 signed: 0 trust: 1-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2023-05-12
pub rsa4096 2021-04-19 [SC] [expires: 2026-04-18]
C874 011F 0AB4 0511 0D02 1055 3436 5D94 72D7 468F
uid [ 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.com
sub 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 Speed
100 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 Speed
100 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 Speed
100 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_SHA256SUMS
gpg: Signature made Thu May 6 13:08:56 2021 CDT
gpg: using RSA key B36CBA91A2C0730C435FC280B0B441097685B676
gpg: 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_SHA256SUMS
terraform_0.15.3_darwin_amd64.zip: OK
shasum: terraform_0.15.3_freebsd_386.zip:
terraform_0.15.3_freebsd_386.zip: FAILED open or read
shasum: terraform_0.15.3_freebsd_amd64.zip: No such file or directory
terraform_0.15.3_freebsd_amd64.zip: FAILED open or read
shasum: 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.