Prevent malicious Terraform Providers
Tags: terraform, security, ci
Published: 2023-11-05 04:30:00

In this blog post, I describe how [tfprovidercheck](https://github.com/suzuki-shunsuke/tfprovidercheck) prevents malicious Terraform Providers from being executed.

To run Terraform securely, we should prevent malicious Terraform Providers from being executed.
[tfprovidercheck](https://github.com/suzuki-shunsuke/tfprovidercheck) is a simple command line tool for this.
Using tfprovidercheck, you can define the allow list of Terraform Providers and their versions, and check if disallowed providers aren't used.

```console
# Only google provider and azurerm provider are allowed
$ cat .tfprovidercheck.yaml
providers:
  - name: registry.terraform.io/hashicorp/google
    version: ">= 4.0.0"
  - name: registry.terraform.io/hashicorp/azurerm

# tfprovidercheck fails because aws provider is disallowed
$ terraform version -json | tfprovidercheck
FATA[0000] tfprovidercheck failed                        error="this Terraform Provider is disallowed" program=tfprovidercheck provider_name=registry.terraform.io/hashicorp/aws tfprovidercheck_version=0.1.0
```

Using tfprovidercheck in Terraform CI, you can improve the security of Terraform CI.

## Install

tfprovidercheck is a single binary written in [Go](https://go.dev/). So you only need to install an execurable file into `$PATH`.

Please see [Install](https://github.com/suzuki-shunsuke/tfprovidercheck#install).

## How to use

1. Prepare tfprovider's [configuration](https://github.com/suzuki-shunsuke/tfprovidercheck#configuration)
1. Run `terraform init` to update the list of Terraform Providers
1. Run `terraform version -json | tfprovidercheck`

To prevent malicious codes from being executed, you should run tfprovidercheck before running other Terraform commands such as `terraform validate`, `terraform plan`, and `terraform apply`.

## Configuration

There are several ways to configure tfprovidercheck.
In order of priority, they are as follows.

1. The command line option `-config [-c]`, which is the configuration file path
1. The environment variable `TFPROVIDERCHECK_CONFIG_BODY`, which is the configuration itself (YAML)
1. The environment variable `TFPROVIDERCHECK_CONFIG`, which is the configuration file path
1. The configuration file `.tfprovidercheck.yaml` on the current directory

The field `providers` lists allowed providers and their versions.

e.g.

```yaml
providers:
  - name: registry.terraform.io/hashicorp/aws
    version: ">= 3.0.0" # Quotes are necessary because '>' is a special character for YAML
  - name: registry.terraform.io/hashicorp/google
    # version is optional
```

- `name` (Required, string): `name` must be equal to the provider name. Regular expression and glob aren't supported
- `version` (Optional, string): The version constraint of Terraform Provider. `version` is evaluated as [hashicorp/go-version' Version Constraints](https://github.com/hashicorp/go-version#version-constraints). If `version` is empty, any version is allowed

## :bulb: Prevent configuration from being tampered

It's important to prevent configuration from being tamperd.
If you run tfprovidercheck on GitHub Actions, `pull_request_target` event is useful to prevent workflows from being tampered.

[Secure GitHub Actions by pull_request_target](https://dev.to/suzukishunsuke/secure-github-actions-by-pullrequesttarget-641)

tfprovidercheck supports configuring with the environment variable `TFPROVIDERCHECK_CONFIG_BODY`, so you can define the configuraiton in a workflow file.

e.g.

```yaml
- run: terraform version -json | tfprovidercheck
  env:
    TFPROVIDERCHECK_CONFIG_BODY: |
      providers:
        - name: registry.terraform.io/hashicorp/aws
          version: ">= 3.0.0"
```

Then you can prevent configuration from being tampered by `pull_request_target` event.

## Conclusion

In this blog post, I described how [tfprovidercheck](https://github.com/suzuki-shunsuke/tfprovidercheck) prevents malicious Terraform Providers from being executed.

Please try [tfprovidercheck](https://github.com/suzuki-shunsuke/tfprovidercheck) and give me your feedback!