319 lines
12 KiB
Markdown
319 lines
12 KiB
Markdown
# Terraform Provider for Threshold
|
|
|
|
A community fork of [hashicorp/terraform-provider-boundary](https://github.com/hashicorp/terraform-provider-boundary)
|
|
for [Threshold](https://repo.anhonesthost.net/CyberCoveLLC/threshold), itself a community fork of Boundary CE.
|
|
|
|
## About this fork
|
|
|
|
- **Upstream:** `hashicorp/terraform-provider-boundary`, licensed MPL-2.0 (see [LICENSE](LICENSE) and [NOTICE](NOTICE)).
|
|
This fork is not affiliated with, endorsed by, or supported by HashiCorp or IBM.
|
|
- **What changed:** the Go module is `repo.anhonesthost.net/CyberCoveLLC/terraform-provider-threshold`,
|
|
it builds against the Threshold `api` and `sdk` Go modules
|
|
(`repo.anhonesthost.net/CyberCoveLLC/threshold/api` and `.../sdk`), and product wording in docs and
|
|
schema descriptions says "Threshold". Release plumbing for HashiCorp's CRT/registry pipeline was removed.
|
|
- **Compatibility:** resource and data source type names (`boundary_*`), provider arguments (`addr`,
|
|
`auth_method_id`, ...) and the `BOUNDARY_*` environment variables are unchanged, so existing Terraform
|
|
configurations keep working. Because the resource types start with `boundary_`, Terraform infers the
|
|
provider local name `boundary`; keep `boundary = { source = ... }` in `required_providers`.
|
|
- **Distribution:** there is no public registry for this provider. Install it from a release zip or a local build
|
|
as described below. Its address is `repo.anhonesthost.net/cybercovellc/threshold`.
|
|
|
|
## Requirements
|
|
|
|
- [Terraform](https://www.terraform.io/downloads.html) >= 0.13.x (or OpenTofu)
|
|
- [Go](https://golang.org/doc/install) >= 1.26 (see `go.mod`), with `GOPRIVATE=repo.anhonesthost.net` if the Threshold modules are not publicly fetchable
|
|
|
|
## Installing
|
|
|
|
Provider address: `repo.anhonesthost.net/cybercovellc/threshold`. Version `0.1.0` is used in the examples.
|
|
|
|
### 1. Build locally
|
|
|
|
```sh
|
|
export GOPRIVATE=repo.anhonesthost.net
|
|
make build-all VERSION=0.1.0 # or: scripts/build-release.sh 0.1.0 dist
|
|
# single platform, no zip:
|
|
go build -o terraform-provider-threshold .
|
|
# with goreleaser installed:
|
|
goreleaser build --snapshot --clean --single-target
|
|
```
|
|
|
|
`make build-all` writes `dist/terraform-provider-threshold_<version>_<os>_<arch>.zip` for linux, darwin and
|
|
windows on amd64 and arm64 (needs `zip`). Never commit `dist/`.
|
|
|
|
### 2. Filesystem mirror (recommended for shared hosts)
|
|
|
|
Terraform's `provider_installation` can serve providers from a local directory. Layout (unpacked form):
|
|
|
|
```
|
|
/usr/share/terraform/providers/
|
|
repo.anhonesthost.net/cybercovellc/threshold/0.1.0/linux_amd64/terraform-provider-threshold_v0.1.0
|
|
```
|
|
|
|
or the packed form: `.../repo.anhonesthost.net/cybercovellc/threshold/terraform-provider-threshold_0.1.0_linux_amd64.zip`.
|
|
Then in `~/.terraformrc` (`%APPDATA%\terraform.rc` on Windows):
|
|
|
|
```hcl
|
|
provider_installation {
|
|
filesystem_mirror {
|
|
path = "/usr/share/terraform/providers"
|
|
include = ["repo.anhonesthost.net/cybercovellc/threshold"]
|
|
}
|
|
direct {
|
|
exclude = ["repo.anhonesthost.net/cybercovellc/threshold"]
|
|
}
|
|
}
|
|
```
|
|
|
|
and in your configuration:
|
|
|
|
```hcl
|
|
terraform {
|
|
required_providers {
|
|
boundary = {
|
|
source = "repo.anhonesthost.net/cybercovellc/threshold"
|
|
version = "0.1.0"
|
|
}
|
|
}
|
|
}
|
|
|
|
provider "boundary" {
|
|
addr = "https://threshold.example.com:9200"
|
|
# auth_method_id / auth_method_login_name / auth_method_password, token, or recovery_kms_hcl
|
|
}
|
|
```
|
|
|
|
### 3. dev_overrides (development)
|
|
|
|
Build the binary into a directory and point Terraform at it (`terraform init` is not needed, and `terraform plan`
|
|
prints a warning):
|
|
|
|
```hcl
|
|
# ~/.terraformrc
|
|
provider_installation {
|
|
dev_overrides {
|
|
"repo.anhonesthost.net/cybercovellc/threshold" = "/home/you/go/bin" # directory holding terraform-provider-threshold
|
|
}
|
|
direct {}
|
|
}
|
|
```
|
|
|
|
`go install .` places `terraform-provider-threshold` in `$GOPATH/bin`. `make dev` installs a `0.0.1` build
|
|
into Terraform's implied local mirror under the same address.
|
|
|
|
## Building The Provider
|
|
|
|
1. Clone the repository
|
|
1. Enter the repository directory
|
|
1. Build with `go build -o terraform-provider-threshold .` (or `make dev`, which also builds the optional built-in KMS plugins from `plugins/kms/mains`)
|
|
|
|
## Adding Dependencies
|
|
|
|
This provider uses [Go modules](https://github.com/golang/go/wiki/Modules).
|
|
Please see the Go documentation for the most up to date information about using Go modules.
|
|
|
|
To add a new dependency `github.com/author/dependency` to your Terraform provider:
|
|
|
|
```shell
|
|
go get github.com/author/dependency
|
|
go mod tidy
|
|
```
|
|
|
|
Then commit the changes to `go.mod` and `go.sum`.
|
|
|
|
## Developing the Provider
|
|
|
|
If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (see [Requirements](#requirements) above).
|
|
|
|
To compile the provider, run `go install`. This will build the provider and put the provider binary in the `$GOPATH/bin` directory.
|
|
|
|
Unit tests (no controller needed) run with `make test`. All other tests are acceptance tests and require a running
|
|
Threshold/Boundary-compatible controller (`BOUNDARY_ADDR`, `BOUNDARY_AUTH_TOKEN`, `BOUNDARY_DEV_RECOVERY_KEY`) and, for the
|
|
Vault tests, Docker. In order to run the full suite of Acceptance tests,
|
|
a postgres docker container must be started first:
|
|
|
|
```sh
|
|
$ go mod download # ensure boundary is installed, files are used by the docker image
|
|
$ make test-database-up
|
|
```
|
|
|
|
Once the test database is ready the tests can be run using `make testacc`.
|
|
|
|
*Note:* Acceptance tests create real resources, and often cost money to run.
|
|
|
|
```sh
|
|
$ make testacc
|
|
```
|
|
|
|
For more details on the docker image and troubleshooting see the
|
|
[Threshold contributing guide](https://repo.anhonesthost.net/CyberCoveLLC/threshold).
|
|
|
|
## Debugging the provider
|
|
|
|
If you're using vscode, this provider has delve debugging baked into the [.vscode](https://repo.anhonesthost.net/CyberCoveLLC/terraform-provider-threshold/tree/main/.vscode) directory. To debug you can find instructions [here.](https://dev.to/drewmullen/vscode-terraform-provider-development-setup-debugging-6bn#usage)
|
|
|
|
## Generating Docs
|
|
|
|
This provider uses the [terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs/) tool to generate documentation. Each resource and data source requires a set of examples [examples](https://repo.anhonesthost.net/CyberCoveLLC/terraform-provider-threshold/tree/main/examples) then you execute a binary to generate the docs which are placed in [./docs](https://repo.anhonesthost.net/CyberCoveLLC/terraform-provider-threshold/tree/main/docs). Optionally, you can specify your own [templates](https://repo.anhonesthost.net/CyberCoveLLC/terraform-provider-threshold/tree/main/templates) for a resource or data source if you want to add custom information (example: [data "boundary_scope"](https://repo.anhonesthost.net/CyberCoveLLC/terraform-provider-threshold/blob/main/templates/data-sources/scope.md.tmpl#L11))
|
|
|
|
### New Resources & Data Sources (documentation templates)
|
|
|
|
If you're adding a new resource or a data source, you must include a documentation template for your new R/DS in [./templates](https://repo.anhonesthost.net/CyberCoveLLC/terraform-provider-threshold/tree/main/templates) directory. This provider uses the [terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs/) tool to generate documentation. For full details see the link.
|
|
|
|
### Documentation Examples for Resources & Data Sources
|
|
|
|
Examples are required for all resources and data sources. This provider uses the [terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs/) tool to generate documentation. To add examples, add a new file to the [./examples](https://repo.anhonesthost.net/CyberCoveLLC/terraform-provider-threshold/tree/main/examples) directory or update the existing files. Next make sure the corresponding template in [./templates](https://repo.anhonesthost.net/CyberCoveLLC/terraform-provider-threshold/tree/main/templates) directory references this example.
|
|
|
|
### Generating
|
|
|
|
From the root of the repo run:
|
|
|
|
```shell
|
|
go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs
|
|
```
|
|
|
|
## Using the provider
|
|
|
|
Please see our detailed docs for individual resource usage. Below is a complex example using the provider to configure all resource types available:
|
|
|
|
```hcl
|
|
provider "boundary" {
|
|
addr = "http://127.0.0.1:9200"
|
|
auth_method_id = "ampw_1234567890" # changeme
|
|
auth_method_login_name = "myuser" # changeme
|
|
auth_method_password = "passpass" # changeme
|
|
}
|
|
|
|
variable "users" {
|
|
type = set(string)
|
|
default = [
|
|
"Jim",
|
|
"Mike",
|
|
"Todd",
|
|
"Jeff",
|
|
"Randy",
|
|
"Susmitha"
|
|
]
|
|
}
|
|
|
|
variable "readonly_users" {
|
|
type = set(string)
|
|
default = [
|
|
"Jeff",
|
|
"Pete",
|
|
"JT"
|
|
]
|
|
}
|
|
|
|
variable "backend_server_ips" {
|
|
type = set(string)
|
|
default = [
|
|
"10.1.0.1",
|
|
"10.1.0.2",
|
|
]
|
|
}
|
|
|
|
resource "boundary_scope" "global" {
|
|
global_scope = true
|
|
scope_id = "global"
|
|
}
|
|
|
|
resource "boundary_scope" "corp" {
|
|
scope_id = boundary_scope.global.id
|
|
auto_create_admin_role = true
|
|
auto_create_default_role = true
|
|
}
|
|
|
|
resource "boundary_user" "users" {
|
|
for_each = var.users
|
|
name = each.key
|
|
description = "User resource for ${each.key}"
|
|
scope_id = boundary_scope.corp.id
|
|
}
|
|
|
|
// organization level group for readonly users
|
|
resource "boundary_group" "readonly" {
|
|
name = "readonly"
|
|
description = "Organization group for readonly users"
|
|
member_ids = [for user in boundary_user.readonly_users : user.id]
|
|
scope_id = boundary_scope.corp.id
|
|
}
|
|
|
|
// add org-level role for readonly access
|
|
resource "boundary_role" "organization_readonly" {
|
|
name = "readonly"
|
|
description = "Read-only role"
|
|
principal_ids = [boundary_group.readonly_users.id]
|
|
grant_strings = ["ids=*;type=*;actions=read"]
|
|
scope_id = boundary_scope.corp.id
|
|
}
|
|
|
|
// add org-level role for administration access
|
|
resource "boundary_role" "organization_admin" {
|
|
name = "admin"
|
|
description = "Administrator role"
|
|
principal_ids = concat(
|
|
[for user in boundary_user.user: user.id]
|
|
)
|
|
grant_strings = ["ids=*;type=*;actions=create,read,update,delete"]
|
|
scope_id = boundary_scope.corp.id
|
|
}
|
|
|
|
// create a project for core infrastructure
|
|
resource "boundary_scope" "core_infra" {
|
|
description = "Core infrastrcture"
|
|
scope_id = boundary_scope.corp.id
|
|
auto_create_admin_role = true
|
|
}
|
|
|
|
resource "boundary_host_catalog" "backend_servers" {
|
|
name = "backend_servers"
|
|
description = "Backend servers host catalog"
|
|
type = "static"
|
|
scope_id = boundary_scope.core_infra.id
|
|
}
|
|
|
|
resource "boundary_host" "backend_servers" {
|
|
for_each = var.backend_server_ips
|
|
type = "static"
|
|
name = "backend_server_service_${each.value}"
|
|
description = "Backend server host"
|
|
address = "${each.key}"
|
|
host_catalog_id = boundary_host_catalog.backend_servers.id
|
|
}
|
|
|
|
resource "boundary_host_set" "backend_servers_ssh" {
|
|
type = "static"
|
|
name = "backend_servers_ssh"
|
|
description = "Host set for backend servers"
|
|
host_catalog_id = boundary_host_catalog.backend_servers.id
|
|
host_ids = [for host in boundary_host.backend_servers : host.id]
|
|
}
|
|
|
|
// create target for accessing backend servers on port :8000
|
|
resource "boundary_target" "backend_servers_service" {
|
|
type = "tcp"
|
|
name = "backend_servers_service"
|
|
description = "Backend service target"
|
|
scope_id = boundary_scope.core_infra.id
|
|
default_port = "8080"
|
|
|
|
host_set_ids = [
|
|
boundary_host_set.backend_servers.id
|
|
]
|
|
}
|
|
|
|
// create target for accessing backend servers on port :22
|
|
resource "boundary_target" "backend_servers_ssh" {
|
|
type = "tcp"
|
|
name = "backend_servers_ssh"
|
|
description = "Backend SSH target"
|
|
scope_id = boundary_scope.core_infra.id
|
|
default_port = "22"
|
|
|
|
host_set_ids = [
|
|
boundary_host_set.backend_servers_ssh.id
|
|
]
|
|
}
|
|
```
|