Write policy plugins
Plugins provide a way to extend Terraform policy with additional functions that you can use to customize your policy authoring experience. Write Terraform policy plugins in Golang using the terraform-policy-plugin-framework open source library, and compile them for your testing environment and HCP Terraform execution environment.
Requirements
You must compile Terraform policy plugins and include them in your policy VCS repository before you can use them in your policies. You must compile plugins for an architecture that matches the environment in which Terraform policy runs.
Author a plugin
To author your own plugins, create a new Go package, import the Terraform policy plugin framework library, and then author a main() function to register your plugin's functions and Go functions to implement each of them.
The following is an example of a plugin that defines two functions, echo, and trim:
plugins/src/example/main.go
package main
import (
"strings"
"github.com/hashicorp/terraform-policy-plugin-framework/policy-plugin/plugins"
)
func main() {
plugins.RegisterFunction("echo", echo)
plugins.RegisterFunction("trim", trim)
plugins.Serve()
}
func echo(value string) (string, error) {
return value, nil
}
func trim(value, prefix string) (string, error) {
return strings.TrimPrefix(value, prefix), nil
}
After you implement your plugin in Go, compile it into a binary for your target platform and store both the source and binary in the same VCS repository as your policy files. Because plugins are natively compiled Go binaries, you must compile them for the specific OS and architecture where your policy set runs.
Plugin directory structure
Set up the following recommended directory structure for your plugin in your VCS repository:
./
├── policies/
├── tests/
├── plugins/
│ ├── src/
│ │ └── example/
│ │ ├── main.go
│ │ ├── go.mod
│ │ └── go.sum
│ └── bin/
│ └── example
└── README.md
When you enforce your policies in HCP Terraform, your VCS repository must also contain the plugin binary, compiled for the OS and architecture of the system where the plugin runs.
Compile a plugin
Before you can use a plugin in your policies, you must compile the plugin into a binary that is compatible with the target architecture. When testing policies on your local machine, compile the plugin to match your system's OS and architecture.
When deploying policies to HCP Terraform, you must compile the plugin to match the OS and architecture HCP Terraform uses to evaluate your policies. When the HCP Terraform execution mode is set to Remote, the plugin must match the HCP Terraform worker. When set to Agent, the plugin must match the HCP Terraform agent that you have configured for your organization. Refer to Default execution mode in the HCP Terraform documentation for more information.
HCP Terraform workers run a linux/amd64 architecture. If you use HCP Terraform agents, your agents may use either a linux/amd64 or a linux/arm64 environment. Refer to VCS setup for Terraform policy for more information about evaluating your policies in HCP Terraform.
To compile your plugin, first change into the plugin source directory.
$ cd plugins/src/example
Initialize go modules.
$ go mod init example
Replace example with the name of your plugin.
Download and verify go modules.
$ go mod tidy
Build the plugin for your target platform.
To test your plugin on your local machine with the tfpolicy test command, build it with the following command:
$ go build -o ../../bin/example main.go
Do not check this binary into your VCS repository because it only runs on a system compatible with your local machine.
To build the plugin for HCP Terraform workers or agents running linux/amd64, run the following command:
$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ../../bin/example main.go
To build the plugin for HCP Terraform agents running linux/arm64, run the following command:
$ CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o ../../bin/example main.go
The CGO_ENABLED=0 environment variable creates a portable, statically linked binary. The GOOS and GOARCH environment variables specify the target operating system and architecture. Be sure to commit the correct binary for your HCP Terraform environment to your version control repository.
To test your plugin in an integration environment, compile it with the appropriate flags for that environment.
To verify the architecture of a plugin binary after it has been built, run the file command to print out information about your plugin binary, including the architecture it was built for.
$ file ../../bin/example
../../bin/example: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=tcL6PtwbRKimZ9iy-iA7/FryCXlRse6zTcZ_uYu9v/frsL-MoNJNn84Zs4Z2ly/_dgXVY_pV7ZU36C1ZDHc, BuildID[sha1]=8f0bf62fe3d29c58f659657741d1108523deb544, with debug_info, not stripped
The file command detects plugins built for linux/amd64 as ELF 64-bit LSB executable, x86-64, and plugins built for linux/arm64 as 64-bit LSB executable, ARM aarch64.
Use plugins in policies
Specify plugins by using the plugins block within the policy block of your .policy.hcl files. Refer to policy for more information.
policies/example.policy.hcl
policy {
plugins {
example = {
source = "../plugins/bin/example"
}
second_example = {
source = "path/to/second-bin"
}
}
}
locals {
instance_type = plugin::example::trim("foo.t3.micro", "foo.")
}
The value of the source attribute must be a string that is the relative path to a binary in the same VCS repository as your policies. The binary must be a valid Terraform policy Go plugin server. Use the terraform-policy-plugin-framework open source library to ensure your plugin provides the correct interface. Be sure to commit a binary compiled for the correct architecture to your VCS repository. Refer to VCS setup for Terraform policy for more information.
In your policies, reference your plugin functions with the plugin::<plugin_label>::<function_name>(<arguments...>).