Skip to content

Commit

Permalink
[fix](polixy)support drop policy for user or role (apache#29488)
Browse files Browse the repository at this point in the history
  • Loading branch information
zddr authored and pull[bot] committed Feb 26, 2024
1 parent faa5417 commit abf5aac
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Grammar:

1. Drop row policy
```sql
DROP ROW POLICY test_row_policy_1 on table1 [FOR user];
DROP ROW POLICY test_row_policy_1 on table1 [FOR user| ROLE role];
```

2. Drop storage policy
Expand All @@ -61,8 +61,14 @@ DROP STORAGE POLICY policy_name1
```sql
DROP ROW POLICY test_row_policy_1 on table1 for test
```

3. Drop the row policy for table1 using by role1

3. Drop the storage policy named policy_name1
```sql
DROP ROW POLICY test_row_policy_1 on table1 for role role1
```

4. Drop the storage policy named policy_name1
```sql
DROP STORAGE POLICY policy_name1
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ SHOW ROW POLICY
View the row security policy under the current DB

```sql
SHOW ROW POLICY [FOR user]
SHOW ROW POLICY [FOR user| ROLE role]
```

### Example
Expand Down Expand Up @@ -68,7 +68,19 @@ SHOW ROW POLICY [FOR user]
1 row in set (0.01 sec)
```

3. demonstrate data migration strategies
3. specify role name query

```sql
mysql> SHOW ROW POLICY for role role1;
+------------+--------+-----------+------+-------------+----------------+------+-------+----------------------------------------------------------------------------------+
| PolicyName | DbName | TableName | Type | FilterType | WherePredicate | User | Role | OriginStmt |
+------------+--------+-----------+------+-------------+----------------+------+-------+----------------------------------------------------------------------------------+
| zdtest1 | zd | user | ROW | RESTRICTIVE | `user_id` = 1 | NULL | role1 | create row policy zdtest1 on user as restrictive to role role1 using (user_id=1) |
+------------+--------+-----------+------+-------------+----------------+------+-------+----------------------------------------------------------------------------------+
1 row in set (0.01 sec)
```

4. demonstrate data migration strategies
```sql
mysql> SHOW STORAGE POLICY;
+---------------------+---------+-----------------------+---------------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ DROP POLICY

1. 删除行安全策略
```sql
DROP ROW POLICY test_row_policy_1 on table1 [FOR user];
DROP ROW POLICY test_row_policy_1 on table1 [FOR user| ROLE role];
```

2. 删除存储策略
Expand All @@ -62,7 +62,13 @@ DROP STORAGE POLICY policy_name1
DROP ROW POLICY test_row_policy_1 on table1 for test
```

3. 删除名字为policy_name1的存储策略
3. 删除 table1 作用于 role1 的 test_row_policy_1 行安全策略

```sql
DROP ROW POLICY test_row_policy_1 on table1 for role role1
```

4. 删除名字为policy_name1的存储策略
```sql
DROP STORAGE POLICY policy_name1
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ SHOW ROW POLICY
语法:

```sql
SHOW ROW POLICY [FOR user]
SHOW ROW POLICY [FOR user| ROLE role]
```

### Example
Expand Down Expand Up @@ -70,7 +70,19 @@ SHOW ROW POLICY [FOR user]
1 row in set (0.01 sec)
```

3. 展示数据迁移策略
3. 指定角色名查询

```sql
mysql> SHOW ROW POLICY for role role1;
+------------+--------+-----------+------+-------------+----------------+------+-------+----------------------------------------------------------------------------------+
| PolicyName | DbName | TableName | Type | FilterType | WherePredicate | User | Role | OriginStmt |
+------------+--------+-----------+------+-------------+----------------+------+-------+----------------------------------------------------------------------------------+
| zdtest1 | zd | user | ROW | RESTRICTIVE | `user_id` = 1 | NULL | role1 | create row policy zdtest1 on user as restrictive to role role1 using (user_id=1) |
+------------+--------+-----------+------+-------------+----------------+------+-------+----------------------------------------------------------------------------------+
1 row in set (0.01 sec)
```

4. 展示数据迁移策略
```sql
mysql> SHOW STORAGE POLICY;
+---------------------+---------+-----------------------+---------------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Expand Down
16 changes: 12 additions & 4 deletions fe/fe-core/src/main/cup/sql_parser.cup
Original file line number Diff line number Diff line change
Expand Up @@ -3023,13 +3023,21 @@ drop_stmt ::=
{:
RESULT = new DropSqlBlockRuleStmt(ifExists, ruleNames);
:}
| KW_DROP KW_ROW KW_POLICY opt_if_exists:ifExists ident:policyName
| KW_DROP KW_ROW KW_POLICY opt_if_exists:ifExists ident:policyName KW_ON table_name:tbl
{:
RESULT = new DropPolicyStmt(PolicyTypeEnum.ROW, ifExists, policyName);
RESULT = new DropPolicyStmt(PolicyTypeEnum.ROW, ifExists, policyName, tbl, null, null);
:}
| KW_DROP KW_ROW KW_POLICY opt_if_exists:ifExists ident:policyName KW_ON table_name:tbl KW_FOR user_identity:user
{:
RESULT = new DropPolicyStmt(PolicyTypeEnum.ROW, ifExists, policyName, tbl, user, null);
:}
| KW_DROP KW_ROW KW_POLICY opt_if_exists:ifExists ident:policyName KW_ON table_name:tbl KW_FOR KW_ROLE ident:role
{:
RESULT = new DropPolicyStmt(PolicyTypeEnum.ROW, ifExists, policyName, tbl, null, role);
:}
| KW_DROP KW_STORAGE KW_POLICY opt_if_exists:ifExists ident:policyName
{:
RESULT = new DropPolicyStmt(PolicyTypeEnum.STORAGE, ifExists, policyName);
RESULT = new DropPolicyStmt(PolicyTypeEnum.STORAGE, ifExists, policyName, null, null, null);
:}
/* statistics */
| KW_DROP KW_STATS table_name:tbl opt_col_list:cols
Expand Down Expand Up @@ -3852,7 +3860,7 @@ show_stmt ::=
{:
RESULT = new ShowPolicyStmt(PolicyTypeEnum.ROW, user, null);
:}
| KW_SHOW KW_ROW KW_POLICY KW_FOR KW_ROLE STRING_LITERAL:role
| KW_SHOW KW_ROW KW_POLICY KW_FOR KW_ROLE ident:role
{:
RESULT = new ShowPolicyStmt(PolicyTypeEnum.ROW, null, role);
:}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

/**
* Drop policy statement.
* syntax:
* DROP [ROW] POLICY [IF EXISTS] test_row_policy
* DROP [ROW] POLICY [IF EXISTS] test_row_policy ON test_table [FOR user|ROLE role]
**/
@AllArgsConstructor
public class DropPolicyStmt extends DdlStmt {
Expand All @@ -45,9 +46,28 @@ public class DropPolicyStmt extends DdlStmt {
@Getter
private final String policyName;

@Getter
private final TableName tableName;

@Getter
private final UserIdentity user;

@Getter
private final String roleName;

@Override
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
switch (type) {
case STORAGE:
break;
case ROW:
default:
tableName.analyze(analyzer);
if (user != null) {
user.analyze();
}
}
// check auth
if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
Expand All @@ -62,6 +82,19 @@ public String toSql() {
sb.append("IF EXISTS ");
}
sb.append(policyName);
switch (type) {
case STORAGE:
break;
case ROW:
default:
sb.append(" ON ").append(tableName.toSql());
if (user != null) {
sb.append(" FOR ").append(user.getQualifiedUser());
}
if (StringUtils.isEmpty(roleName)) {
sb.append(" FOR ROLE ").append(roleName);
}
}
return sb.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@
package org.apache.doris.policy;

import org.apache.doris.analysis.DropPolicyStmt;
import org.apache.doris.analysis.UserIdentity;
import org.apache.doris.catalog.Database;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.Table;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.io.Text;
import org.apache.doris.common.io.Writable;
import org.apache.doris.persist.gson.GsonUtils;
import org.apache.doris.qe.ConnectContext;

import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
Expand All @@ -37,18 +42,44 @@
@AllArgsConstructor
@Getter
public class DropPolicyLog implements Writable {

@SerializedName(value = "dbId")
private long dbId;

@SerializedName(value = "tableId")
private long tableId;

@SerializedName(value = "type")
private PolicyTypeEnum type;

@SerializedName(value = "policyName")
private String policyName;

@SerializedName(value = "user")
private UserIdentity user;

@SerializedName(value = "roleName")
private String roleName;

/**
* Generate delete logs through stmt.
**/
public static DropPolicyLog fromDropStmt(DropPolicyStmt stmt) throws AnalysisException {
return new DropPolicyLog(stmt.getType(), stmt.getPolicyName());
switch (stmt.getType()) {
case STORAGE:
return new DropPolicyLog(-1, -1, stmt.getType(), stmt.getPolicyName(), null, null);
case ROW:
String curDb = stmt.getTableName().getDb();
if (curDb == null) {
curDb = ConnectContext.get().getDatabase();
}
Database db = Env.getCurrentInternalCatalog().getDbOrAnalysisException(curDb);
Table table = db.getTableOrAnalysisException(stmt.getTableName().getTbl());
return new DropPolicyLog(db.getId(), table.getId(), stmt.getType(),
stmt.getPolicyName(), stmt.getUser(), stmt.getRoleName());
default:
throw new AnalysisException("Invalid policy type: " + stmt.getType().name());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ public boolean matchPolicy(Policy checkedPolicyCondition) {
rowPolicy.getPolicyName(), rowPolicy.getUser(), rowPolicy.getRoleName());
}

@Override
public boolean matchPolicy(DropPolicyLog checkedDropPolicyLogCondition) {
return checkMatched(checkedDropPolicyLogCondition.getDbId(), checkedDropPolicyLogCondition.getTableId(),
checkedDropPolicyLogCondition.getType(), checkedDropPolicyLogCondition.getPolicyName(),
checkedDropPolicyLogCondition.getUser(), checkedDropPolicyLogCondition.getRoleName());
}

@Override
public boolean isInvalid() {
return (wherePredicate == null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ protected void runBeforeAll() throws Exception {
user.analyze();
CreateUserStmt createUserStmt = new CreateUserStmt(new UserDesc(user));
Env.getCurrentEnv().getAuth().createUser(createUserStmt);
List<AccessPrivilegeWithCols> privileges = Lists.newArrayList(new AccessPrivilegeWithCols(AccessPrivilege.ADMIN_PRIV));
List<AccessPrivilegeWithCols> privileges = Lists
.newArrayList(new AccessPrivilegeWithCols(AccessPrivilege.ADMIN_PRIV));
TablePattern tablePattern = new TablePattern("*", "*", "*");
tablePattern.analyze();
GrantStmt grantStmt = new GrantStmt(user, null, tablePattern, privileges);
Expand All @@ -101,7 +102,8 @@ protected void runBeforeAll() throws Exception {

@Test
public void checkUser() throws AnalysisException, org.apache.doris.common.AnalysisException {
LogicalRelation relation = new LogicalOlapScan(StatementScopeIdGenerator.newRelationId(), olapTable, Arrays.asList(fullDbName));
LogicalRelation relation = new LogicalOlapScan(StatementScopeIdGenerator.newRelationId(), olapTable,
Arrays.asList(fullDbName));
LogicalCheckPolicy<LogicalRelation> checkPolicy = new LogicalCheckPolicy<>(relation);

useUser("root");
Expand All @@ -116,7 +118,8 @@ public void checkUser() throws AnalysisException, org.apache.doris.common.Analys
@Test
public void checkNoPolicy() throws org.apache.doris.common.AnalysisException {
useUser(userName);
LogicalRelation relation = new LogicalOlapScan(StatementScopeIdGenerator.newRelationId(), olapTable, Arrays.asList(fullDbName));
LogicalRelation relation = new LogicalOlapScan(StatementScopeIdGenerator.newRelationId(), olapTable,
Arrays.asList(fullDbName));
LogicalCheckPolicy<LogicalRelation> checkPolicy = new LogicalCheckPolicy<>(relation);
Plan plan = PlanRewriter.bottomUpRewrite(checkPolicy, connectContext, new CheckPolicy());
Assertions.assertEquals(plan, relation);
Expand All @@ -125,7 +128,8 @@ public void checkNoPolicy() throws org.apache.doris.common.AnalysisException {
@Test
public void checkOnePolicy() throws Exception {
useUser(userName);
LogicalRelation relation = new LogicalOlapScan(StatementScopeIdGenerator.newRelationId(), olapTable, Arrays.asList(fullDbName));
LogicalRelation relation = new LogicalOlapScan(StatementScopeIdGenerator.newRelationId(), olapTable,
Arrays.asList(fullDbName));
LogicalCheckPolicy<LogicalRelation> checkPolicy = new LogicalCheckPolicy<>(relation);
connectContext.getSessionVariable().setEnableNereidsPlanner(true);
createPolicy("CREATE ROW POLICY "
Expand All @@ -143,6 +147,9 @@ public void checkOnePolicy() throws Exception {
Assertions.assertTrue(ImmutableList.copyOf(filter.getConjuncts()).get(0) instanceof EqualTo);
Assertions.assertTrue(filter.getConjuncts().toString().contains("'k1 = 1"));

dropPolicy("DROP ROW POLICY " + policyName);
dropPolicy("DROP ROW POLICY "
+ policyName
+ " ON "
+ tableName);
}
}
Loading

0 comments on commit abf5aac

Please sign in to comment.