Introduction
HCP Terraform provides a hierarchical permission model where roles can be assigned at the organization, project, and workspace levels. This allows fine-grained control over what teams and users can access, including managing workspace runs, variables, and state files.
A key aspect to note: organization-level permissions always override project and workspace-level roles. Understanding this hierarchy is critical when creating custom roles or restricting access to sensitive resources like state files.
Expected Outcome
After following this guide, you will be able to:
Understand permission scopes and role precedence in HCP Terraform.
Assign custom project and workspace roles that restrict access to sensitive resources.
Prevent unintended access caused by additive permissions across multiple teams.
Prerequisites
- HCP Terraform Owners Access
Terraform CLI (v1.3+) installed
API token with administrative privileges
TFE provider (
hashicorp/tfe
) configured
Use Case
A project team needs to:
Read workspace configurations and approve applies.
Prevent developers from accessing state files.
This scenario is implemented using a custom workspace-level role with restricted state access, while still allowing project-level read permissions and apply capabilities.
Procedure
-
Step 1: Create a Team
provider "tfe" { hostname = "app.terraform.io" token = var.tfe_token } resource "tfe_team" "dev_team" { name = "developers" organization = "my-org" }
-
Step 2: Assign Project-Level Custom Role
resource "tfe_team_project_access" "app_operators" { access = "custom" team_id = data.tfe_team.app_operators.id project_id = data.tfe_project.target_project.id project_access { settings = "read" teams = "read" variable_sets = "read" } workspace_access { state_versions = "none" sentinel_mocks = "read" runs = "apply" variables = "read" create = false locking = false move = false delete = false run_tasks = false } }
This ensures that:
> The team can view workspace settings, approve applies, and read variables.
> The team cannot access or modify state files.Step 3: Verify Organization-Level Permissions
Navigate to Organization Settings → Teams → [Select Team] → General → Permissions.
Ensure that Project access and Workspace access are set to
none
for this team.Important: If the same users are members of an org-level team with broader access (e.g., View all Workspaces), those permissions will override the project/workspace-level restrictions.
Step 4: Audit Team Memberships
Confirm users are not in other org-level teams granting global workspace visibility.
Users should only inherit the permissions explicitly defined in the project/workspace custom role.
Key Points:-
-
Permission Precedence:
Organization-level roles (override all lower levels)
Project-level roles (apply to all workspaces in the project unless overridden)
Workspace-level roles (apply only to the workspace if no broader role exists)
-
Best Practices:
Use organization-level teams permission sparingly (only for owners).
Apply custom roles at the project level for operator teams.
Restrict workspace-level roles for developers or CI/CD pipelines.
Regularly audit team memberships to prevent unintended permission inheritance.