This tutorial is part of the Bytebase Terraform Provider series:

What You’ll Learn

  • 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

Prerequisites

Before starting this tutorial, ensure you have:

Setup

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 Admin role

Understanding IAM in Bytebase

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

Configure Access Control

Step 1 - Configure Workspace IAM Policy

Terraform resourcebytebase_iam_policy
Sample file7-1-workspace-iam.tf
Create 7-1-workspace-iam.tf with workspace-level permissions:
7-1-workspace-iam.tf
resource "bytebase_iam_policy" "workspace_iam" {
  depends_on = [
    bytebase_user.workspace_admin,
    bytebase_user.tf_service_account,
    bytebase_user.workspace_dba1,
    bytebase_user.workspace_dba2,
    bytebase_group.qa
  ]

  parent = "workspaces/-"

  iam_policy {

    binding {
      role = "roles/workspaceAdmin"
      members = [
        format("user:%s", bytebase_user.workspace_admin.email),
        format("user:%s", bytebase_user.tf_service_account.email),
      ]
    }

    binding {
      role = "roles/workspaceDBA"
      members = [
        format("user:%s", bytebase_user.workspace_dba1.email),
        format("user:%s", bytebase_user.workspace_dba2.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
    }
  }
}
allUsers is a special member representing everyone in the workspace. Without it, users may be unable to access the workspace.

Step 2 - Apply Workspace IAM Configuration

terraform plan
terraform apply
Verify Workspace Roles
  1. Go to IAM & Admin > Members
  2. Check user roles:
    • admin@example.com: Workspace Admin
    • tf@service.bytebase.com: Workspace Admin
    • dba@example.com, dba2@example.com: Workspace DBA
    • allUsers: Workspace Member
  3. Note that QA Team group has Project Viewer role for ALL projects members

Step 3 - Configure Project IAM Policy

Terraform resourcebytebase_iam_policy
Sample file7-2-project-iam.tf
Create 7-2-project-iam.tf for project-specific permissions:
7-2-project-iam.tf
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"
      }
    }

  }
}
2027-07-10T16:17:49Z is an ISO 8601 UTC timestamp. Our system uses PostgreSQL to store metadata, where this value is stored as a timestamptz.

Step 4 - Apply Complete IAM Configuration

terraform plan
terraform apply

Step 5 - Verify Project Permissions

Go to Project One > Manage > Members:
  • QA Team: Project Viewer (inherited from workspace)
  • Terraform Service Account: Project Owner (as creator)
project-1-members

Step 6 - Test Access Control

Test the access control configuration by logging in as different users:

Set Up Test User

  1. Go to IAM & Admin > Users & Groups.
  2. Find and click on Developer 1.
  3. Click Edit and set a password. dev1-pw

Test Developer Access

  1. Log in as dev1@example.com in a new browser/incognito window.
  2. Verify project visibility:
    • ✅ Can see Project Two
    • ❌ Cannot see Project One

Test SQL Editor Restrictions

  1. Navigate to SQL Editor.
  2. Connect to Prod > Prod Sample Instance > hr_prod.
  3. Test table access:
    • ✅ Query employee table - Should work
    • ✅ Query salary table - Should work
    • ❌ Query department table - Should fail with permission error
    sql-editor-employee sql-editor-department

Common Access Control Patterns

This tutorial demonstrates several best practices:
  1. Separation of Duties: DBAs have owner permissions, developers have restricted access
  2. Group-Based Management: Use groups instead of individual user assignments
  3. Least Privilege: Grant only necessary permissions at the appropriate level
  4. Conditional Access: Time-limited, table-specific permissions for sensitive data
  5. Inheritance: Workspace-level project roles apply to ALL projects

Key Points

  • 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

Part 8: Manage Data Masking with Terraform