From d1ca6709b41ed72ad8ced5d7c1e1201467ddab36 Mon Sep 17 00:00:00 2001 From: wangbo <506340561@qq.com> Date: Fri, 26 Jul 2024 15:27:44 +0800 Subject: [PATCH 1/2] Add schema table workload_group_privileges --- be/src/exec/schema_scanner.cpp | 3 + .../schema_workload_group_privileges.cpp | 136 ++++++++++++++++++ .../schema_workload_group_privileges.h | 52 +++++++ .../doris/analysis/SchemaTableType.java | 4 +- .../org/apache/doris/catalog/SchemaTable.java | 8 ++ .../apache/doris/mysql/privilege/Auth.java | 53 +++++++ .../doris/mysql/privilege/RoleManager.java | 26 ++++ .../tablefunction/MetadataGenerator.java | 37 +++++ gensrc/thrift/Descriptors.thrift | 3 +- gensrc/thrift/FrontendService.thrift | 1 + .../jdbc/test_mariadb_jdbc_catalog.out | 1 + .../jdbc/test_mysql_jdbc_catalog.out | 1 + .../jdbc/test_mysql_jdbc_catalog_nereids.out | 1 + .../jdbc/test_mysql_jdbc_driver5_catalog.out | 1 + .../workload_manager_p0/test_curd_wlg.out | 49 +++++++ .../workload_manager_p0/test_curd_wlg.groovy | 58 ++++++++ 16 files changed, 432 insertions(+), 2 deletions(-) create mode 100644 be/src/exec/schema_scanner/schema_workload_group_privileges.cpp create mode 100644 be/src/exec/schema_scanner/schema_workload_group_privileges.h diff --git a/be/src/exec/schema_scanner.cpp b/be/src/exec/schema_scanner.cpp index de9857bad2ce83..9cae67f677d3b3 100644 --- a/be/src/exec/schema_scanner.cpp +++ b/be/src/exec/schema_scanner.cpp @@ -48,6 +48,7 @@ #include "exec/schema_scanner/schema_user_scanner.h" #include "exec/schema_scanner/schema_variables_scanner.h" #include "exec/schema_scanner/schema_views_scanner.h" +#include "exec/schema_scanner/schema_workload_group_privileges.h" #include "exec/schema_scanner/schema_workload_groups_scanner.h" #include "exec/schema_scanner/schema_workload_sched_policy_scanner.h" #include "olap/hll.h" @@ -170,6 +171,8 @@ std::unique_ptr SchemaScanner::create(TSchemaTableType::type type return SchemaWorkloadSchedulePolicyScanner::create_unique(); case TSchemaTableType::SCH_TABLE_OPTIONS: return SchemaTableOptionsScanner::create_unique(); + case TSchemaTableType::SCH_WORKLOAD_GROUP_PRIVILEGES: + return SchemaWorkloadGroupPrivilegesScanner::create_unique(); default: return SchemaDummyScanner::create_unique(); break; diff --git a/be/src/exec/schema_scanner/schema_workload_group_privileges.cpp b/be/src/exec/schema_scanner/schema_workload_group_privileges.cpp new file mode 100644 index 00000000000000..88baddb550ec7c --- /dev/null +++ b/be/src/exec/schema_scanner/schema_workload_group_privileges.cpp @@ -0,0 +1,136 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "exec/schema_scanner/schema_workload_group_privileges.h" + +#include "runtime/client_cache.h" +#include "runtime/exec_env.h" +#include "runtime/runtime_state.h" +#include "util/thrift_rpc_helper.h" +#include "vec/common/string_ref.h" +#include "vec/core/block.h" +#include "vec/data_types/data_type_factory.hpp" + +namespace doris { +std::vector SchemaWorkloadGroupPrivilegesScanner::_s_tbls_columns = { + {"GRANTEE", TYPE_VARCHAR, sizeof(StringRef), true}, + {"WORKLOAD_GROUP_NAME", TYPE_VARCHAR, sizeof(StringRef), true}, + {"PRIVILEGE_TYPE", TYPE_VARCHAR, sizeof(StringRef), true}, + {"IS_GRANTABLE", TYPE_VARCHAR, sizeof(StringRef), true}, +}; + +SchemaWorkloadGroupPrivilegesScanner::SchemaWorkloadGroupPrivilegesScanner() + : SchemaScanner(_s_tbls_columns, TSchemaTableType::SCH_WORKLOAD_GROUPS) {} + +SchemaWorkloadGroupPrivilegesScanner::~SchemaWorkloadGroupPrivilegesScanner() {} + +Status SchemaWorkloadGroupPrivilegesScanner::start(RuntimeState* state) { + _block_rows_limit = state->batch_size(); + _rpc_timeout = state->execution_timeout() * 1000; + return Status::OK(); +} + +Status SchemaWorkloadGroupPrivilegesScanner::_get_workload_group_privs_block_from_fe() { + TNetworkAddress master_addr = ExecEnv::GetInstance()->master_info()->network_address; + + TSchemaTableRequestParams schema_table_request_params; + for (int i = 0; i < _s_tbls_columns.size(); i++) { + schema_table_request_params.__isset.columns_name = true; + schema_table_request_params.columns_name.emplace_back(_s_tbls_columns[i].name); + } + schema_table_request_params.__set_current_user_ident(*_param->common_param->current_user_ident); + + TFetchSchemaTableDataRequest request; + request.__set_schema_table_name(TSchemaTableName::WORKLOAD_GROUP_PRIVILEGES); + request.__set_schema_table_params(schema_table_request_params); + + TFetchSchemaTableDataResult result; + + RETURN_IF_ERROR(ThriftRpcHelper::rpc( + master_addr.hostname, master_addr.port, + [&request, &result](FrontendServiceConnection& client) { + client->fetchSchemaTableData(result, request); + }, + _rpc_timeout)); + + Status status(Status::create(result.status)); + if (!status.ok()) { + LOG(WARNING) << "fetch workload group privileges from FE failed, errmsg=" << status; + return status; + } + std::vector result_data = result.data_batch; + + _workload_groups_privs_block = vectorized::Block::create_unique(); + for (int i = 0; i < _s_tbls_columns.size(); ++i) { + TypeDescriptor descriptor(_s_tbls_columns[i].type); + auto data_type = vectorized::DataTypeFactory::instance().create_data_type(descriptor, true); + _workload_groups_privs_block->insert(vectorized::ColumnWithTypeAndName( + data_type->create_column(), data_type, _s_tbls_columns[i].name)); + } + + if (result_data.size() > 0) { + int col_size = result_data[0].column_value.size(); + if (col_size != _s_tbls_columns.size()) { + return Status::InternalError( + "workload group privileges schema is not match for FE and BE"); + } + } + + _workload_groups_privs_block->reserve(result_data.size()); + + for (int i = 0; i < result_data.size(); i++) { + TRow row = result_data[i]; + + for (int j = 0; j < _s_tbls_columns.size(); j++) { + RETURN_IF_ERROR(insert_block_column(row.column_value[j], j, + _workload_groups_privs_block.get(), + _s_tbls_columns[j].type)); + } + } + return Status::OK(); +} + +Status SchemaWorkloadGroupPrivilegesScanner::get_next_block(vectorized::Block* block, bool* eos) { + if (!_is_init) { + return Status::InternalError("Used before initialized."); + } + + if (nullptr == block || nullptr == eos) { + return Status::InternalError("input pointer is nullptr."); + } + + if (_workload_groups_privs_block == nullptr) { + RETURN_IF_ERROR(_get_workload_group_privs_block_from_fe()); + _total_rows = _workload_groups_privs_block->rows(); + } + + if (_row_idx == _total_rows) { + *eos = true; + return Status::OK(); + } + + int current_batch_rows = std::min(_block_rows_limit, _total_rows - _row_idx); + vectorized::MutableBlock mblock = vectorized::MutableBlock::build_mutable_block(block); + RETURN_IF_ERROR( + mblock.add_rows(_workload_groups_privs_block.get(), _row_idx, current_batch_rows)); + _row_idx += current_batch_rows; + + *eos = _row_idx == _total_rows; + return Status::OK(); +} + +} // namespace doris \ No newline at end of file diff --git a/be/src/exec/schema_scanner/schema_workload_group_privileges.h b/be/src/exec/schema_scanner/schema_workload_group_privileges.h new file mode 100644 index 00000000000000..cdf3c9697b1e78 --- /dev/null +++ b/be/src/exec/schema_scanner/schema_workload_group_privileges.h @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#include + +#include "common/status.h" +#include "exec/schema_scanner.h" + +namespace doris { +class RuntimeState; +namespace vectorized { +class Block; +} // namespace vectorized + +class SchemaWorkloadGroupPrivilegesScanner : public SchemaScanner { + ENABLE_FACTORY_CREATOR(SchemaWorkloadGroupPrivilegesScanner); + +public: + SchemaWorkloadGroupPrivilegesScanner(); + ~SchemaWorkloadGroupPrivilegesScanner() override; + + Status start(RuntimeState* state) override; + Status get_next_block(vectorized::Block* block, bool* eos) override; + + static std::vector _s_tbls_columns; + +private: + Status _get_workload_group_privs_block_from_fe(); + + int _block_rows_limit = 4096; + int _row_idx = 0; + int _total_rows = 0; + std::unique_ptr _workload_groups_privs_block = nullptr; + int _rpc_timeout = 3000; +}; +}; // namespace doris \ No newline at end of file diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java index 988953ed4cbc7a..d0a3a3728b2d6b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java @@ -78,7 +78,9 @@ public enum SchemaTableType { SCH_WORKLOAD_POLICY("WORKLOAD_POLICY", "WORKLOAD_POLICY", TSchemaTableType.SCH_WORKLOAD_POLICY), SCH_TABLE_OPTIONS("TABLE_OPTIONS", "TABLE_OPTIONS", - TSchemaTableType.SCH_TABLE_OPTIONS); + TSchemaTableType.SCH_TABLE_OPTIONS), + SCH_WORKLOAD_GROUP_PRIVILEGES("WORKLOAD_GROUP_PRIVILEGES", + "WORKLOAD_GROUP_PRIVILEGES", TSchemaTableType.SCH_WORKLOAD_GROUP_PRIVILEGES); private static final String dbName = "INFORMATION_SCHEMA"; private static SelectList fullSelectLists; diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/SchemaTable.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/SchemaTable.java index dd731e0909ef1d..1c8f5dde930136 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/SchemaTable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/SchemaTable.java @@ -532,6 +532,14 @@ public class SchemaTable extends Table { .column("PARTITION_NUM", ScalarType.createType(PrimitiveType.INT)) .column("PROPERTIES", ScalarType.createStringType()) .build())) + .put("workload_group_privileges", + new SchemaTable(SystemIdGenerator.getNextId(), "workload_group_privileges", TableType.SCHEMA, + builder().column("GRANTEE", ScalarType.createVarchar(NAME_CHAR_LEN)) + .column("WORKLOAD_GROUP_NAME", ScalarType.createVarchar(256)) + .column("PRIVILEGE_TYPE", ScalarType.createVarchar(PRIVILEGE_TYPE_LEN)) + .column("IS_GRANTABLE", ScalarType.createVarchar(IS_GRANTABLE_LEN)) + .build()) + ) .build(); protected SchemaTable(long id, String name, TableType type, List baseSchema) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java index 9fb6d9218b0ce9..6c0bfa095b9782 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java @@ -82,6 +82,7 @@ import java.io.DataOutput; import java.io.IOException; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -1407,6 +1408,58 @@ private void getUserAuthInfo(List> userAuthInfos, UserIdentity user userAuthInfos.add(userAuthInfo); } + public static boolean isAdminPriv(GlobalPrivTable userGlobalPrivTable) { + PrivBitSet globalPrivs = new PrivBitSet(); + for (PrivEntry pe : userGlobalPrivTable.getEntries()) { + globalPrivs.or(pe.privSet); + } + if (globalPrivs.satisfy(PrivPredicate.ADMIN)) { + return true; + } + return false; + } + + public void getUserRoleWorkloadGroupPrivs(List> result, UserIdentity currentUserIdentity) { + readLock(); + try { + boolean isCurrentUserAdmin = isAdminPriv(getUserGlobalPrivTable(currentUserIdentity)); + Map> nameToUsers = userManager.getNameToUsers(); + for (List users : nameToUsers.values()) { + for (User user : users) { + if (!user.isSetByDomainResolver()) { + if (!isCurrentUserAdmin && !currentUserIdentity.equals(user.getUserIdentity())) { + continue; + } + GlobalPrivTable userGlobalPrivTable = getUserGlobalPrivTable(user.getUserIdentity()); + String isGrantable = isAdminPriv(userGlobalPrivTable) ? "YES" : "NO"; + + // workload group + for (PrivEntry entry : getUserWorkloadGroupPrivTable(user.getUserIdentity()).entries) { + WorkloadGroupPrivEntry workloadGroupPrivEntry = (WorkloadGroupPrivEntry) entry; + PrivBitSet savedPrivs = workloadGroupPrivEntry.getPrivSet().copy(); + + List row = Lists.newArrayList(); + row.add(user.getUserIdentity().toString()); + row.add(workloadGroupPrivEntry.getOrigWorkloadGroupName()); + row.add(savedPrivs.toString()); + row.add(isGrantable); + result.add(row); + } + } + } + } + + Set currentUserRole = null; + if (!isCurrentUserAdmin) { + currentUserRole = userRoleManager.getRolesByUser(currentUserIdentity, false); + currentUserRole = currentUserRole == null ? new HashSet<>() : currentUserRole; + } + roleManager.getRoleWorkloadGroupPrivs(result, currentUserRole); + } finally { + readUnlock(); + } + } + private ResourcePrivTable getUserCloudClusterPrivTable(UserIdentity userIdentity) { ResourcePrivTable table = new ResourcePrivTable(); Set roles = userRoleManager.getRolesByUser(userIdentity); diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java index 93bd7f72fdc270..600bd149c39158 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java @@ -37,6 +37,7 @@ import org.apache.doris.qe.ConnectContext; import org.apache.doris.resource.workloadgroup.WorkloadGroupMgr; +import com.aliyuncs.utils.StringUtils; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.Lists; @@ -211,6 +212,31 @@ public void getRoleInfo(List> results) { } } + public void getRoleWorkloadGroupPrivs(List> result, Set limitedRole) { + for (Role role : roles.values()) { + if (ClusterNamespace.getNameFromFullName(role.getRoleName()).startsWith(DEFAULT_ROLE_PREFIX)) { + continue; + } + + if (limitedRole != null && !limitedRole.contains(role.getRoleName())) { + continue; + } + String isGrantable = Auth.isAdminPriv(role.getGlobalPrivTable()) ? "YES" : "NO"; + + for (Map.Entry entry : role.getWorkloadGroupPatternToPrivs().entrySet()) { + List row = Lists.newArrayList(); + row.add(role.getRoleName()); + row.add(entry.getKey().getworkloadGroupName()); + if (StringUtils.isEmpty(entry.getValue().toString())) { + continue; + } + row.add(entry.getValue().toString()); + row.add(isGrantable); + result.add(row); + } + } + } + public Role createDefaultRole(UserIdentity userIdent) throws DdlException { String userDefaultRoleName = getUserDefaultRoleName(userIdent); if (roles.containsKey(userDefaultRoleName)) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java index 2f27b020cd8ff4..b446cd4210a764 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/MetadataGenerator.java @@ -113,6 +113,8 @@ public class MetadataGenerator { private static final ImmutableMap TABLE_OPTIONS_COLUMN_TO_INDEX; + private static final ImmutableMap WORKLOAD_GROUP_PRIVILEGES_COLUMN_TO_INDEX; + static { ImmutableMap.Builder activeQueriesbuilder = new ImmutableMap.Builder(); List activeQueriesColList = SchemaTable.TABLE_MAP.get("active_queries").getFullSchema(); @@ -146,6 +148,13 @@ public class MetadataGenerator { optionBuilder.put(optionColList.get(i).getName().toLowerCase(), i); } TABLE_OPTIONS_COLUMN_TO_INDEX = optionBuilder.build(); + + ImmutableMap.Builder wgPrivsBuilder = new ImmutableMap.Builder(); + List wgPrivsColList = SchemaTable.TABLE_MAP.get("workload_group_privileges").getFullSchema(); + for (int i = 0; i < wgPrivsColList.size(); i++) { + wgPrivsBuilder.put(wgPrivsColList.get(i).getName().toLowerCase(), i); + } + WORKLOAD_GROUP_PRIVILEGES_COLUMN_TO_INDEX = wgPrivsBuilder.build(); } public static TFetchSchemaTableDataResult getMetadataTable(TFetchSchemaTableDataRequest request) throws TException { @@ -229,6 +238,10 @@ public static TFetchSchemaTableDataResult getSchemaTableData(TFetchSchemaTableDa result = tableOptionsMetadataResult(schemaTableParams); columnIndex = TABLE_OPTIONS_COLUMN_TO_INDEX; break; + case WORKLOAD_GROUP_PRIVILEGES: + result = workloadGroupPrivsMetadataResult(schemaTableParams); + columnIndex = WORKLOAD_GROUP_PRIVILEGES_COLUMN_TO_INDEX; + break; default: return errorResult("invalid schema table name."); } @@ -537,6 +550,30 @@ private static TFetchSchemaTableDataResult workloadSchedPolicyMetadataResult(TSc return result; } + private static TFetchSchemaTableDataResult workloadGroupPrivsMetadataResult(TSchemaTableRequestParams params) { + if (!params.isSetCurrentUserIdent()) { + return errorResult("current user ident is not set."); + } + UserIdentity currentUserIdentity = UserIdentity.fromThrift(params.getCurrentUserIdent()); + + List> rows = new ArrayList<>(); + Env.getCurrentEnv().getAuth().getUserRoleWorkloadGroupPrivs(rows, currentUserIdentity); + List dataBatch = Lists.newArrayList(); + for (List privRow : rows) { + TRow trow = new TRow(); + String workloadGroupName = privRow.get(1); + trow.addToColumnValue(new TCell().setStringVal(privRow.get(0))); // GRANTEE + trow.addToColumnValue(new TCell().setStringVal(workloadGroupName)); // WORKLOAD_GROUP_NAME + trow.addToColumnValue(new TCell().setStringVal(privRow.get(2))); // PRIVILEGE_TYPE + trow.addToColumnValue(new TCell().setStringVal(privRow.get(3))); // IS_GRANTABLE + dataBatch.add(trow); + } + TFetchSchemaTableDataResult result = new TFetchSchemaTableDataResult(); + result.setDataBatch(dataBatch); + result.setStatus(new TStatus(TStatusCode.OK)); + return result; + } + private static TFetchSchemaTableDataResult queriesMetadataResult(TSchemaTableRequestParams tSchemaTableParams, TFetchSchemaTableDataRequest parentRequest) { TFetchSchemaTableDataResult result = new TFetchSchemaTableDataResult(); diff --git a/gensrc/thrift/Descriptors.thrift b/gensrc/thrift/Descriptors.thrift index cb844c933616bb..20042adc42ebd0 100644 --- a/gensrc/thrift/Descriptors.thrift +++ b/gensrc/thrift/Descriptors.thrift @@ -133,7 +133,8 @@ enum TSchemaTableType { SCH_USER, SCH_PROCS_PRIV, SCH_WORKLOAD_POLICY, - SCH_TABLE_OPTIONS; + SCH_TABLE_OPTIONS, + SCH_WORKLOAD_GROUP_PRIVILEGES; } enum THdfsCompression { diff --git a/gensrc/thrift/FrontendService.thrift b/gensrc/thrift/FrontendService.thrift index d48bd7564362f6..cce9e93fcc99c2 100644 --- a/gensrc/thrift/FrontendService.thrift +++ b/gensrc/thrift/FrontendService.thrift @@ -1002,6 +1002,7 @@ enum TSchemaTableName { ROUTINES_INFO = 4, // db information_schema's table WORKLOAD_SCHEDULE_POLICY = 5, TABLE_OPTIONS = 6, + WORKLOAD_GROUP_PRIVILEGES = 7, } struct TMetadataTableRequestParams { diff --git a/regression-test/data/external_table_p0/jdbc/test_mariadb_jdbc_catalog.out b/regression-test/data/external_table_p0/jdbc/test_mariadb_jdbc_catalog.out index 0eb3e6ed9eb7ac..c828848a8faf24 100644 --- a/regression-test/data/external_table_p0/jdbc/test_mariadb_jdbc_catalog.out +++ b/regression-test/data/external_table_p0/jdbc/test_mariadb_jdbc_catalog.out @@ -59,6 +59,7 @@ tables triggers user_privileges views +workload_group_privileges workload_groups workload_policy diff --git a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out index e79545774a1514..ee5cb342440a24 100644 --- a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out +++ b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out @@ -223,6 +223,7 @@ tables triggers user_privileges views +workload_group_privileges workload_groups workload_policy diff --git a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog_nereids.out b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog_nereids.out index fb9bf51ad936ce..0d7e953567f8ec 100644 --- a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog_nereids.out +++ b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog_nereids.out @@ -191,6 +191,7 @@ tables triggers user_privileges views +workload_group_privileges workload_groups workload_policy diff --git a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_driver5_catalog.out b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_driver5_catalog.out index 7e16cadc3c7448..953b425394c154 100644 --- a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_driver5_catalog.out +++ b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_driver5_catalog.out @@ -233,6 +233,7 @@ tables triggers user_privileges views +workload_group_privileges workload_groups workload_policy diff --git a/regression-test/data/workload_manager_p0/test_curd_wlg.out b/regression-test/data/workload_manager_p0/test_curd_wlg.out index 92de73f32784e5..5d9629aa440367 100644 --- a/regression-test/data/workload_manager_p0/test_curd_wlg.out +++ b/regression-test/data/workload_manager_p0/test_curd_wlg.out @@ -97,3 +97,52 @@ tag1_wg3 0% 80% tag1 -- !select_remote_scan_num_8 -- -1 -1 +-- !select_wgp_1 -- +'test_wg_priv_user1'@'%' normal Usage_priv NO + +-- !select_wgp_2 -- +'test_wg_priv_user1'@'%' normal Usage_priv NO +'test_wg_priv_user1'@'%' test_wg_priv_g1 Usage_priv NO + +-- !select_wgp_3 -- +'test_wg_priv_user1'@'%' normal Usage_priv NO + +-- !select_wgp_4 -- +'test_wg_priv_user1'@'%' normal Usage_priv NO +'test_wg_priv_user1'@'%' test_wg_priv_g1 Usage_priv NO + +-- !select_wgp_5 -- +'test_wg_priv_user1'@'%' normal Usage_priv NO +'test_wg_priv_user1'@'%' test_wg_priv_g1 Usage_priv NO + +-- !select_wgp_6 -- +'test_wg_priv_user1'@'%' normal Usage_priv NO +'test_wg_priv_user1'@'%' test_wg_priv_g1 Usage_priv NO +test_wg_priv_role1 test_wg_priv_g1 Usage_priv NO + +-- !select_wgp_7 -- +'test_wg_priv_user1'@'%' normal Usage_priv NO +'test_wg_priv_user1'@'%' test_wg_priv_g1 Usage_priv NO + +-- !select_wgp_8 -- +'test_wg_priv_user1'@'%' normal Usage_priv NO +'test_wg_priv_user1'@'%' test_wg_priv_g1 Usage_priv NO +test_wg_priv_role1 test_wg_priv_g1 Usage_priv NO + +-- !select_wgp_9 -- +'test_wg_priv_user1'@'%' % Usage_priv NO +'test_wg_priv_user1'@'%' normal Usage_priv NO +'test_wg_priv_user1'@'%' test_wg_priv_g1 Usage_priv NO +test_wg_priv_role1 % Usage_priv NO +test_wg_priv_role1 test_wg_priv_g1 Usage_priv NO + +-- !select_wgp_10 -- +'test_wg_priv_user1'@'%' normal Usage_priv NO +'test_wg_priv_user1'@'%' test_wg_priv_g1 Usage_priv NO +test_wg_priv_role1 test_wg_priv_g1 Usage_priv NO + +-- !select_wgp_11 -- +'test_wg_priv_user2'@'%' normal Usage_priv NO + +-- !select_wgp_12 -- + diff --git a/regression-test/suites/workload_manager_p0/test_curd_wlg.groovy b/regression-test/suites/workload_manager_p0/test_curd_wlg.groovy index 0aa60af7fbd09b..76721728bf202e 100644 --- a/regression-test/suites/workload_manager_p0/test_curd_wlg.groovy +++ b/regression-test/suites/workload_manager_p0/test_curd_wlg.groovy @@ -94,6 +94,7 @@ suite("test_crud_wlg") { sql "alter workload group normal properties ( 'scan_thread_num'='-1' );" sql "alter workload group normal properties ( 'scan_thread_num'='-1' );" sql "alter workload group normal properties ( 'remote_read_bytes_per_second'='-1' );" + sql "alter workload group normal properties ( 'read_bytes_per_second'='-1' );" sql "set workload_group=normal;" @@ -640,4 +641,61 @@ suite("test_crud_wlg") { sql "drop workload group tag1_mem_wg3;" sql "drop workload group bypass_group;" + // test workload group privilege table + sql "set workload_group=normal;" + sql "drop user if exists test_wg_priv_user1" + sql "drop user if exists test_wg_priv_user2" + sql "drop role if exists test_wg_priv_role1" + sql "drop workload group if exists test_wg_priv_g1;" + // 1 test grant user + sql "create workload group test_wg_priv_g1 properties('cpu_share'='1024')" + + sql "create user test_wg_priv_user1" + qt_select_wgp_1 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + + sql "GRANT USAGE_PRIV ON WORKLOAD GROUP 'test_wg_priv_g1' TO test_wg_priv_user1;" + qt_select_wgp_2 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + + sql "revoke USAGE_PRIV ON WORKLOAD GROUP 'test_wg_priv_g1' from test_wg_priv_user1;" + qt_select_wgp_3 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + + sql "GRANT USAGE_PRIV ON WORKLOAD GROUP 'test_wg_priv_g1' TO test_wg_priv_user1;" + qt_select_wgp_4 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + + + + // 2 test grant role + sql "create role test_wg_priv_role1;" + qt_select_wgp_5 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + + sql "GRANT USAGE_PRIV ON WORKLOAD GROUP 'test_wg_priv_g1' TO role 'test_wg_priv_role1';" + qt_select_wgp_6 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + + sql "revoke USAGE_PRIV ON WORKLOAD GROUP 'test_wg_priv_g1' from role 'test_wg_priv_role1';" + qt_select_wgp_7 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + + sql "GRANT USAGE_PRIV ON WORKLOAD GROUP 'test_wg_priv_g1' TO role 'test_wg_priv_role1';" + qt_select_wgp_8 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + + // 3 test grant % + sql "GRANT USAGE_PRIV ON WORKLOAD GROUP '%' TO test_wg_priv_user1; " + sql "GRANT USAGE_PRIV ON WORKLOAD GROUP '%' TO role 'test_wg_priv_role1'; " + qt_select_wgp_9 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + sql "revoke USAGE_PRIV ON WORKLOAD GROUP '%' from test_wg_priv_user1; " + sql "revoke USAGE_PRIV ON WORKLOAD GROUP '%' from role 'test_wg_priv_role1'; " + qt_select_wgp_10 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + + //4 test row filter + sql "create user test_wg_priv_user2" + sql "grant SELECT_PRIV on *.*.* to test_wg_priv_user2" + connect(user = 'test_wg_priv_user2', password = '', url = context.config.jdbcUrl) { + qt_select_wgp_11 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + } + + sql "drop user test_wg_priv_user1" + sql "drop user test_wg_priv_user2" + sql "drop role test_wg_priv_role1" + qt_select_wgp_12 "select GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE from information_schema.workload_group_privileges where grantee like '%test_wg_priv%' order by GRANTEE,WORKLOAD_GROUP_NAME,PRIVILEGE_TYPE,IS_GRANTABLE; " + sql "drop workload group test_wg_priv_g1" + } From a2d52d6e385a7aa2e57776754acab9cb00c7c9e0 Mon Sep 17 00:00:00 2001 From: wangbo <506340561@qq.com> Date: Tue, 30 Jul 2024 20:49:51 +0800 Subject: [PATCH 2/2] +1 --- .../org/apache/doris/mysql/privilege/Auth.java | 17 +++-------------- .../doris/mysql/privilege/RoleManager.java | 2 +- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java index 6c0bfa095b9782..2073e33cb4fdfc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java @@ -1408,21 +1408,10 @@ private void getUserAuthInfo(List> userAuthInfos, UserIdentity user userAuthInfos.add(userAuthInfo); } - public static boolean isAdminPriv(GlobalPrivTable userGlobalPrivTable) { - PrivBitSet globalPrivs = new PrivBitSet(); - for (PrivEntry pe : userGlobalPrivTable.getEntries()) { - globalPrivs.or(pe.privSet); - } - if (globalPrivs.satisfy(PrivPredicate.ADMIN)) { - return true; - } - return false; - } - public void getUserRoleWorkloadGroupPrivs(List> result, UserIdentity currentUserIdentity) { readLock(); try { - boolean isCurrentUserAdmin = isAdminPriv(getUserGlobalPrivTable(currentUserIdentity)); + boolean isCurrentUserAdmin = checkGlobalPriv(currentUserIdentity, PrivPredicate.ADMIN); Map> nameToUsers = userManager.getNameToUsers(); for (List users : nameToUsers.values()) { for (User user : users) { @@ -1430,8 +1419,8 @@ public void getUserRoleWorkloadGroupPrivs(List> result, UserIdentit if (!isCurrentUserAdmin && !currentUserIdentity.equals(user.getUserIdentity())) { continue; } - GlobalPrivTable userGlobalPrivTable = getUserGlobalPrivTable(user.getUserIdentity()); - String isGrantable = isAdminPriv(userGlobalPrivTable) ? "YES" : "NO"; + String isGrantable = checkGlobalPriv(user.getUserIdentity(), PrivPredicate.ADMIN) ? "YES" + : "NO"; // workload group for (PrivEntry entry : getUserWorkloadGroupPrivTable(user.getUserIdentity()).entries) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java index 600bd149c39158..6b215982c7d926 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java @@ -221,7 +221,7 @@ public void getRoleWorkloadGroupPrivs(List> result, Set lim if (limitedRole != null && !limitedRole.contains(role.getRoleName())) { continue; } - String isGrantable = Auth.isAdminPriv(role.getGlobalPrivTable()) ? "YES" : "NO"; + String isGrantable = role.checkGlobalPriv(PrivPredicate.ADMIN) ? "YES" : "NO"; for (Map.Entry entry : role.getWorkloadGroupPatternToPrivs().entrySet()) { List row = Lists.newArrayList();