Back to Bytebase

Grant Permission

backend/api/mcp/skills/grant-permission.md

3.17.14.3 KB
Original Source

Grant Permission

Overview

Grant roles to users or groups using Bytebase's RBAC system. Permissions can be set at workspace level (global) or project level (scoped).

Prerequisites

  • Have bb.workspaces.setIamPolicy for workspace-level grants
  • Have bb.projects.setIamPolicy for project-level grants

Permission Levels

LevelScopeUse Case
WorkspaceAll projectsAdmins, DBAs, global viewers
ProjectSingle projectDevelopers, project owners

Workflow

Step 1: List Available Roles

search_api(operationId="RoleService/ListRoles")
call_api(operationId="RoleService/ListRoles", body={})

Built-in roles:

RoleDescription
roles/workspaceAdminFull workspace access
roles/workspaceDBADatabase administration
roles/workspaceMemberBasic workspace access
roles/projectOwnerFull project access
roles/projectDeveloperDevelopment access (create issues, plans)
roles/projectReleaserExecute rollouts
roles/sqlEditorUserSQL Editor access only
roles/projectViewerRead-only access
roles/gitopsServiceAgentGitOps automation

Step 2: Get Current IAM Policy

Always fetch current policy first to avoid overwriting existing bindings.

Workspace level:

search_api(operationId="WorkspaceService/GetIamPolicy")
call_api(operationId="WorkspaceService/GetIamPolicy", body={
  "resource": "workspaces/{id}"
})

Project level:

search_api(operationId="ProjectService/GetIamPolicy")
call_api(operationId="ProjectService/GetIamPolicy", body={
  "resource": "projects/{project-id}"
})

Save the returned etag for the update.

Step 3: Set IAM Policy

Add new bindings while preserving existing ones.

Workspace level:

search_api(operationId="WorkspaceService/SetIamPolicy")
call_api(operationId="WorkspaceService/SetIamPolicy", body={
  "resource": "workspaces/{id}",
  "etag": "{etag-from-get}",
  "policy": {
    "bindings": [
      {
        "role": "roles/workspaceDBA",
        "members": ["user:[email protected]"]
      },
      {
        "role": "roles/workspaceMember",
        "members": [
          "user:[email protected]",
          "user:[email protected]",
          "group:[email protected]"
        ]
      }
    ]
  }
})

Project level:

call_api(operationId="ProjectService/SetIamPolicy", body={
  "resource": "projects/{project-id}",
  "etag": "{etag-from-get}",
  "policy": {
    "bindings": [
      {
        "role": "roles/projectOwner",
        "members": ["user:[email protected]"]
      },
      {
        "role": "roles/projectDeveloper",
        "members": ["group:[email protected]"]
      }
    ]
  }
})

Member Format

TypeFormatExample
Useruser:{email}user:[email protected]
Groupgroup:{email}group:[email protected]
All usersallUsersallUsers

Time-Limited Access (CEL Expressions)

Grant temporary access using CEL conditions.

call_api(operationId="ProjectService/SetIamPolicy", body={
  "resource": "projects/{project-id}",
  "etag": "{etag}",
  "policy": {
    "bindings": [{
      "role": "roles/projectDeveloper",
      "members": ["user:[email protected]"],
      "condition": {
        "expression": "request.time < timestamp('2024-12-31T23:59:59Z')",
        "title": "Temporary access",
        "description": "Access expires end of 2024"
      }
    }]
  }
})

CEL variables for sqlEditorUser:

  • resource.database: Database name (instances/{id}/databases/{name})
  • resource.schema_name: Schema name
  • resource.table_name: Table name
  • request.time: For expiration

CEL examples:

  • Expire at date: request.time < timestamp('2024-12-31T23:59:59Z')
  • Limit to database: resource.database == "instances/prod/databases/main"

Common Errors

ErrorCauseFix
etag mismatchPolicy changedRe-fetch policy and retry
role not foundInvalid role nameList roles first, use roles/{name} format
invalid memberWrong formatUse user:email or group:email format
permission deniedMissing setIamPolicyCheck workspace/project admin access
invalid CELBad expression syntaxValidate CEL expression format