| title | Manage Database Access Control with Terraform |
|---|---|
| author | Adela |
| updated_at | 2025/07/16 21:15 |
| tags | Tutorial |
| integrations | Terraform |
| category | Integration |
| featured | true |
| level | Intermediate |
| estimated_time | 30 mins |
import TerraformGitHubSample from '/snippets/tutorials/terraform-github-sample.mdx';
This tutorial is part of the Bytebase Terraform Provider series:
- Part 1: Manage Environments with Terraform - Set up environments with policies
- Part 2: Manage Databases with Terraform - Register database instances
- Part 3: Manage Projects with Terraform - Organize databases into projects
- Part 4: Manage Bytebase Settings with Terraform - Configure workspace profile and approval policies
- Part 5: Manage SQL Review Rules with Terraform - Define SQL review policies
- Part 6: Manage Users and Groups with Terraform - Configure users and groups
- Part 7: Manage Database Access Control with Terraform 👈
- Part 8: Manage Data Masking with Terraform - Protect sensitive data
- Configure workspace-level IAM policies for role assignments
- Set up project-level permissions with granular database access
- Implement conditional access control for specific tables
- Test access restrictions with different user roles
Before starting this tutorial, ensure you have:
- Completed Part 6: Manage Users and Groups with Terraform
- Bytebase running with service account configured
- Your Terraform files from the previous tutorials
From the previous tutorials, you should have:
- Bytebase workspaces and projects configured
- Workspace settings and approval flows set up
- Users and groups created from Part 6
- Service account with
Workspace Adminrole
Bytebase has a hierarchical IAM system:
- Workspace Level: Permissions apply to the entire workspace
- Project Level: Permissions apply to specific projects only
- Conditional Access: Fine-grained permissions for specific databases, schemas, and tables
| Terraform resource | bytebase_iam_policy |
| Sample file | 7-1-workspace-iam.tf |
Create 7-1-workspace-iam.tf with workspace-level permissions:
resource "bytebase_iam_policy" "workspace_iam" {
depends_on = [
bytebase_user.workspace_admin,
bytebase_service_account.tf_service_account,
bytebase_workload_identity.github_ci,
bytebase_user.workspace_dba1,
bytebase_user.workspace_dba2,
bytebase_group.qa
]
# parent defaults to the current workspace when omitted.
iam_policy {
binding {
role = "roles/workspaceAdmin"
members = [
format("user:%s", bytebase_user.workspace_admin.email),
]
}
binding {
role = "roles/workspaceDBA"
members = [
format("user:%s", bytebase_user.workspace_dba1.email),
format("user:%s", bytebase_user.workspace_dba2.email),
format("serviceAccount:%s", bytebase_service_account.tf_service_account.email),
format("workloadIdentity:%s", bytebase_workload_identity.github_ci.email),
]
}
binding {
role = "roles/workspaceMember"
members = [
"allUsers"
# Note: a special member representing everyone in the workspace
]
}
binding {
role = "roles/projectViewer"
members = [
format("group:%s", bytebase_group.qa.email),
]
# Note: This grants projectViewer role to ALL projects in the workspace
}
}
}terraform plan
terraform applyVerify Workspace Roles
-
Go to IAM & Admin > Members
-
Check user roles:
admin@example.com: Workspace Admintf@service.bytebase.com: Workspace Admindba@example.com,dba2@example.com: Workspace DBAallUsers: Workspace Member
-
Note that
QA Teamgroup hasProject Viewerrole for ALL projects
| Terraform resource | bytebase_iam_policy |
| Sample file | 7-2-project-iam.tf |
Create 7-2-project-iam.tf for project-specific permissions:
resource "bytebase_iam_policy" "project_iam" {
depends_on = [
bytebase_group.developers,
bytebase_user.workspace_dba1,
bytebase_user.workspace_dba2
]
parent = bytebase_project.project-two.name
iam_policy {
binding {
role = "roles/projectOwner"
members = [
format("user:%s", bytebase_user.workspace_dba1.email),
format("user:%s", bytebase_user.workspace_dba2.email)
]
}
binding {
role = "roles/projectDeveloper"
members = [
"allUsers",
format("group:%s", bytebase_group.developers.email)
]
}
binding {
role = "roles/sqlEditorUser"
members = [
format("group:%s", bytebase_group.developers.email)
]
condition {
database = "instances/prod-sample-instance/databases/hr_prod"
schema = "public"
tables = ["employee", "salary"]
expire_timestamp = "2027-07-10T16:17:49Z"
}
}
}
}terraform plan
terraform apply - `QA Team`: `Project Viewer` (inherited from workspace)
- `Terraform Service Account`: `Project Owner` (as creator)

- `QA Team`: `Project Viewer`(inherited from workspace)
- `DBA users`: `Project Owner`
- `All users` + `Developer Team`: `Project Developer`
- `Developer Team`: `SQL Editor User` with table restrictions

1. Click **Edit** (pen icon) on `Developer Team`'s `SQL Editor User` role to see table-level restrictions:

Test the access control configuration by logging in as different users:
- Log in as
dev1@example.comin a new browser/incognito window. - Verify project visibility:
- ✅ Can see Project Two
- ❌ Cannot see Project One
-
Navigate to SQL Editor.
-
Connect to
Prod > Prod Sample Instance > hr_prod. -
Test table access:
- ✅ Query
employeetable - Should work - ✅ Query
salarytable - Should work - ❌ Query
departmenttable - Should fail with permission error
- ✅ Query
This tutorial demonstrates several best practices:
- Separation of Duties: DBAs have owner permissions, developers have restricted access
- Group-Based Management: Use groups instead of individual user assignments
- Least Privilege: Grant only necessary permissions at the appropriate level
- Conditional Access: Time-limited, table-specific permissions for sensitive data
- Inheritance: Workspace-level project roles apply to ALL projects
- IAM Hierarchy: Workspace policies apply globally, project policies are scoped to specific projects
- Project Roles at Workspace Level: When assigned in workspace IAM, project roles (like
projectViewer) apply to ALL projects - Group Benefits: Manage permissions for teams rather than individuals
- Conditional Bindings: Fine-grained access control down to table level with expiration
- Role Inheritance: Higher roles include permissions of lower roles
<Card title="Part 8: Manage Data Masking with Terraform" icon="arrow-right" href="/tutorials/manage-data-masking-with-terraform" horizontal



