The StackGuardian Terraform Provider allows Terraform to programmatically interact with the StackGuardian API to help you manage resources on the StackGuardian platform, ultimately enabling organizations to manage cloud infrastructure in a cost-efficient, secure, and compliant way.
It covers 15 resources and 17 data sources — workflows, workflow groups, stacks, templates and their revisions, connectors, policies, roles, role assignments and runner groups.
Tip
Looking for ready-to-use examples? All StackGuardian Terraform modules and examples are maintained in the terraform-stackguardian-modules repository.
The provider is published on the Terraform Registry:
terraform {
required_providers {
stackguardian = {
source = "StackGuardian/stackguardian"
version = "~> 1.12"
}
}
}
provider "stackguardian" {
api_key = "<YOUR-API-KEY>" # or env var STACKGUARDIAN_API_KEY
org_name = "<YOUR-ORG-NAME>" # or env var STACKGUARDIAN_ORG_NAME
api_uri = "https://api.app.stackguardian.io" # or env var STACKGUARDIAN_API_URI; use "https://api.us.stackguardian.io" for the US region
}
resource "stackguardian_workflow_group" "example" {
resource_name = "Simple-Workflow-Group"
description = "Example of how to create a workflow group using the StackGuardian Terraform Provider"
tags = ["tf-provider-example", "example"]
}Reference for every resource and data source is on the Terraform Registry, alongside eleven guides:
| Guide | What it covers |
|---|---|
| Installation | Installing and configuring the provider |
| Getting Started | A working deployment, one resource at a time |
| Object Model | How workflow groups, templates, connectors and roles relate |
| Resource IDs | The path-form IDs StackGuardian uses, and where they differ |
| Runtime References | The ${...} tokens the platform resolves at run time |
| Templates and Revisions | The template/revision split, and what a revision upgrade changes |
| Policies | Guardrails, approval gates, and where a policy body comes from |
| Access Management | Roles, permissions and assignments |
| Team Onboarding | Laying out groups and roles for a team |
| Importing Existing Resources | Import ID formats per resource |
| Troubleshooting | Common errors and what they mean |
- terraform-stackguardian-modules — the collection of StackGuardian Terraform modules and examples.
- Quickstart — a minimal working configuration to get started.
- Onboarding projects — end-to-end projects covering connectors, workflow groups, roles and role assignments.
- Go >= 1.26.7 (see go.mod)
- Terraform — CI tests against 1.14.0; the
acceptance suite skips versions below 1.1.0, and the
import {}block examples need 1.5.0 or newer tfplugindocsfor documentation work, viamake tools-installactto run the GitHub workflows locally (optional)
| Command | What it does |
|---|---|
make build |
Compile the provider binary |
make install |
Build and install into ~/.terraform.d/plugins for local use |
make test |
Unit tests |
make test-acc |
Acceptance tests against a real organization |
make docs-generate |
Regenerate docs/ from the schemas and templates |
make docs-validate |
Structure and frontmatter checks |
make docs-check |
Fail if docs/ is out of date — the CI gate |
make docs-validate-examples |
Type-check every documentation example |
docs/ is generated — never edit it by hand. Content lives in two places:
- Attribute text comes from
MarkdownDescriptionin eachschema.go, mostly via shared constants ininternal/constants/. A data source should reuse the same constant as its resource twin so the two cannot drift. - Page prose lives in
docs-templates/, and embedded.tfsnippets indocs-examples/.
Edit those, then:
make docs-generate # rebuild docs/
make docs-validate # structure and frontmatter
make docs-validate-examples # type-check every example
make docs-check # fail if docs/ is staledocs-validate-examples needs no credentials and makes no API calls. It builds the provider, serves
it from a local filesystem mirror, and runs terraform validate over every example — the standalone
files under docs-examples/ and docs-guides-assets/, plus every ```terraform block embedded
in page and guide prose. Prose blocks are not uniform, so
scripts/extract-doc-blocks.py classifies each one and checks it
the way it can actually be checked: self-contained snippets are validated, import {} blocks have
their target verified against the schema, and bare attribute fragments have their names looked up.
That catches unknown resource types, renamed attributes, bad references and type errors before a
reader copies them.
Unit tests need nothing:
make testAcceptance tests create and destroy real resources, so they need an organization:
export TF_ACC=1
export STACKGUARDIAN_API_KEY=<key>
export STACKGUARDIAN_API_URI=<uri>
export STACKGUARDIAN_ORG_NAME=<org>
make test-acc # everything
make test-acc TEST=./internal/resource/workflow_git/ # one package
make test-acc TESTARGS='-run TestAccWorkflowGit_WithVcsConfig' # one testEvery identifier the suite creates is generated per run and prefixed tfacc-, via
acctest.ResourceName. Static names made the suite order-dependent: a run that failed before its
destroy step left the name taken, and every later run failed at create with 409 already exists.
The shared prefix is what makes a leak identifiable afterwards.
When a run is interrupted between create and destroy, its resources survive. Sweep them:
make test-acc-sweep # report what carries the prefix; deletes nothing
make test-acc-sweep-apply # delete itThe sweep only ever touches names carrying the tfacc- prefix, and reports rather than deletes
unless you ask it to.
The GitHub workflows can be run on your machine with act, which
avoids pushing a branch to see a CI result:
make gh-workflow-test-provider # the provider test workflow
make gh-workflow-test-api-stg # API tests against staging
make gh-workflow-test-api-prd # API tests against productionRelease notes for each version are in the CHANGELOG and on the GitHub releases page.
The minimum supported Terraform version is 1.5.7. The supported range is
defined in internal/constants/terraform_version.go:
MinTerraformVersion— the support floor, 1.5.7.MaxTerraformVersion— the newest release CI exercises. Not a ceiling on support; the provider imposes none.SupportedTerraformVersions— the CI matrix: the floor, the newest tested release, and the latest patch of every minor series in between.
Four layers keep that promise honest:
| Layer | What it does | Where |
|---|---|---|
| Runtime check | The provider refuses to configure on a CLI below the floor, with a message saying so | internal/provider/version_check.go |
| Acceptance tests | Every test case fails — rather than silently skips — below the floor | acctest.VersionChecks() |
| Compatibility gate | Every pull request to main makes each Terraform version in the matrix load the provider, decode its full schema, and validate every example under docs-examples/. No credentials required. |
.github/workflows/compat.yaml |
| Acceptance matrix | Every pull request to main runs the full acceptance suite against that same matrix |
.github/workflows/test.yaml |
Both workflows hardcode the matrix in their YAML.
TestTerraformMatrixMatchesWorkflows fails if either drifts from
SupportedTerraformVersions, so the Go list stays the single place to edit when
the range changes.
Raising the floor is a breaking change for users: bump the provider version alongside it and note it in the CHANGELOG.
All workflows gate on main:
feature branch ──PR──▶ main ──tag v*──▶ release
│ │
compatibility gate acceptance matrix
(no credentials) (hits the API)
A pull request to main runs the hermetic compatibility gate first, then the
expensive acceptance suite that creates real resources. Both target main
only — no develop branch is involved.
| Workflow | Runs on | Needs secrets | What it does |
|---|---|---|---|
compat.yaml |
PR and push to main; manual |
No | Build, go vet, unit tests, docs validation, and the Terraform compatibility matrix |
test.yaml |
PR and push to main; manual |
Yes | Full acceptance suite across the Terraform matrix, plus docs validation |
release.yaml |
Tag v*; manual |
Yes | Runs both of the above, then builds and signs the release |
test-api-prd.yaml |
Manual only | Yes | API high-load test against production, using main |
test-api-stg.yaml |
Manual only | Yes | API high-load test against staging, using main |
test-api.yaml |
Called by the two above | Yes | Shared implementation; takes gitref and testenv inputs |
community.yml |
Called by release.yaml |
Yes | GoReleaser build and GPG signing |
No workflow is scheduled. The two API load tests in particular are triggered by hand from the Actions tab — they used to run on a cron during a fixed window, and now need someone to start them.
Everything that calls the API shares one StackGuardian organization, and some
tests use fixed resource names, so overlapping runs collide in ways that look
like version incompatibilities rather than the race they are. test.yaml guards
against this twice: max-parallel: 1 keeps its own matrix sequential, and a
concurrency: acceptance-tests group stops two of its runs overlapping. That
group does not cover test-api-prd.yaml or test-api-stg.yaml — check the
Actions tab before triggering a load test by hand.
Contributions are welcome — please see CONTRIBUTING.md for guidelines and the Code of Conduct for community standards. Use GitHub issues to report bugs or request features.
This project is licensed under the Mozilla Public License 2.0.