5. Infrastructure Governance with HCP Terraform
Application delivery depends on infrastructure: GitLab configuration, Terraform workspaces, Kubernetes clusters, runner namespaces, policy sets, cloud permissions, and network paths. If that infrastructure changes without review, the delivery platform can become unsafe even when application pipelines look healthy.
HCP Terraform is the provisioning and infrastructure governance plane in this guide. It owns remote state, locking, speculative plans, policy checks, and approved applies. It does not own GitLab pipeline logic, per-repository CI content, or runtime enforcement inside application pipelines.
Infrastructure-as-code in plain language
Section titled “Infrastructure-as-code in plain language”Infrastructure-as-code means writing desired infrastructure state in files instead of configuring everything manually in a UI. A Terraform file can describe a GitLab project, a cloud network, a Kubernetes namespace, or an HCP Terraform workspace. Terraform compares the desired state to real state and produces a plan.
The plan is the key governance artifact. It answers: what will change if we apply this?
That makes review possible. A platform engineer can inspect a plan before it changes branch protections, creates runner infrastructure, modifies workspace variables, or updates a policy set. Without a plan, the organization is trusting hidden automation.
Why HCP Terraform is a control plane
Section titled “Why HCP Terraform is a control plane”HCP Terraform is useful because it separates plan generation, policy evaluation, state management, and apply permissions from an individual laptop or CI job. The platform can require speculative plans for review, centralize sensitive variables, attach policy sets, and keep a record of infrastructure changes.
That boundary keeps Terraform focused on structural state:
- GitLab groups, projects, and protected refs
- HCP Terraform projects, workspaces, and policy sets
- EKS runner infrastructure and Helm releases
- baseline configuration that should be reviewed before apply
It also keeps repository creation from becoming a manual setup exercise. Terraform can create the GitLab group structure, place new projects in the right groups, and apply baseline repository settings at creation time.
GitLab can trigger workflows and hold review history, but HCP Terraform should own the plan and apply lifecycle for infrastructure with durable blast radius.
Workspace layers
Section titled “Workspace layers”The project uses workspace layers by blast radius:
| Layer | Example workspace | Change frequency |
|---|---|---|
| Organization structure | gitlab-org-structure |
Low |
| Project provisioning | gitlab-projects-platform |
Medium |
| Policy baseline | gitlab-policy-baseline |
Controlled |
| Runner infrastructure | eks-runners-standard |
Medium |
This avoids both extremes. A workspace per repository creates state sprawl. A single global workspace creates a dangerous blast radius. Layering by domain keeps plans reviewable and limits the scope of each apply.
A practical split is:
- one workspace for organization structure and top-level groups
- one workspace for baseline GitLab policy and configuration objects
- one workspace per top-level group or platform domain when the workspace manages multiple repositories
- separate workspaces for runner infrastructure and external integrations such as IAM, networking, and deployment services
The governance stack delegates HCP Terraform object creation to a module:
module "platform_governance" { source = "../../modules/tfc-workspace"
organization = var.organization project_name = "SDLC Platform" workspaces = var.workspaces policy_sets = var.policy_sets}The module boundary matters because workspace policy is not incidental. It is part of the platform design.
Repository bootstrap
Section titled “Repository bootstrap”New projects should start with the baseline already applied:
- group placement
- protected default branches
- merge request rules
- initial approval rules
- required security policies
- default CI/CD component includes
- repository variables that are safe to set at creation time
GitLab-native templates and CI/CD components still own developer workflow shape. Terraform should bootstrap the durable settings and integrations that define the platform baseline.
Credentials
Section titled “Credentials”The credential rule is conservative: avoid long-lived credentials wherever the platform has a better option.
For AWS, HCP Terraform dynamic provider credentials are the preferred model. For GitLab, the provider still needs API access, so tokens should be scoped, sensitive, and stored as HCP Terraform workspace variables rather than committed. Kubernetes and Helm access should come from approved runner infrastructure workflows with short-lived cluster access.
Credentials do not disappear. The job is to keep them narrow, auditable, and separate from source code.
Policy checks
Section titled “Policy checks”Terraform plans should be evaluated before apply. The reference OPA policy rejects dangerous or noncompliant changes, including public GitLab groups, unprotected GitLab project variables, unmasked secret-like environment variables, and destructive changes without an explicit exception:
deny contains msg if { resource := input.resource_changes[_] resource.type == "gitlab_group" visibility := object.get(resource.change.after, "visibility_level", "private") visibility == "public" msg := sprintf("GitLab group must not be public: %s", [resource.address])}
deny contains msg if { resource := input.resource_changes[_] resource.type == "gitlab_project_variable" after := resource.change.after object.get(after, "protected", false) == false msg := sprintf("GitLab project variable must be protected: %s", [resource.address])}These rules are intentionally small. They prove the shape of the governance model without pretending every enterprise exception is known on day one.
Review flow
Section titled “Review flow”The operating model is:
- Commit desired state changes.
- Generate a speculative plan.
- Evaluate policy checks.
- Require platform approval for structural changes.
- Apply only from approved HCP Terraform runs.
This is the infrastructure equivalent of protected branches in GitLab. Safe changes should feel normal, and risky changes should be visible.
Next, the guide moves from durable infrastructure state to the runtime environment that executes CI jobs.