Skip to content

Commit 82a89ac

Browse files
committed
chore: support raw_expression
1 parent 4d6c59f commit 82a89ac

File tree

6 files changed

+98
-42
lines changed

6 files changed

+98
-42
lines changed

docs/data-sources/policy.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,15 @@ Optional:
8787

8888
Required:
8989

90-
- `action` (String)
91-
- `member` (String) The member in user:{email} or group:{email} format.
90+
- `actions` (Set of String)
91+
- `members` (Set of String)
9292

9393
Optional:
9494

95-
- `column` (String)
95+
- `columns` (Set of String)
9696
- `database` (String) The database full name in instances/{instance resource id}/databases/{database name} format
9797
- `expire_timestamp` (String) The expiration timestamp in YYYY-MM-DDThh:mm:ss.000Z format
98+
- `raw_expression` (String) The raw CEL expression. We will use it as the masking exception and ignore the "database"/"schema"/"table"/"columns"/"expire_timestamp" fields if you provide the raw expression.
9899
- `reason` (String) The reason for the masking exemption
99100
- `schema` (String)
100101
- `table` (String)

docs/data-sources/policy_list.md

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,34 @@ The policy data source list.
2929

3030
Read-Only:
3131

32+
- `data_source_query_policy` (List of Object) (see [below for nested schema](#nestedobjatt--policies--data_source_query_policy))
33+
- `disable_copy_data_policy` (List of Object) (see [below for nested schema](#nestedobjatt--policies--disable_copy_data_policy))
3234
- `enforce` (Boolean)
3335
- `global_masking_policy` (List of Object) (see [below for nested schema](#nestedobjatt--policies--global_masking_policy))
3436
- `inherit_from_parent` (Boolean)
3537
- `masking_exception_policy` (List of Object) (see [below for nested schema](#nestedobjatt--policies--masking_exception_policy))
3638
- `name` (String)
39+
- `rollout_policy` (List of Object) (see [below for nested schema](#nestedobjatt--policies--rollout_policy))
3740
- `type` (String)
3841

42+
<a id="nestedobjatt--policies--data_source_query_policy"></a>
43+
### Nested Schema for `policies.data_source_query_policy`
44+
45+
Read-Only:
46+
47+
- `disallow_ddl` (Boolean)
48+
- `disallow_dml` (Boolean)
49+
- `restriction` (String)
50+
51+
52+
<a id="nestedobjatt--policies--disable_copy_data_policy"></a>
53+
### Nested Schema for `policies.disable_copy_data_policy`
54+
55+
Read-Only:
56+
57+
- `enable` (Boolean)
58+
59+
3960
<a id="nestedobjatt--policies--global_masking_policy"></a>
4061
### Nested Schema for `policies.global_masking_policy`
4162

@@ -67,13 +88,24 @@ Read-Only:
6788

6889
Read-Only:
6990

70-
- `action` (String)
71-
- `column` (String)
91+
- `actions` (Set of String)
92+
- `columns` (Set of String)
7293
- `database` (String)
7394
- `expire_timestamp` (String)
74-
- `member` (String)
95+
- `members` (Set of String)
96+
- `raw_expression` (String)
7597
- `reason` (String)
7698
- `schema` (String)
7799
- `table` (String)
78100

79101

102+
103+
<a id="nestedobjatt--policies--rollout_policy"></a>
104+
### Nested Schema for `policies.rollout_policy`
105+
106+
Read-Only:
107+
108+
- `automatic` (Boolean)
109+
- `roles` (Set of String)
110+
111+

docs/resources/policy.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,15 @@ Optional:
8787

8888
Required:
8989

90-
- `action` (String)
91-
- `member` (String) The member in user:{email} or group:{email} format.
90+
- `actions` (Set of String)
91+
- `members` (Set of String)
9292

9393
Optional:
9494

95-
- `column` (String)
95+
- `columns` (Set of String)
9696
- `database` (String) The database full name in instances/{instance resource id}/databases/{database name} format
9797
- `expire_timestamp` (String) The expiration timestamp in YYYY-MM-DDThh:mm:ss.000Z format
98+
- `raw_expression` (String) The raw CEL expression. We will use it as the masking exception and ignore the "database"/"schema"/"table"/"columns"/"expire_timestamp" fields if you provide the raw expression.
9899
- `reason` (String) The reason for the masking exemption
99100
- `schema` (String)
100101
- `table` (String)

examples/setup/data_masking.tf

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,16 @@ resource "bytebase_policy" "masking_exception_policy" {
131131
format("user:%s", bytebase_user.workspace_dba.email),
132132
]
133133
actions = ["EXPORT"]
134-
reason = "Grant access"
134+
reason = "Grant export access"
135+
}
136+
137+
exceptions {
138+
members = [
139+
format("user:%s", bytebase_user.project_developer.email),
140+
]
141+
actions = ["QUERY"]
142+
reason = "Grant query access"
143+
raw_expression = "resource.instance_id == \"test-sample-instance\" && resource.database_name == \"employee\" && resource.table_name == \"employee\" && resource.column_name in [\"first_name\", \"last_name\", \"gender\"]"
135144
}
136145
}
137146
}

provider/data_source_policy.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ func getMaskingExceptionPolicySchema(computed bool) *schema.Schema {
159159
Optional: true,
160160
Description: "The expiration timestamp in YYYY-MM-DDThh:mm:ss.000Z format",
161161
},
162+
"raw_expression": {
163+
Type: schema.TypeString,
164+
Computed: computed,
165+
Optional: true,
166+
Description: `The raw CEL expression. We will use it as the masking exception and ignore the "database"/"schema"/"table"/"columns"/"expire_timestamp" fields if you provide the raw expression.`,
167+
},
162168
},
163169
},
164170
Set: exceptionHash,
@@ -477,9 +483,10 @@ func flattenMaskingExceptionPolicy(p *v1pb.MaskingExceptionPolicy) ([]interface{
477483

478484
for _, combine := range exceptionMap {
479485
raw := map[string]interface{}{
480-
"members": schema.NewSet(schema.HashString, combine.members),
481-
"actions": schema.NewSet(schema.HashString, combine.actions),
482-
"reason": combine.reason,
486+
"members": schema.NewSet(schema.HashString, combine.members),
487+
"actions": schema.NewSet(schema.HashString, combine.actions),
488+
"reason": combine.reason,
489+
"raw_expression": combine.expression,
483490
}
484491

485492
expressions := strings.Split(combine.expression, " && ")

provider/resource_policy.go

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -351,40 +351,46 @@ func convertToV1Exceptions(rawSchema interface{}) ([]*v1pb.MaskingExceptionPolic
351351
rawException := rawSchema.(map[string]interface{})
352352

353353
expressions := []string{}
354-
databaseFullName := rawException["database"].(string)
355-
if databaseFullName != "" {
356-
instanceID, databaseName, err := internal.GetInstanceDatabaseID(databaseFullName)
357-
if err != nil {
358-
return nil, errors.Wrapf(err, "invalid database full name: %v", databaseFullName)
359-
}
360-
expressions = append(
361-
expressions,
362-
fmt.Sprintf(`resource.instance_id == "%s"`, instanceID),
363-
fmt.Sprintf(`resource.database_name == "%s"`, databaseName),
364-
)
365-
366-
if schema, ok := rawException["schema"].(string); ok && schema != "" {
367-
expressions = append(expressions, fmt.Sprintf(`resource.schema_name == "%s"`, schema))
368-
}
369-
if table, ok := rawException["table"].(string); ok && table != "" {
370-
expressions = append(expressions, fmt.Sprintf(`resource.table_name == "%s"`, table))
371-
}
354+
rawExpression := rawException["raw_expression"].(string)
355+
356+
if rawExpression != "" {
357+
expressions = append(expressions, rawExpression)
358+
} else {
359+
databaseFullName := rawException["database"].(string)
360+
if databaseFullName != "" {
361+
instanceID, databaseName, err := internal.GetInstanceDatabaseID(databaseFullName)
362+
if err != nil {
363+
return nil, errors.Wrapf(err, "invalid database full name: %v", databaseFullName)
364+
}
365+
expressions = append(
366+
expressions,
367+
fmt.Sprintf(`resource.instance_id == "%s"`, instanceID),
368+
fmt.Sprintf(`resource.database_name == "%s"`, databaseName),
369+
)
370+
371+
if schema, ok := rawException["schema"].(string); ok && schema != "" {
372+
expressions = append(expressions, fmt.Sprintf(`resource.schema_name == "%s"`, schema))
373+
}
374+
if table, ok := rawException["table"].(string); ok && table != "" {
375+
expressions = append(expressions, fmt.Sprintf(`resource.table_name == "%s"`, table))
376+
}
372377

373-
if rawColumns, ok := rawException["columns"].(*schema.Set); ok && rawColumns.Len() > 0 {
374-
columnNames := []string{}
375-
for _, column := range rawColumns.List() {
376-
columnNames = append(columnNames, fmt.Sprintf(`"%s"`, column.(string)))
378+
if rawColumns, ok := rawException["columns"].(*schema.Set); ok && rawColumns.Len() > 0 {
379+
columnNames := []string{}
380+
for _, column := range rawColumns.List() {
381+
columnNames = append(columnNames, fmt.Sprintf(`"%s"`, column.(string)))
382+
}
383+
expressions = append(expressions, fmt.Sprintf(`resource.column_name in [%s]`, strings.Join(columnNames, ", ")))
377384
}
378-
expressions = append(expressions, fmt.Sprintf(`resource.column_name in [%s]`, strings.Join(columnNames, ", ")))
379385
}
380-
}
381386

382-
if expire, ok := rawException["expire_timestamp"].(string); ok && expire != "" {
383-
formattedTime, err := time.Parse(time.RFC3339, expire)
384-
if err != nil {
385-
return nil, errors.Wrapf(err, "invalid time: %v", expire)
387+
if expire, ok := rawException["expire_timestamp"].(string); ok && expire != "" {
388+
formattedTime, err := time.Parse(time.RFC3339, expire)
389+
if err != nil {
390+
return nil, errors.Wrapf(err, "invalid time: %v", expire)
391+
}
392+
expressions = append(expressions, fmt.Sprintf(`request.time < timestamp("%s")`, formattedTime.Format(time.RFC3339)))
386393
}
387-
expressions = append(expressions, fmt.Sprintf(`request.time < timestamp("%s")`, formattedTime.Format(time.RFC3339)))
388394
}
389395

390396
exceptions := []*v1pb.MaskingExceptionPolicy_MaskingException{}

0 commit comments

Comments
 (0)