Skip to content

Commit d1ca670

Browse files
committed
Add schema table workload_group_privileges
1 parent 9741887 commit d1ca670

File tree

16 files changed

+432
-2
lines changed

16 files changed

+432
-2
lines changed

be/src/exec/schema_scanner.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "exec/schema_scanner/schema_user_scanner.h"
4949
#include "exec/schema_scanner/schema_variables_scanner.h"
5050
#include "exec/schema_scanner/schema_views_scanner.h"
51+
#include "exec/schema_scanner/schema_workload_group_privileges.h"
5152
#include "exec/schema_scanner/schema_workload_groups_scanner.h"
5253
#include "exec/schema_scanner/schema_workload_sched_policy_scanner.h"
5354
#include "olap/hll.h"
@@ -170,6 +171,8 @@ std::unique_ptr<SchemaScanner> SchemaScanner::create(TSchemaTableType::type type
170171
return SchemaWorkloadSchedulePolicyScanner::create_unique();
171172
case TSchemaTableType::SCH_TABLE_OPTIONS:
172173
return SchemaTableOptionsScanner::create_unique();
174+
case TSchemaTableType::SCH_WORKLOAD_GROUP_PRIVILEGES:
175+
return SchemaWorkloadGroupPrivilegesScanner::create_unique();
173176
default:
174177
return SchemaDummyScanner::create_unique();
175178
break;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#include "exec/schema_scanner/schema_workload_group_privileges.h"
19+
20+
#include "runtime/client_cache.h"
21+
#include "runtime/exec_env.h"
22+
#include "runtime/runtime_state.h"
23+
#include "util/thrift_rpc_helper.h"
24+
#include "vec/common/string_ref.h"
25+
#include "vec/core/block.h"
26+
#include "vec/data_types/data_type_factory.hpp"
27+
28+
namespace doris {
29+
std::vector<SchemaScanner::ColumnDesc> SchemaWorkloadGroupPrivilegesScanner::_s_tbls_columns = {
30+
{"GRANTEE", TYPE_VARCHAR, sizeof(StringRef), true},
31+
{"WORKLOAD_GROUP_NAME", TYPE_VARCHAR, sizeof(StringRef), true},
32+
{"PRIVILEGE_TYPE", TYPE_VARCHAR, sizeof(StringRef), true},
33+
{"IS_GRANTABLE", TYPE_VARCHAR, sizeof(StringRef), true},
34+
};
35+
36+
SchemaWorkloadGroupPrivilegesScanner::SchemaWorkloadGroupPrivilegesScanner()
37+
: SchemaScanner(_s_tbls_columns, TSchemaTableType::SCH_WORKLOAD_GROUPS) {}
38+
39+
SchemaWorkloadGroupPrivilegesScanner::~SchemaWorkloadGroupPrivilegesScanner() {}
40+
41+
Status SchemaWorkloadGroupPrivilegesScanner::start(RuntimeState* state) {
42+
_block_rows_limit = state->batch_size();
43+
_rpc_timeout = state->execution_timeout() * 1000;
44+
return Status::OK();
45+
}
46+
47+
Status SchemaWorkloadGroupPrivilegesScanner::_get_workload_group_privs_block_from_fe() {
48+
TNetworkAddress master_addr = ExecEnv::GetInstance()->master_info()->network_address;
49+
50+
TSchemaTableRequestParams schema_table_request_params;
51+
for (int i = 0; i < _s_tbls_columns.size(); i++) {
52+
schema_table_request_params.__isset.columns_name = true;
53+
schema_table_request_params.columns_name.emplace_back(_s_tbls_columns[i].name);
54+
}
55+
schema_table_request_params.__set_current_user_ident(*_param->common_param->current_user_ident);
56+
57+
TFetchSchemaTableDataRequest request;
58+
request.__set_schema_table_name(TSchemaTableName::WORKLOAD_GROUP_PRIVILEGES);
59+
request.__set_schema_table_params(schema_table_request_params);
60+
61+
TFetchSchemaTableDataResult result;
62+
63+
RETURN_IF_ERROR(ThriftRpcHelper::rpc<FrontendServiceClient>(
64+
master_addr.hostname, master_addr.port,
65+
[&request, &result](FrontendServiceConnection& client) {
66+
client->fetchSchemaTableData(result, request);
67+
},
68+
_rpc_timeout));
69+
70+
Status status(Status::create(result.status));
71+
if (!status.ok()) {
72+
LOG(WARNING) << "fetch workload group privileges from FE failed, errmsg=" << status;
73+
return status;
74+
}
75+
std::vector<TRow> result_data = result.data_batch;
76+
77+
_workload_groups_privs_block = vectorized::Block::create_unique();
78+
for (int i = 0; i < _s_tbls_columns.size(); ++i) {
79+
TypeDescriptor descriptor(_s_tbls_columns[i].type);
80+
auto data_type = vectorized::DataTypeFactory::instance().create_data_type(descriptor, true);
81+
_workload_groups_privs_block->insert(vectorized::ColumnWithTypeAndName(
82+
data_type->create_column(), data_type, _s_tbls_columns[i].name));
83+
}
84+
85+
if (result_data.size() > 0) {
86+
int col_size = result_data[0].column_value.size();
87+
if (col_size != _s_tbls_columns.size()) {
88+
return Status::InternalError<false>(
89+
"workload group privileges schema is not match for FE and BE");
90+
}
91+
}
92+
93+
_workload_groups_privs_block->reserve(result_data.size());
94+
95+
for (int i = 0; i < result_data.size(); i++) {
96+
TRow row = result_data[i];
97+
98+
for (int j = 0; j < _s_tbls_columns.size(); j++) {
99+
RETURN_IF_ERROR(insert_block_column(row.column_value[j], j,
100+
_workload_groups_privs_block.get(),
101+
_s_tbls_columns[j].type));
102+
}
103+
}
104+
return Status::OK();
105+
}
106+
107+
Status SchemaWorkloadGroupPrivilegesScanner::get_next_block(vectorized::Block* block, bool* eos) {
108+
if (!_is_init) {
109+
return Status::InternalError("Used before initialized.");
110+
}
111+
112+
if (nullptr == block || nullptr == eos) {
113+
return Status::InternalError("input pointer is nullptr.");
114+
}
115+
116+
if (_workload_groups_privs_block == nullptr) {
117+
RETURN_IF_ERROR(_get_workload_group_privs_block_from_fe());
118+
_total_rows = _workload_groups_privs_block->rows();
119+
}
120+
121+
if (_row_idx == _total_rows) {
122+
*eos = true;
123+
return Status::OK();
124+
}
125+
126+
int current_batch_rows = std::min(_block_rows_limit, _total_rows - _row_idx);
127+
vectorized::MutableBlock mblock = vectorized::MutableBlock::build_mutable_block(block);
128+
RETURN_IF_ERROR(
129+
mblock.add_rows(_workload_groups_privs_block.get(), _row_idx, current_batch_rows));
130+
_row_idx += current_batch_rows;
131+
132+
*eos = _row_idx == _total_rows;
133+
return Status::OK();
134+
}
135+
136+
} // namespace doris
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
#pragma once
19+
20+
#include <vector>
21+
22+
#include "common/status.h"
23+
#include "exec/schema_scanner.h"
24+
25+
namespace doris {
26+
class RuntimeState;
27+
namespace vectorized {
28+
class Block;
29+
} // namespace vectorized
30+
31+
class SchemaWorkloadGroupPrivilegesScanner : public SchemaScanner {
32+
ENABLE_FACTORY_CREATOR(SchemaWorkloadGroupPrivilegesScanner);
33+
34+
public:
35+
SchemaWorkloadGroupPrivilegesScanner();
36+
~SchemaWorkloadGroupPrivilegesScanner() override;
37+
38+
Status start(RuntimeState* state) override;
39+
Status get_next_block(vectorized::Block* block, bool* eos) override;
40+
41+
static std::vector<SchemaScanner::ColumnDesc> _s_tbls_columns;
42+
43+
private:
44+
Status _get_workload_group_privs_block_from_fe();
45+
46+
int _block_rows_limit = 4096;
47+
int _row_idx = 0;
48+
int _total_rows = 0;
49+
std::unique_ptr<vectorized::Block> _workload_groups_privs_block = nullptr;
50+
int _rpc_timeout = 3000;
51+
};
52+
}; // namespace doris

fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ public enum SchemaTableType {
7878
SCH_WORKLOAD_POLICY("WORKLOAD_POLICY", "WORKLOAD_POLICY",
7979
TSchemaTableType.SCH_WORKLOAD_POLICY),
8080
SCH_TABLE_OPTIONS("TABLE_OPTIONS", "TABLE_OPTIONS",
81-
TSchemaTableType.SCH_TABLE_OPTIONS);
81+
TSchemaTableType.SCH_TABLE_OPTIONS),
82+
SCH_WORKLOAD_GROUP_PRIVILEGES("WORKLOAD_GROUP_PRIVILEGES",
83+
"WORKLOAD_GROUP_PRIVILEGES", TSchemaTableType.SCH_WORKLOAD_GROUP_PRIVILEGES);
8284

8385
private static final String dbName = "INFORMATION_SCHEMA";
8486
private static SelectList fullSelectLists;

fe/fe-core/src/main/java/org/apache/doris/catalog/SchemaTable.java

+8
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,14 @@ public class SchemaTable extends Table {
532532
.column("PARTITION_NUM", ScalarType.createType(PrimitiveType.INT))
533533
.column("PROPERTIES", ScalarType.createStringType())
534534
.build()))
535+
.put("workload_group_privileges",
536+
new SchemaTable(SystemIdGenerator.getNextId(), "workload_group_privileges", TableType.SCHEMA,
537+
builder().column("GRANTEE", ScalarType.createVarchar(NAME_CHAR_LEN))
538+
.column("WORKLOAD_GROUP_NAME", ScalarType.createVarchar(256))
539+
.column("PRIVILEGE_TYPE", ScalarType.createVarchar(PRIVILEGE_TYPE_LEN))
540+
.column("IS_GRANTABLE", ScalarType.createVarchar(IS_GRANTABLE_LEN))
541+
.build())
542+
)
535543
.build();
536544

537545
protected SchemaTable(long id, String name, TableType type, List<Column> baseSchema) {

fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java

+53
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
import java.io.DataOutput;
8383
import java.io.IOException;
8484
import java.util.Collections;
85+
import java.util.HashSet;
8586
import java.util.List;
8687
import java.util.Map;
8788
import java.util.Map.Entry;
@@ -1407,6 +1408,58 @@ private void getUserAuthInfo(List<List<String>> userAuthInfos, UserIdentity user
14071408
userAuthInfos.add(userAuthInfo);
14081409
}
14091410

1411+
public static boolean isAdminPriv(GlobalPrivTable userGlobalPrivTable) {
1412+
PrivBitSet globalPrivs = new PrivBitSet();
1413+
for (PrivEntry pe : userGlobalPrivTable.getEntries()) {
1414+
globalPrivs.or(pe.privSet);
1415+
}
1416+
if (globalPrivs.satisfy(PrivPredicate.ADMIN)) {
1417+
return true;
1418+
}
1419+
return false;
1420+
}
1421+
1422+
public void getUserRoleWorkloadGroupPrivs(List<List<String>> result, UserIdentity currentUserIdentity) {
1423+
readLock();
1424+
try {
1425+
boolean isCurrentUserAdmin = isAdminPriv(getUserGlobalPrivTable(currentUserIdentity));
1426+
Map<String, List<User>> nameToUsers = userManager.getNameToUsers();
1427+
for (List<User> users : nameToUsers.values()) {
1428+
for (User user : users) {
1429+
if (!user.isSetByDomainResolver()) {
1430+
if (!isCurrentUserAdmin && !currentUserIdentity.equals(user.getUserIdentity())) {
1431+
continue;
1432+
}
1433+
GlobalPrivTable userGlobalPrivTable = getUserGlobalPrivTable(user.getUserIdentity());
1434+
String isGrantable = isAdminPriv(userGlobalPrivTable) ? "YES" : "NO";
1435+
1436+
// workload group
1437+
for (PrivEntry entry : getUserWorkloadGroupPrivTable(user.getUserIdentity()).entries) {
1438+
WorkloadGroupPrivEntry workloadGroupPrivEntry = (WorkloadGroupPrivEntry) entry;
1439+
PrivBitSet savedPrivs = workloadGroupPrivEntry.getPrivSet().copy();
1440+
1441+
List<String> row = Lists.newArrayList();
1442+
row.add(user.getUserIdentity().toString());
1443+
row.add(workloadGroupPrivEntry.getOrigWorkloadGroupName());
1444+
row.add(savedPrivs.toString());
1445+
row.add(isGrantable);
1446+
result.add(row);
1447+
}
1448+
}
1449+
}
1450+
}
1451+
1452+
Set<String> currentUserRole = null;
1453+
if (!isCurrentUserAdmin) {
1454+
currentUserRole = userRoleManager.getRolesByUser(currentUserIdentity, false);
1455+
currentUserRole = currentUserRole == null ? new HashSet<>() : currentUserRole;
1456+
}
1457+
roleManager.getRoleWorkloadGroupPrivs(result, currentUserRole);
1458+
} finally {
1459+
readUnlock();
1460+
}
1461+
}
1462+
14101463
private ResourcePrivTable getUserCloudClusterPrivTable(UserIdentity userIdentity) {
14111464
ResourcePrivTable table = new ResourcePrivTable();
14121465
Set<String> roles = userRoleManager.getRolesByUser(userIdentity);

fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java

+26
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.doris.qe.ConnectContext;
3838
import org.apache.doris.resource.workloadgroup.WorkloadGroupMgr;
3939

40+
import com.aliyuncs.utils.StringUtils;
4041
import com.google.common.base.Joiner;
4142
import com.google.common.base.Strings;
4243
import com.google.common.collect.Lists;
@@ -211,6 +212,31 @@ public void getRoleInfo(List<List<String>> results) {
211212
}
212213
}
213214

215+
public void getRoleWorkloadGroupPrivs(List<List<String>> result, Set<String> limitedRole) {
216+
for (Role role : roles.values()) {
217+
if (ClusterNamespace.getNameFromFullName(role.getRoleName()).startsWith(DEFAULT_ROLE_PREFIX)) {
218+
continue;
219+
}
220+
221+
if (limitedRole != null && !limitedRole.contains(role.getRoleName())) {
222+
continue;
223+
}
224+
String isGrantable = Auth.isAdminPriv(role.getGlobalPrivTable()) ? "YES" : "NO";
225+
226+
for (Map.Entry<WorkloadGroupPattern, PrivBitSet> entry : role.getWorkloadGroupPatternToPrivs().entrySet()) {
227+
List<String> row = Lists.newArrayList();
228+
row.add(role.getRoleName());
229+
row.add(entry.getKey().getworkloadGroupName());
230+
if (StringUtils.isEmpty(entry.getValue().toString())) {
231+
continue;
232+
}
233+
row.add(entry.getValue().toString());
234+
row.add(isGrantable);
235+
result.add(row);
236+
}
237+
}
238+
}
239+
214240
public Role createDefaultRole(UserIdentity userIdent) throws DdlException {
215241
String userDefaultRoleName = getUserDefaultRoleName(userIdent);
216242
if (roles.containsKey(userDefaultRoleName)) {

0 commit comments

Comments
 (0)