From 353783145729c1c29c872d972911a7007d734ac9 Mon Sep 17 00:00:00 2001
From: adela
Date: Wed, 9 Jul 2025 17:46:15 +0800
Subject: [PATCH 1/3] add tutorial hcl
---
tutorials/0-provider.tf | 15 ++++
tutorials/1-instances.tf | 37 ++++++++
tutorials/2-projects.tf | 23 +++++
tutorials/3-settings.tf | 72 ++++++++++++++++
tutorials/4-user-iam.tf | 182 +++++++++++++++++++++++++++++++++++++++
5 files changed, 329 insertions(+)
create mode 100644 tutorials/0-provider.tf
create mode 100644 tutorials/1-instances.tf
create mode 100644 tutorials/2-projects.tf
create mode 100644 tutorials/3-settings.tf
create mode 100644 tutorials/4-user-iam.tf
diff --git a/tutorials/0-provider.tf b/tutorials/0-provider.tf
new file mode 100644
index 0000000..ac242c3
--- /dev/null
+++ b/tutorials/0-provider.tf
@@ -0,0 +1,15 @@
+terraform {
+ required_providers {
+ bytebase = {
+ version = "3.8.0"
+ # For local development, please use "terraform.local/bytebase/bytebase" instead
+ source = "registry.terraform.io/bytebase/bytebase"
+ }
+ }
+}
+
+provider "bytebase" {
+ service_account = "tf@service.bytebase.com"
+ service_key = "bbs_EttGNSWLLGCqWB9Yev0I"
+ url = "https://valid-just-tadpole.ngrok-free.app"
+}
\ No newline at end of file
diff --git a/tutorials/1-instances.tf b/tutorials/1-instances.tf
new file mode 100644
index 0000000..7ce2592
--- /dev/null
+++ b/tutorials/1-instances.tf
@@ -0,0 +1,37 @@
+# Built-in Test Instance
+resource "bytebase_instance" "test" {
+ depends_on = [bytebase_setting.environments]
+ resource_id = "test-sample-instance"
+ environment = "environments/test"
+ title = "Test Sample Instance"
+ engine = "POSTGRES"
+ activation = true
+
+ data_sources {
+ id = "admin data source test-sample-instance"
+ type = "ADMIN"
+ host = "/tmp"
+ port = "8083"
+ username = "bbsample"
+ password = ""
+ }
+}
+
+# Built-in Prod Instance
+resource "bytebase_instance" "prod" {
+ depends_on = [bytebase_setting.environments]
+ resource_id = "prod-sample-instance"
+ environment = "environments/prod"
+ title = "Prod Sample Instance"
+ engine = "POSTGRES"
+ activation = true
+
+ data_sources {
+ id = "admin data source prod-sample-instance"
+ type = "ADMIN"
+ host = "/tmp"
+ port = "8084"
+ username = "bbsample"
+ password = ""
+ }
+}
\ No newline at end of file
diff --git a/tutorials/2-projects.tf b/tutorials/2-projects.tf
new file mode 100644
index 0000000..c188162
--- /dev/null
+++ b/tutorials/2-projects.tf
@@ -0,0 +1,23 @@
+# Project One
+resource "bytebase_project" "project-one" {
+ depends_on = [
+ bytebase_instance.test
+ ]
+ resource_id = "project-one"
+ title = "Project One"
+
+ databases = bytebase_instance.test.databases
+}
+
+# Project Two
+resource "bytebase_project" "project-two" {
+ depends_on = [
+ bytebase_instance.prod
+ ]
+ resource_id = "project-two"
+ title = "Project Two"
+
+ databases = [
+ "instances/prod-sample-instance/databases/hr_prod"
+ ]
+}
\ No newline at end of file
diff --git a/tutorials/3-settings.tf b/tutorials/3-settings.tf
new file mode 100644
index 0000000..b305811
--- /dev/null
+++ b/tutorials/3-settings.tf
@@ -0,0 +1,72 @@
+# Environment Settings
+resource "bytebase_setting" "environments" {
+ name = "settings/ENVIRONMENT"
+
+ environment_setting {
+ environment {
+ id = "test"
+ title = "Test"
+ protected = false
+ }
+ environment {
+ id = "prod"
+ title = "Prod"
+ protected = true
+ }
+ }
+}
+
+# Step 1: Workspace profile configuration
+resource "bytebase_setting" "workspace_profile" {
+ name = "settings/WORKSPACE_PROFILE"
+
+ workspace_profile {
+ disallow_signup = true
+ domains = ["example.com"]
+ enforce_identity_domain = false
+ external_url = "https://valid-just-tadpole.ngrok-free.app"
+ }
+}
+
+# Step 2: Approval flow settings
+resource "bytebase_setting" "approval_flow" {
+ name = "settings/WORKSPACE_APPROVAL"
+
+ approval_flow {
+ rules {
+ flow {
+ title = "Project Owner → DBA → Admin"
+ description = "Need DBA and workspace admin approval"
+
+ steps { role = "roles/projectOwner" }
+ steps { role = "roles/workspaceDBA" }
+ steps { role = "roles/workspaceAdmin" }
+ }
+ conditions {
+ source = "DML"
+ level = "MODERATE"
+ }
+ conditions {
+ source = "DDL"
+ level = "HIGH"
+ }
+ }
+ }
+}
+
+# Step 3: Risk management policies
+resource "bytebase_risk" "dml_moderate" {
+ title = "DML Moderate Risk"
+ source = "DML"
+ level = 200
+ active = true
+ condition = "environment_id == \"prod\" && affected_rows >= 100"
+}
+
+resource "bytebase_risk" "ddl_high" {
+ title = "DDL High Risk"
+ source = "DDL"
+ level = 300
+ active = true
+ condition = "environment_id == \"prod\""
+}
\ No newline at end of file
diff --git a/tutorials/4-user-iam.tf b/tutorials/4-user-iam.tf
new file mode 100644
index 0000000..7c70718
--- /dev/null
+++ b/tutorials/4-user-iam.tf
@@ -0,0 +1,182 @@
+# Create users and groups
+resource "bytebase_user" "workspace_admin" {
+ email = "admin@example.com"
+ title = "Workspace Admin"
+ type = "USER"
+}
+
+resource "bytebase_user" "tf_service_account" {
+ email = "tf@service.bytebase.com"
+ title = "Terraform Service Account"
+ type = "SERVICE_ACCOUNT"
+}
+
+resource "bytebase_user" "workspace_dba1" {
+ email = "dba@example.com"
+ title = "Database Administrator 1"
+ type = "USER"
+}
+
+resource "bytebase_user" "workspace_dba2" {
+ email = "dba2@example.com"
+ title = "Database Administrator 2"
+ type = "USER"
+}
+
+resource "bytebase_user" "dev1" {
+ email = "dev1@example.com"
+ title = "Developer 1"
+ type = "USER"
+}
+
+resource "bytebase_user" "dev2" {
+ email = "dev2@example.com"
+ title = "Developer 2"
+ type = "USER"
+}
+
+resource "bytebase_user" "dev3" {
+ email = "dev3@example.com"
+ title = "Developer 3"
+ type = "USER"
+}
+
+resource "bytebase_user" "qa1" {
+ email = "qa1@example.com"
+ title = "QA Tester 1"
+ type = "USER"
+}
+
+resource "bytebase_user" "qa2" {
+ email = "qa2@example.com"
+ title = "QA Tester 2"
+ type = "USER"
+}
+
+# Create groups
+resource "bytebase_group" "developers" {
+ email = "developers@example.com"
+ title = "Developer Team"
+ description = "Group for all developers"
+
+ members {
+ member = "users/${bytebase_user.dev1.email}"
+ role = "OWNER"
+ }
+
+ members {
+ member = "users/${bytebase_user.dev2.email}"
+ role = "MEMBER"
+ }
+
+ members {
+ member = "users/${bytebase_user.dev3.email}"
+ role = "MEMBER"
+ }
+}
+
+resource "bytebase_group" "qa" {
+ email = "qa@example.com"
+ title = "QA Team"
+ description = "Group for all QA testers"
+
+ members {
+ member = "users/${bytebase_user.qa1.email}"
+ role = "OWNER"
+ }
+
+ members {
+ member = "users/${bytebase_user.qa2.email}"
+ role = "MEMBER"
+ }
+}
+
+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 = [
+ format("user:%s", bytebase_user.dev1.email),
+ format("user:%s", bytebase_user.dev2.email),
+ format("user:%s", bytebase_user.dev3.email)
+ ]
+ }
+
+ binding {
+ role = "roles/projectViewer"
+ members = [
+ format("group:%s", bytebase_group.qa.email),
+ ]
+ }
+ }
+}
+
+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","department"]
+ expire_timestamp = "2027-07-10T16:17:49Z"
+ }
+ }
+
+ }
+}
\ No newline at end of file
From b1a5fd09760a24dc90ee2fa4d8cf45b2bc7434d9 Mon Sep 17 00:00:00 2001
From: adela
Date: Wed, 9 Jul 2025 17:48:00 +0800
Subject: [PATCH 2/3] fix
---
tutorials/0-provider.tf | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tutorials/0-provider.tf b/tutorials/0-provider.tf
index ac242c3..488cd8f 100644
--- a/tutorials/0-provider.tf
+++ b/tutorials/0-provider.tf
@@ -10,6 +10,6 @@ terraform {
provider "bytebase" {
service_account = "tf@service.bytebase.com"
- service_key = "bbs_EttGNSWLLGCqWB9Yev0I"
- url = "https://valid-just-tadpole.ngrok-free.app"
+ service_key = "bbs_xxxx"
+ url = "https://xxx.xxx.xxx"
}
\ No newline at end of file
From 1e6c034cc561deeb8c0346bfdb4ce38b5b66fc9e Mon Sep 17 00:00:00 2001
From: adela
Date: Fri, 11 Jul 2025 16:20:27 +0800
Subject: [PATCH 3/3] latest
---
tutorials/0-provider.tf | 2 +-
tutorials/1-0-list-env-instance.tf | 13 ++++
tutorials/1-1-env-alt.tf.alt | 17 +++++
tutorials/1-1-env.tf | 17 +++++
tutorials/1-instances-alt.tf.alt | 37 +++++++++++
tutorials/3-1-workspace-profile.tf | 10 +++
tutorials/3-2-env-setting.tf | 53 ++++++++++++++++
tutorials/3-3-risk.tf | 15 +++++
tutorials/3-4-approval-flow.tf | 24 ++++++++
tutorials/3-settings.tf | 72 ----------------------
tutorials/4-sql-review.tf | 40 ++++++++++++
tutorials/{4-user-iam.tf => 5-user-iam.tf} | 4 +-
tutorials/6-1-semantic-types.tf | 40 ++++++++++++
tutorials/6-2-classification.tf | 45 ++++++++++++++
tutorials/6-3-global-data-masking.tf | 32 ++++++++++
tutorials/6-4-database-masking.tf | 28 +++++++++
tutorials/6-5-masking-exception.tf | 28 +++++++++
17 files changed, 403 insertions(+), 74 deletions(-)
create mode 100644 tutorials/1-0-list-env-instance.tf
create mode 100644 tutorials/1-1-env-alt.tf.alt
create mode 100644 tutorials/1-1-env.tf
create mode 100644 tutorials/1-instances-alt.tf.alt
create mode 100644 tutorials/3-1-workspace-profile.tf
create mode 100644 tutorials/3-2-env-setting.tf
create mode 100644 tutorials/3-3-risk.tf
create mode 100644 tutorials/3-4-approval-flow.tf
delete mode 100644 tutorials/3-settings.tf
create mode 100644 tutorials/4-sql-review.tf
rename tutorials/{4-user-iam.tf => 5-user-iam.tf} (96%)
create mode 100644 tutorials/6-1-semantic-types.tf
create mode 100644 tutorials/6-2-classification.tf
create mode 100644 tutorials/6-3-global-data-masking.tf
create mode 100644 tutorials/6-4-database-masking.tf
create mode 100644 tutorials/6-5-masking-exception.tf
diff --git a/tutorials/0-provider.tf b/tutorials/0-provider.tf
index 488cd8f..2a1fb6c 100644
--- a/tutorials/0-provider.tf
+++ b/tutorials/0-provider.tf
@@ -1,7 +1,7 @@
terraform {
required_providers {
bytebase = {
- version = "3.8.0"
+ version = "3.8.2"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
diff --git a/tutorials/1-0-list-env-instance.tf b/tutorials/1-0-list-env-instance.tf
new file mode 100644
index 0000000..9241a1d
--- /dev/null
+++ b/tutorials/1-0-list-env-instance.tf
@@ -0,0 +1,13 @@
+# List all environments using settings
+data "bytebase_setting" "environments" {
+ name = "settings/ENVIRONMENT"
+}
+output "all_environments" {
+ value = data.bytebase_setting.environments
+}
+
+# List all instances
+data "bytebase_instance_list" "all" {}
+output "all_instances" {
+ value = data.bytebase_instance_list.all
+}
\ No newline at end of file
diff --git a/tutorials/1-1-env-alt.tf.alt b/tutorials/1-1-env-alt.tf.alt
new file mode 100644
index 0000000..2f284ad
--- /dev/null
+++ b/tutorials/1-1-env-alt.tf.alt
@@ -0,0 +1,17 @@
+resource "bytebase_environment" "test" {
+ resource_id = "test"
+ title = "Test"
+ order = 0
+ protected = false
+}
+
+# Create Production environment
+# depends_on ensures environments are created in sequence
+# This prevents API conflicts when updating the environment list
+resource "bytebase_environment" "prod" {
+ depends_on = [bytebase_environment.test]
+ resource_id = "prod"
+ title = "Prod"
+ order = 1
+ protected = true
+}
\ No newline at end of file
diff --git a/tutorials/1-1-env.tf b/tutorials/1-1-env.tf
new file mode 100644
index 0000000..f651686
--- /dev/null
+++ b/tutorials/1-1-env.tf
@@ -0,0 +1,17 @@
+# Environment Settings
+resource "bytebase_setting" "environments" {
+ name = "settings/ENVIRONMENT"
+
+ environment_setting {
+ environment {
+ id = "test"
+ title = "Test"
+ protected = false
+ }
+ environment {
+ id = "prod"
+ title = "Prod"
+ protected = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/tutorials/1-instances-alt.tf.alt b/tutorials/1-instances-alt.tf.alt
new file mode 100644
index 0000000..ae1362a
--- /dev/null
+++ b/tutorials/1-instances-alt.tf.alt
@@ -0,0 +1,37 @@
+# Built-in Test Instance
+resource "bytebase_instance" "test" {
+ depends_on = [bytebase_environment.test]
+ resource_id = "test-sample-instance"
+ environment = bytebase_environment.test.name
+ title = "Test Sample Instance"
+ engine = "POSTGRES"
+ activation = true
+
+ data_sources {
+ id = "admin data source test-sample-instance"
+ type = "ADMIN"
+ host = "/tmp"
+ port = "8083"
+ username = "bbsample"
+ password = ""
+ }
+}
+
+# Built-in Prod Instance
+resource "bytebase_instance" "prod" {
+ depends_on = [bytebase_environment.prod]
+ resource_id = "prod-sample-instance"
+ environment = bytebase_environment.prod.name
+ title = "Prod Sample Instance"
+ engine = "POSTGRES"
+ activation = true
+
+ data_sources {
+ id = "admin data source prod-sample-instance"
+ type = "ADMIN"
+ host = "/tmp"
+ port = "8084"
+ username = "bbsample"
+ password = ""
+ }
+}
\ No newline at end of file
diff --git a/tutorials/3-1-workspace-profile.tf b/tutorials/3-1-workspace-profile.tf
new file mode 100644
index 0000000..b7800c3
--- /dev/null
+++ b/tutorials/3-1-workspace-profile.tf
@@ -0,0 +1,10 @@
+resource "bytebase_setting" "workspace_profile" {
+ name = "settings/WORKSPACE_PROFILE"
+
+ workspace_profile {
+ disallow_signup = true
+ domains = ["example.com"]
+ enforce_identity_domain = false
+ external_url = "https://valid-just-tadpole.ngrok-free.app"
+ }
+}
\ No newline at end of file
diff --git a/tutorials/3-2-env-setting.tf b/tutorials/3-2-env-setting.tf
new file mode 100644
index 0000000..1ca4398
--- /dev/null
+++ b/tutorials/3-2-env-setting.tf
@@ -0,0 +1,53 @@
+resource "bytebase_policy" "rollout_policy_test" {
+ depends_on = [bytebase_setting.environments]
+ parent = bytebase_setting.environments.environment_setting[0].environment[0].name
+ type = "ROLLOUT_POLICY"
+
+ rollout_policy {
+ automatic = true
+ roles = [
+ "roles/workspaceAdmin",
+ "roles/projectOwner",
+ "roles/LAST_APPROVER",
+ "roles/CREATOR"
+ ]
+ }
+}
+
+resource "bytebase_policy" "rollout_policy_prod" {
+ depends_on = [bytebase_setting.environments]
+ parent = bytebase_setting.environments.environment_setting[0].environment[1].name
+ type = "ROLLOUT_POLICY"
+
+ rollout_policy {
+ automatic = false
+ roles = [
+ "roles/workspaceAdmin",
+ "roles/projectOwner",
+ "roles/LAST_APPROVER",
+ "roles/CREATOR"
+ ]
+ }
+}
+
+resource "bytebase_policy" "disable_copy_data_policy_prod" {
+ depends_on = [bytebase_setting.environments]
+ parent = bytebase_setting.environments.environment_setting[0].environment[1].name
+ type = "DISABLE_COPY_DATA"
+
+ disable_copy_data_policy {
+ enable = true
+ }
+}
+
+resource "bytebase_policy" "data_source_query_policy_prod" {
+ depends_on = [bytebase_setting.environments]
+ parent = bytebase_setting.environments.environment_setting[0].environment[1].name
+ type = "DATA_SOURCE_QUERY"
+
+ data_source_query_policy {
+ restriction = "FALLBACK" # or DISALLOW or RESTRICTION_UNSPECIFIED
+ disallow_ddl = true
+ disallow_dml = true
+ }
+}
\ No newline at end of file
diff --git a/tutorials/3-3-risk.tf b/tutorials/3-3-risk.tf
new file mode 100644
index 0000000..e02d402
--- /dev/null
+++ b/tutorials/3-3-risk.tf
@@ -0,0 +1,15 @@
+resource "bytebase_risk" "dml_moderate" {
+ title = "DML Moderate Risk"
+ source = "DML"
+ level = 200
+ active = true
+ condition = "environment_id == \"prod\" && affected_rows >= 100"
+}
+
+resource "bytebase_risk" "ddl_high" {
+ title = "DDL High Risk"
+ source = "DDL"
+ level = 300
+ active = true
+ condition = "environment_id == \"prod\""
+}
\ No newline at end of file
diff --git a/tutorials/3-4-approval-flow.tf b/tutorials/3-4-approval-flow.tf
new file mode 100644
index 0000000..8af617f
--- /dev/null
+++ b/tutorials/3-4-approval-flow.tf
@@ -0,0 +1,24 @@
+resource "bytebase_setting" "approval_flow" {
+ name = "settings/WORKSPACE_APPROVAL"
+
+ approval_flow {
+ rules {
+ flow {
+ title = "Project Owner → DBA → Admin"
+ description = "Need DBA and workspace admin approval"
+
+ steps { role = "roles/projectOwner" }
+ steps { role = "roles/workspaceDBA" }
+ steps { role = "roles/workspaceAdmin" }
+ }
+ conditions {
+ source = "DML"
+ level = "MODERATE"
+ }
+ conditions {
+ source = "DDL"
+ level = "HIGH"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tutorials/3-settings.tf b/tutorials/3-settings.tf
deleted file mode 100644
index b305811..0000000
--- a/tutorials/3-settings.tf
+++ /dev/null
@@ -1,72 +0,0 @@
-# Environment Settings
-resource "bytebase_setting" "environments" {
- name = "settings/ENVIRONMENT"
-
- environment_setting {
- environment {
- id = "test"
- title = "Test"
- protected = false
- }
- environment {
- id = "prod"
- title = "Prod"
- protected = true
- }
- }
-}
-
-# Step 1: Workspace profile configuration
-resource "bytebase_setting" "workspace_profile" {
- name = "settings/WORKSPACE_PROFILE"
-
- workspace_profile {
- disallow_signup = true
- domains = ["example.com"]
- enforce_identity_domain = false
- external_url = "https://valid-just-tadpole.ngrok-free.app"
- }
-}
-
-# Step 2: Approval flow settings
-resource "bytebase_setting" "approval_flow" {
- name = "settings/WORKSPACE_APPROVAL"
-
- approval_flow {
- rules {
- flow {
- title = "Project Owner → DBA → Admin"
- description = "Need DBA and workspace admin approval"
-
- steps { role = "roles/projectOwner" }
- steps { role = "roles/workspaceDBA" }
- steps { role = "roles/workspaceAdmin" }
- }
- conditions {
- source = "DML"
- level = "MODERATE"
- }
- conditions {
- source = "DDL"
- level = "HIGH"
- }
- }
- }
-}
-
-# Step 3: Risk management policies
-resource "bytebase_risk" "dml_moderate" {
- title = "DML Moderate Risk"
- source = "DML"
- level = 200
- active = true
- condition = "environment_id == \"prod\" && affected_rows >= 100"
-}
-
-resource "bytebase_risk" "ddl_high" {
- title = "DDL High Risk"
- source = "DDL"
- level = 300
- active = true
- condition = "environment_id == \"prod\""
-}
\ No newline at end of file
diff --git a/tutorials/4-sql-review.tf b/tutorials/4-sql-review.tf
new file mode 100644
index 0000000..2a7350b
--- /dev/null
+++ b/tutorials/4-sql-review.tf
@@ -0,0 +1,40 @@
+resource "bytebase_review_config" "sample" {
+ depends_on = [
+ bytebase_setting.environments
+ ]
+
+ resource_id = "review-config-sample"
+ title = "Sample SQL Review Config"
+ enabled = true
+ resources = toset([
+ bytebase_setting.environments.environment_setting[0].environment[1].name
+ ])
+ rules {
+ type = "column.no-null"
+ engine = "POSTGRES"
+ level = "WARNING"
+ }
+ rules {
+ type = "column.required"
+ engine = "POSTGRES"
+ level = "ERROR"
+ payload = "{\"list\":[\"id\",\"created_ts\",\"updated_ts\",\"creator_id\",\"updater_id\"]}"
+ }
+ rules {
+ type = "table.require-pk"
+ engine = "POSTGRES"
+ level = "ERROR"
+ }
+ rules {
+ type = "naming.column"
+ engine = "POSTGRES"
+ level = "ERROR"
+ payload = "{\"format\":\"^[a-z]+(_[a-z]+)*$\",\"maxLength\":64}"
+ }
+ rules {
+ type = "statement.maximum-limit-value"
+ engine = "POSTGRES"
+ level = "ERROR"
+ payload = "{\"number\":1000}"
+ }
+}
\ No newline at end of file
diff --git a/tutorials/4-user-iam.tf b/tutorials/5-user-iam.tf
similarity index 96%
rename from tutorials/4-user-iam.tf
rename to tutorials/5-user-iam.tf
index 7c70718..0c1aa90 100644
--- a/tutorials/4-user-iam.tf
+++ b/tutorials/5-user-iam.tf
@@ -125,7 +125,9 @@ resource "bytebase_iam_policy" "workspace_iam" {
members = [
format("user:%s", bytebase_user.dev1.email),
format("user:%s", bytebase_user.dev2.email),
- format("user:%s", bytebase_user.dev3.email)
+ format("user:%s", bytebase_user.dev3.email),
+ format("user:%s", bytebase_user.qa1.email),
+ format("user:%s", bytebase_user.qa2.email)
]
}
diff --git a/tutorials/6-1-semantic-types.tf b/tutorials/6-1-semantic-types.tf
new file mode 100644
index 0000000..b91d560
--- /dev/null
+++ b/tutorials/6-1-semantic-types.tf
@@ -0,0 +1,40 @@
+resource "bytebase_setting" "semantic_types" {
+ name = "settings/SEMANTIC_TYPES"
+
+ semantic_types {
+ id = "full-mask"
+ title = "Full mask"
+ algorithm {
+ full_mask {
+ substitution = "***"
+ }
+ }
+ }
+
+ semantic_types {
+ id = "date-year-mask"
+ title = "Date year mask"
+ algorithm {
+ range_mask {
+ slices {
+ start = 0
+ end = 4
+ substitution = "****"
+ }
+ }
+ }
+ }
+
+ semantic_types {
+ id = "name-first-letter-only"
+ title = "Name first letter only"
+ algorithm {
+ inner_outer_mask {
+ prefix_len = 1
+ suffix_len = 0
+ substitution = "*"
+ type = "INNER"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tutorials/6-2-classification.tf b/tutorials/6-2-classification.tf
new file mode 100644
index 0000000..d687cbd
--- /dev/null
+++ b/tutorials/6-2-classification.tf
@@ -0,0 +1,45 @@
+resource "bytebase_setting" "classification" {
+ name = "settings/DATA_CLASSIFICATION"
+
+ classification {
+ id = "classification-example"
+ title = "Classification Example"
+
+ levels {
+ id = "1"
+ title = "Level 1"
+ }
+ levels {
+ id = "2"
+ title = "Level 2"
+ }
+
+ classifications {
+ id = "1"
+ title = "Basic"
+ }
+
+ classifications {
+ id = "1-1"
+ title = "User basic"
+ level = "1"
+ }
+
+ classifications {
+ id = "1-2"
+ title = "User contact info"
+ level = "2"
+ }
+
+ classifications {
+ id = "2"
+ title = "Employment"
+ }
+
+ classifications {
+ id = "2-1"
+ title = "Employment info"
+ level = "2"
+ }
+ }
+}
\ No newline at end of file
diff --git a/tutorials/6-3-global-data-masking.tf b/tutorials/6-3-global-data-masking.tf
new file mode 100644
index 0000000..54031a4
--- /dev/null
+++ b/tutorials/6-3-global-data-masking.tf
@@ -0,0 +1,32 @@
+resource "bytebase_policy" "global_masking_policy" {
+ depends_on = [
+ bytebase_instance.prod,
+ bytebase_setting.environments
+ ]
+
+ parent = "workspaces/-"
+ type = "MASKING_RULE"
+ enforce = true
+ inherit_from_parent = false
+
+ global_masking_policy {
+
+ rules {
+ condition = "column_name == \"birth_date\""
+ id = "birth-date-mask"
+ semantic_type = "date-year-mask"
+ }
+
+ rules {
+ condition = "column_name == \"last_name\""
+ id = "last-name-first-letter-only"
+ semantic_type = "name-first-letter-only"
+ }
+
+ rules {
+ condition = "classification_level in [\"2\"]"
+ id = "classification-level-2"
+ semantic_type = "full-mask"
+ }
+ }
+}
\ No newline at end of file
diff --git a/tutorials/6-4-database-masking.tf b/tutorials/6-4-database-masking.tf
new file mode 100644
index 0000000..4d646ae
--- /dev/null
+++ b/tutorials/6-4-database-masking.tf
@@ -0,0 +1,28 @@
+resource "bytebase_database" "database" {
+ depends_on = [
+ bytebase_instance.prod,
+ bytebase_project.project-two,
+ bytebase_setting.environments
+ ]
+
+ name = "instances/prod-sample-instance/databases/hr_prod"
+ project = bytebase_project.project-two.name
+ environment = bytebase_setting.environments.environment_setting[0].environment[1].name
+
+ catalog {
+ schemas {
+ name = "public"
+ tables {
+ name = "salary"
+ columns {
+ name = "from_date"
+ semantic_type = "date-year-mask"
+ }
+ columns {
+ name = "amount"
+ classification = "2-1"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tutorials/6-5-masking-exception.tf b/tutorials/6-5-masking-exception.tf
new file mode 100644
index 0000000..20803ae
--- /dev/null
+++ b/tutorials/6-5-masking-exception.tf
@@ -0,0 +1,28 @@
+resource "bytebase_policy" "masking_exception_policy" {
+ depends_on = [
+ bytebase_project.project-two,
+ bytebase_instance.prod
+ ]
+
+ parent = bytebase_project.project-two.name
+ type = "MASKING_EXCEPTION"
+ enforce = true
+ inherit_from_parent = false
+
+ masking_exception_policy {
+ exceptions {
+ database = "instances/prod-sample-instance/databases/hr_prod"
+ table = "employee"
+ column = "birth_date"
+ member = "user:admin@example.com"
+ action = "QUERY"
+ }
+ exceptions {
+ database = "instances/prod-sample-instance/databases/hr_prod"
+ table = "employee"
+ column = "last_name"
+ member = "user:admin@example.com"
+ action = "EXPORT"
+ }
+ }
+}
\ No newline at end of file