From 042f6f77df86552cd114ebf3277e3bed1ca5ec80 Mon Sep 17 00:00:00 2001 From: TCeason <33082201+TCeason@users.noreply.github.com> Date: Thu, 12 Dec 2024 07:20:31 +0800 Subject: [PATCH] feat(rbac): add GrantObject::Warehouse (#17029) Warehouse permissions are granted to roles, and each warehouse can only be assigned to one role. --- src/common/exception/src/exception_code.rs | 1 + src/meta/app/src/principal/user_grant.rs | 11 ++- src/meta/app/src/principal/user_privilege.rs | 8 +- .../src/user_from_to_protobuf_impl.rs | 8 ++ src/meta/proto-conv/src/util.rs | 1 + src/meta/proto-conv/tests/it/main.rs | 1 + .../tests/it/v113_warehouse_grantobject.rs | 40 +++++++++ src/meta/protos/proto/user.proto | 5 ++ src/query/ast/src/ast/statements/user.rs | 2 + src/query/ast/src/parser/statement.rs | 27 ++++++ src/query/ast/tests/it/parser.rs | 4 + src/query/ast/tests/it/testdata/stmt.txt | 88 +++++++++++++++++++ .../interpreters/access/privilege_access.rs | 9 +- .../service/src/interpreters/common/grant.rs | 4 + .../interpreter_privilege_grant.rs | 2 +- src/query/service/src/sessions/session.rs | 10 +++ src/query/service/src/sessions/session_ctx.rs | 12 +++ .../src/sessions/session_privilege_mgr.rs | 25 ++++++ .../show_grants/show_grants_table.rs | 7 ++ .../tests/it/sessions/session_context.rs | 8 ++ .../sql/src/planner/binder/ddl/account.rs | 2 + src/query/users/src/role_mgr.rs | 25 ++++++ src/query/users/src/user_mgr.rs | 12 +++ src/query/users/src/visibility_checker.rs | 29 ++++++ .../base/05_ddl/05_0017_ddl_grant_role.test | 42 +++++++++ .../18_rbac/18_0001_udf_priv.result | 62 ++++++------- .../18_rbac/18_0002_ownership_cover.result | 4 +- .../18_rbac/18_0007_privilege_access.result | 6 +- .../18_rbac/18_0009_set_role.result | 4 +- .../18_rbac/18_0012_temp_table.result | 2 +- .../00_stage/00_0012_stage_priv.result | 16 ++-- 31 files changed, 422 insertions(+), 55 deletions(-) create mode 100644 src/meta/proto-conv/tests/it/v113_warehouse_grantobject.rs diff --git a/src/common/exception/src/exception_code.rs b/src/common/exception/src/exception_code.rs index 3ac860b8f7a0..ef4a30d220e6 100644 --- a/src/common/exception/src/exception_code.rs +++ b/src/common/exception/src/exception_code.rs @@ -293,6 +293,7 @@ build_exceptions! { // Cluster error codes. ClusterUnknownNode(2401), ClusterNodeAlreadyExists(2402), + InvalidWarehouse(2403), // Stage error codes. UnknownStage(2501), diff --git a/src/meta/app/src/principal/user_grant.rs b/src/meta/app/src/principal/user_grant.rs index e08d86495473..6fb2c38796e3 100644 --- a/src/meta/app/src/principal/user_grant.rs +++ b/src/meta/app/src/principal/user_grant.rs @@ -57,6 +57,7 @@ pub enum GrantObject { TableById(String, u64, u64), UDF(String), Stage(String), + Warehouse(String), } impl GrantObject { @@ -89,6 +90,7 @@ impl GrantObject { (GrantObject::Table(_, _, _), _) => false, (GrantObject::Stage(lstage), GrantObject::Stage(rstage)) => lstage == rstage, (GrantObject::UDF(udf), GrantObject::UDF(rudf)) => udf == rudf, + (GrantObject::Warehouse(w), GrantObject::Warehouse(rw)) => w == rw, _ => false, } } @@ -109,12 +111,16 @@ impl GrantObject { GrantObject::Stage(_) => { UserPrivilegeSet::available_privileges_on_stage(available_ownership) } + GrantObject::Warehouse(_) => UserPrivilegeSet::available_privileges_on_warehouse(), } } pub fn catalog(&self) -> Option { match self { - GrantObject::Global | GrantObject::Stage(_) | GrantObject::UDF(_) => None, + GrantObject::Global + | GrantObject::Stage(_) + | GrantObject::UDF(_) + | GrantObject::Warehouse(_) => None, GrantObject::Database(cat, _) | GrantObject::DatabaseById(cat, _) => Some(cat.clone()), GrantObject::Table(cat, _, _) | GrantObject::TableById(cat, _, _) => Some(cat.clone()), } @@ -135,6 +141,7 @@ impl fmt::Display for GrantObject { } GrantObject::UDF(udf) => write!(f, "UDF {udf}"), GrantObject::Stage(stage) => write!(f, "STAGE {stage}"), + GrantObject::Warehouse(w) => write!(f, "WAREHOUSE {w}"), } } } @@ -179,7 +186,7 @@ impl GrantEntry { } impl fmt::Display for GrantEntry { - fn fmt(&self, f: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { let privileges: UserPrivilegeSet = self.privileges.into(); let privileges_str = if self.has_all_available_privileges() { "ALL".to_string() diff --git a/src/meta/app/src/principal/user_privilege.rs b/src/meta/app/src/principal/user_privilege.rs index 4f7374fabef3..6d87ea58f26b 100644 --- a/src/meta/app/src/principal/user_privilege.rs +++ b/src/meta/app/src/principal/user_privilege.rs @@ -36,7 +36,7 @@ use enumflags2::BitFlags; num_derive::FromPrimitive, )] pub enum UserPrivilegeType { - // UsagePrivilege is a synonym for “no privileges”, if object is udf, means can use this udf + // UsagePrivilege is a synonym for “no privileges”, if object is udf/warehouse, means can use this udf/warehouse Usage = 1 << 0, // Privilege to select rows from tables in a database. Select = 1 << 2, @@ -199,10 +199,12 @@ impl UserPrivilegeSet { let database_privs = Self::available_privileges_on_database(false); let stage_privs_without_ownership = Self::available_privileges_on_stage(false); let udf_privs_without_ownership = Self::available_privileges_on_udf(false); + let wh_privs_without_ownership = Self::available_privileges_on_warehouse(); let privs = make_bitflags!(UserPrivilegeType::{ Usage | Super | CreateUser | DropUser | CreateRole | DropRole | CreateDatabase | Grant | CreateDataMask }); (database_privs.privileges | privs | stage_privs_without_ownership.privileges + | wh_privs_without_ownership.privileges | udf_privs_without_ownership.privileges) .into() } @@ -232,6 +234,10 @@ impl UserPrivilegeSet { } } + pub fn available_privileges_on_warehouse() -> Self { + make_bitflags!(UserPrivilegeType::{ Usage }).into() + } + pub fn available_privileges_on_udf(available_ownership: bool) -> Self { if available_ownership { make_bitflags!(UserPrivilegeType::{ Usage | Ownership }).into() diff --git a/src/meta/proto-conv/src/user_from_to_protobuf_impl.rs b/src/meta/proto-conv/src/user_from_to_protobuf_impl.rs index 8e192b126124..f9df91e48fa8 100644 --- a/src/meta/proto-conv/src/user_from_to_protobuf_impl.rs +++ b/src/meta/proto-conv/src/user_from_to_protobuf_impl.rs @@ -193,6 +193,9 @@ impl FromToProto for mt::principal::GrantObject { pb::grant_object::Object::Stage(pb::grant_object::GrantStageObject { stage }) => { Ok(mt::principal::GrantObject::Stage(stage)) } + pb::grant_object::Object::Warehouse(pb::grant_object::GrantWarehouseObject { + warehouse, + }) => Ok(mt::principal::GrantObject::Warehouse(warehouse)), } } @@ -235,6 +238,11 @@ impl FromToProto for mt::principal::GrantObject { stage: stage.clone(), }, )), + mt::principal::GrantObject::Warehouse(w) => Some(pb::grant_object::Object::Warehouse( + pb::grant_object::GrantWarehouseObject { + warehouse: w.clone(), + }, + )), }; Ok(pb::GrantObject { ver: VER, diff --git a/src/meta/proto-conv/src/util.rs b/src/meta/proto-conv/src/util.rs index 6f82943521ac..1fd8a7ef5218 100644 --- a/src/meta/proto-conv/src/util.rs +++ b/src/meta/proto-conv/src/util.rs @@ -142,6 +142,7 @@ const META_CHANGE_LOG: &[(u64, &str)] = &[ (110, "2024-09-18: Add: database.proto: DatabaseMeta.gc_in_progress"), (111, "2024-11-13: Add: Enable AWS Glue as an Apache Iceberg type when creating a catalog."), (112, "2024-11-28: Add: virtual_column add data_types field"), + (113, "2024-12-10: Add: GrantWarehouseObject"), // Dear developer: // If you're gonna add a new metadata version, you'll have to add a test for it. // You could just copy an existing test file(e.g., `../tests/it/v024_table_meta.rs`) diff --git a/src/meta/proto-conv/tests/it/main.rs b/src/meta/proto-conv/tests/it/main.rs index 5c03fc8db8e8..8264fc85ca56 100644 --- a/src/meta/proto-conv/tests/it/main.rs +++ b/src/meta/proto-conv/tests/it/main.rs @@ -110,3 +110,4 @@ mod v109_procedure_with_args; mod v110_database_meta_gc_in_progress; mod v111_add_glue_as_iceberg_catalog_option; mod v112_virtual_column; +mod v113_warehouse_grantobject; diff --git a/src/meta/proto-conv/tests/it/v113_warehouse_grantobject.rs b/src/meta/proto-conv/tests/it/v113_warehouse_grantobject.rs new file mode 100644 index 000000000000..43e3ac8ef18b --- /dev/null +++ b/src/meta/proto-conv/tests/it/v113_warehouse_grantobject.rs @@ -0,0 +1,40 @@ +// Copyright 2023 Datafuse Labs. +// +// Licensed 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. + +use databend_common_meta_app as mt; +use fastrace::func_name; + +use crate::common; + +// These bytes are built when a new version in introduced, +// and are kept for backward compatibility test. +// +// ************************************************************* +// * These messages should never be updated, * +// * only be added when a new version is added, * +// * or be removed when an old version is no longer supported. * +// ************************************************************* +// + +#[test] +fn test_decode_v113_grant_object() -> anyhow::Result<()> { + let grant_object_v113 = vec![66, 4, 10, 2, 119, 116, 160, 6, 113, 168, 6, 24]; + + let want = || mt::principal::GrantObject::Warehouse("wt".to_string()); + + common::test_pb_from_to(func_name!(), want())?; + common::test_load_old(func_name!(), grant_object_v113.as_slice(), 113, want())?; + + Ok(()) +} diff --git a/src/meta/protos/proto/user.proto b/src/meta/protos/proto/user.proto index 895d7c568062..387695f59d3a 100644 --- a/src/meta/protos/proto/user.proto +++ b/src/meta/protos/proto/user.proto @@ -77,6 +77,10 @@ message GrantObject { string stage = 1; } + message GrantWarehouseObject { + string warehouse = 1; + } + oneof object { GrantGlobalObject global = 1; GrantDatabaseObject database = 2; @@ -85,6 +89,7 @@ message GrantObject { GrantStageObject stage = 5; GrantDatabaseIdObject databasebyid = 6; GrantTableIdObject tablebyid = 7; + GrantWarehouseObject warehouse = 8; } } diff --git a/src/query/ast/src/ast/statements/user.rs b/src/query/ast/src/ast/statements/user.rs index 12e771bc69e2..f0f729baf106 100644 --- a/src/query/ast/src/ast/statements/user.rs +++ b/src/query/ast/src/ast/statements/user.rs @@ -220,6 +220,7 @@ pub enum AccountMgrLevel { Table(Option, String), UDF(String), Stage(String), + Warehouse(String), } impl Display for AccountMgrLevel { @@ -242,6 +243,7 @@ impl Display for AccountMgrLevel { } AccountMgrLevel::UDF(udf) => write!(f, " UDF {udf}"), AccountMgrLevel::Stage(stage) => write!(f, " STAGE {stage}"), + AccountMgrLevel::Warehouse(w) => write!(f, " WAREHOUSE {w}"), } } } diff --git a/src/query/ast/src/parser/statement.rs b/src/query/ast/src/parser/statement.rs index 1b4a68456ee2..ad8ebaea488f 100644 --- a/src/query/ast/src/parser/statement.rs +++ b/src/query/ast/src/parser/statement.rs @@ -3084,9 +3084,31 @@ pub fn grant_source(i: Input) -> IResult { }, ); + let warehouse_privs = map( + rule! { + USAGE ~ ON ~ WAREHOUSE ~ #ident + }, + |(_, _, _, w)| AccountMgrSource::Privs { + privileges: vec![UserPrivilegeType::Usage], + level: AccountMgrLevel::Warehouse(w.to_string()), + }, + ); + + let warehouse_all_privs = map( + rule! { + ALL ~ PRIVILEGES? ~ ON ~ WAREHOUSE ~ #ident + }, + |(_, _, _, _, w)| AccountMgrSource::Privs { + privileges: vec![UserPrivilegeType::Usage], + level: AccountMgrLevel::Warehouse(w.to_string()), + }, + ); + rule!( #role : "ROLE " + | #warehouse_all_privs: "ALL [ PRIVILEGES ] ON WAREHOUSE " | #udf_privs: "USAGE ON UDF " + | #warehouse_privs: "USAGE ON WAREHOUSE " | #privs : " ON " | #stage_privs : " ON STAGE " | #udf_all_privs: "ALL [ PRIVILEGES ] ON UDF " @@ -3229,11 +3251,16 @@ pub fn grant_all_level(i: Input) -> IResult { let stage = map(rule! { STAGE ~ #ident}, |(_, stage_name)| { AccountMgrLevel::Stage(stage_name.to_string()) }); + + let warehouse = map(rule! { WAREHOUSE ~ #ident}, |(_, w)| { + AccountMgrLevel::Warehouse(w.to_string()) + }); rule!( #global : "*.*" | #db : ".*" | #table : "." | #stage : "STAGE " + | #warehouse : "WAREHOUSE " )(i) } diff --git a/src/query/ast/tests/it/parser.rs b/src/query/ast/tests/it/parser.rs index 9b43de488187..dfd95ccd7a19 100644 --- a/src/query/ast/tests/it/parser.rs +++ b/src/query/ast/tests/it/parser.rs @@ -553,6 +553,10 @@ fn test_statement() { r#"GRANT usage ON UDF a TO 'test-grant';"#, r#"REVOKE usage ON UDF a FROM 'test-grant';"#, r#"REVOKE all ON UDF a FROM 'test-grant';"#, + r#"GRANT all ON warehouse a TO role 'test-grant';"#, + r#"GRANT usage ON warehouse a TO role 'test-grant';"#, + r#"REVOKE usage ON warehouse a FROM role 'test-grant';"#, + r#"REVOKE all ON warehouse a FROM role 'test-grant';"#, r#"SHOW GRANTS ON TABLE db1.tb1;"#, r#"SHOW GRANTS ON DATABASE db;"#, r#"UPDATE db1.tb1 set a = a + 1, b = 2 WHERE c > 3;"#, diff --git a/src/query/ast/tests/it/testdata/stmt.txt b/src/query/ast/tests/it/testdata/stmt.txt index 63fdfca7b531..87f5b50ad42b 100644 --- a/src/query/ast/tests/it/testdata/stmt.txt +++ b/src/query/ast/tests/it/testdata/stmt.txt @@ -16075,6 +16075,94 @@ Revoke( ) +---------- Input ---------- +GRANT all ON warehouse a TO role 'test-grant'; +---------- Output --------- +GRANT USAGE ON WAREHOUSE a TO ROLE 'test-grant' +---------- AST ------------ +Grant( + GrantStmt { + source: Privs { + privileges: [ + Usage, + ], + level: Warehouse( + "a", + ), + }, + principal: Role( + "test-grant", + ), + }, +) + + +---------- Input ---------- +GRANT usage ON warehouse a TO role 'test-grant'; +---------- Output --------- +GRANT USAGE ON WAREHOUSE a TO ROLE 'test-grant' +---------- AST ------------ +Grant( + GrantStmt { + source: Privs { + privileges: [ + Usage, + ], + level: Warehouse( + "a", + ), + }, + principal: Role( + "test-grant", + ), + }, +) + + +---------- Input ---------- +REVOKE usage ON warehouse a FROM role 'test-grant'; +---------- Output --------- +REVOKE USAGE ON WAREHOUSE a FROM ROLE 'test-grant' +---------- AST ------------ +Revoke( + RevokeStmt { + source: Privs { + privileges: [ + Usage, + ], + level: Warehouse( + "a", + ), + }, + principal: Role( + "test-grant", + ), + }, +) + + +---------- Input ---------- +REVOKE all ON warehouse a FROM role 'test-grant'; +---------- Output --------- +REVOKE USAGE ON WAREHOUSE a FROM ROLE 'test-grant' +---------- AST ------------ +Revoke( + RevokeStmt { + source: Privs { + privileges: [ + Usage, + ], + level: Warehouse( + "a", + ), + }, + principal: Role( + "test-grant", + ), + }, +) + + ---------- Input ---------- SHOW GRANTS ON TABLE db1.tb1; ---------- Output --------- diff --git a/src/query/service/src/interpreters/access/privilege_access.rs b/src/query/service/src/interpreters/access/privilege_access.rs index c912c5fcc785..d098c71609ef 100644 --- a/src/query/service/src/interpreters/access/privilege_access.rs +++ b/src/query/service/src/interpreters/access/privilege_access.rs @@ -151,7 +151,7 @@ impl PrivilegeAccess { GrantObject::UDF(name) => OwnershipObject::UDF { name: name.to_string(), }, - GrantObject::Global => return Ok(None), + GrantObject::Global | GrantObject::Warehouse(_) => return Ok(None), }; Ok(Some(object)) @@ -225,7 +225,7 @@ impl PrivilegeAccess { return Err(ErrorCode::PermissionDenied(format!( "Permission denied: privilege [{:?}] is required on '{}'.'{}'.* for user {} with roles [{}]. \ - Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage.", + Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage.", privileges, catalog_name, db_name, @@ -441,7 +441,7 @@ impl PrivilegeAccess { | GrantObject::UDF(_) | GrantObject::Stage(_) | GrantObject::TableById(_, _, _) => true, - GrantObject::Global => false, + GrantObject::Global | GrantObject::Warehouse(_) => false, }; if verify_ownership @@ -490,11 +490,12 @@ impl PrivilegeAccess { GrantObject::DatabaseById(_, _) => Err(ErrorCode::PermissionDenied("")), GrantObject::Global | GrantObject::UDF(_) + | GrantObject::Warehouse(_) | GrantObject::Stage(_) | GrantObject::Database(_, _) | GrantObject::Table(_, _, _) => Err(ErrorCode::PermissionDenied(format!( "Permission denied: privilege [{:?}] is required on {} for user {} with roles [{}]. \ - Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage.", + Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage.", privilege, grant_object, ¤t_user.identity().display(), diff --git a/src/query/service/src/interpreters/common/grant.rs b/src/query/service/src/interpreters/common/grant.rs index fb675b6284e4..c0037dc2dad7 100644 --- a/src/query/service/src/interpreters/common/grant.rs +++ b/src/query/service/src/interpreters/common/grant.rs @@ -93,6 +93,10 @@ pub async fn validate_grant_object_exists( ))); } } + GrantObject::Warehouse(_w) => { + // TODO + return Ok(()); + } GrantObject::Global => (), } diff --git a/src/query/service/src/interpreters/interpreter_privilege_grant.rs b/src/query/service/src/interpreters/interpreter_privilege_grant.rs index 97178682692a..91694329d21c 100644 --- a/src/query/service/src/interpreters/interpreter_privilege_grant.rs +++ b/src/query/service/src/interpreters/interpreter_privilege_grant.rs @@ -101,7 +101,7 @@ impl GrantPrivilegeInterpreter { GrantObject::UDF(name) => Ok(OwnershipObject::UDF { name: name.to_string(), }), - GrantObject::Global => Err(ErrorCode::IllegalGrant( + GrantObject::Global | GrantObject::Warehouse(_) => Err(ErrorCode::IllegalGrant( "Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used", )), } diff --git a/src/query/service/src/sessions/session.rs b/src/query/service/src/sessions/session.rs index c6c5f901664d..6c312f03a01c 100644 --- a/src/query/service/src/sessions/session.rs +++ b/src/query/service/src/sessions/session.rs @@ -284,6 +284,16 @@ impl Session { self.privilege_mgr().get_all_effective_roles().await } + #[async_backtrace::framed] + pub async fn set_current_warehouse(&self, w: Option) -> Result<()> { + self.privilege_mgr().set_current_warehouse(w).await + } + + #[async_backtrace::framed] + pub async fn get_current_warehouse(&self) -> Option { + self.session_ctx.get_current_warehouse() + } + #[async_backtrace::framed] pub async fn validate_privilege( &self, diff --git a/src/query/service/src/sessions/session_ctx.rs b/src/query/service/src/sessions/session_ctx.rs index f79f5c5c076e..99a15aeaee63 100644 --- a/src/query/service/src/sessions/session_ctx.rs +++ b/src/query/service/src/sessions/session_ctx.rs @@ -83,6 +83,7 @@ pub struct SessionContext { /// some features like temp table will be unavailable. /// for mysql handler: simple use set id of `Session` client_session_id: RwLock>, + current_warehouse: RwLock>, } impl SessionContext { @@ -106,6 +107,7 @@ impl SessionContext { txn_mgr: Mutex::new(TxnManager::init()), client_session_id: Default::default(), temp_tbl_mgr: Mutex::new(TempTblMgr::init()), + current_warehouse: Default::default(), }) } @@ -164,6 +166,16 @@ impl SessionContext { lock.clone() } + pub fn set_current_warehouse(&self, w: Option) { + let mut lock = self.current_warehouse.write(); + *lock = w + } + + pub fn get_current_warehouse(&self) -> Option { + let lock = self.current_warehouse.read(); + lock.clone() + } + pub fn set_auth_role(&self, role: Option) { let mut lock = self.auth_role.write(); *lock = role diff --git a/src/query/service/src/sessions/session_privilege_mgr.rs b/src/query/service/src/sessions/session_privilege_mgr.rs index 60f1864ff3c6..07f01c1314f2 100644 --- a/src/query/service/src/sessions/session_privilege_mgr.rs +++ b/src/query/service/src/sessions/session_privilege_mgr.rs @@ -81,6 +81,7 @@ pub trait SessionPrivilegeManager { ) -> Result; // fn show_grants(&self); + async fn set_current_warehouse(&self, warehouse: Option) -> Result<()>; } pub struct SessionPrivilegeManagerImpl<'a> { @@ -225,6 +226,30 @@ impl SessionPrivilegeManager for SessionPrivilegeManagerImpl<'_> { Ok(effective_roles) } + async fn set_current_warehouse(&self, warehouse: Option) -> Result<()> { + let warehouse = match &warehouse { + Some(warehouse) => { + let effective_roles = self.get_all_effective_roles().await?; + effective_roles.iter().find_map(|role| { + role.grants.entries().iter().find_map(|grant| { + if let GrantObject::Warehouse(rw) = grant.object() { + if warehouse == rw { + Some(warehouse.to_string()) + } else { + None + } + } else { + None + } + }) + }) + } + None => None, + }; + self.session_ctx.set_current_warehouse(warehouse); + Ok(()) + } + // Returns all the roles the current session has. If the user have been granted auth_role, // the other roles will be ignored. // On executing SET ROLE, the role have to be one of the available roles. diff --git a/src/query/service/src/table_functions/show_grants/show_grants_table.rs b/src/query/service/src/table_functions/show_grants/show_grants_table.rs index bc121b0b60e0..6c16954e44a0 100644 --- a/src/query/service/src/table_functions/show_grants/show_grants_table.rs +++ b/src/query/service/src/table_functions/show_grants/show_grants_table.rs @@ -431,6 +431,13 @@ async fn show_account_grants( privileges.push(get_priv_str(&grant_entry)); grant_list.push(format!("{} TO {}", grant_entry, identity)); } + GrantObject::Warehouse(w_name) => { + // grant all on *.* to a + object_name.push(w_name.to_string()); + object_id.push(None); + privileges.push(get_priv_str(&grant_entry)); + grant_list.push(format!("{} TO {}", grant_entry, identity)); + } GrantObject::Global => { // grant all on *.* to a object_name.push("*.*".to_string()); diff --git a/src/query/service/tests/it/sessions/session_context.rs b/src/query/service/tests/it/sessions/session_context.rs index 9fca690621fc..f84f8cd28ebd 100644 --- a/src/query/service/tests/it/sessions/session_context.rs +++ b/src/query/service/tests/it/sessions/session_context.rs @@ -68,5 +68,13 @@ async fn test_session_context() -> Result<()> { assert!(val.is_none()); } + // Warehouse. + { + session_ctx.set_current_warehouse(Some("wt".to_string())); + + let val = session_ctx.get_current_warehouse().unwrap(); + assert_eq!("wt".to_string(), val); + } + Ok(()) } diff --git a/src/query/sql/src/planner/binder/ddl/account.rs b/src/query/sql/src/planner/binder/ddl/account.rs index f00113118a9e..38c02666e959 100644 --- a/src/query/sql/src/planner/binder/ddl/account.rs +++ b/src/query/sql/src/planner/binder/ddl/account.rs @@ -187,6 +187,7 @@ impl Binder { } AccountMgrLevel::UDF(udf) => Ok(GrantObject::UDF(udf.clone())), AccountMgrLevel::Stage(stage) => Ok(GrantObject::Stage(stage.clone())), + AccountMgrLevel::Warehouse(w) => Ok(GrantObject::Warehouse(w.clone())), } } @@ -247,6 +248,7 @@ impl Binder { } AccountMgrLevel::UDF(udf) => Ok(vec![GrantObject::UDF(udf.clone())]), AccountMgrLevel::Stage(stage) => Ok(vec![GrantObject::Stage(stage.clone())]), + AccountMgrLevel::Warehouse(w) => Ok(vec![GrantObject::Warehouse(w.clone())]), } } diff --git a/src/query/users/src/role_mgr.rs b/src/query/users/src/role_mgr.rs index 4f3ca63ff630..ab12fc206d88 100644 --- a/src/query/users/src/role_mgr.rs +++ b/src/query/users/src/role_mgr.rs @@ -198,6 +198,31 @@ impl UserApiProvider { privileges: UserPrivilegeSet, ) -> Result> { let client = self.role_api(tenant); + // Enforces warehouse exclusivity: a warehouse’s specific permission can only be granted to a single role. + // This logic verifies that no other role within the given tenant currently holds the target permission on the specified warehouse. + if let GrantObject::Warehouse(w) = &object { + let roles = self.get_roles(tenant).await?; + let mut illegal_role = String::new(); + let has_same_warehouse_grant = roles.iter().any(|r| { + let has_grant = r.grants.entries().iter().any(|grant| match grant.object() { + GrantObject::Warehouse(rw) => { + if w.to_lowercase() == rw.to_lowercase() { + illegal_role = r.identity().to_string(); + true + } else { + false + } + } + _ => false, + }); + has_grant + }); + if has_same_warehouse_grant { + return Err(ErrorCode::IllegalRole(format!( + "Error granting '{privileges}' access on data warehouse '{w}' to role '{role}'. Role '{illegal_role}' already possesses this access" + ))); + } + } client .update_role_with(role, MatchSeq::GE(1), |ri: &mut RoleInfo| { ri.update_role_time(); diff --git a/src/query/users/src/user_mgr.rs b/src/query/users/src/user_mgr.rs index df79a9bcf51a..013060438553 100644 --- a/src/query/users/src/user_mgr.rs +++ b/src/query/users/src/user_mgr.rs @@ -181,6 +181,12 @@ impl UserApiProvider { user.username ))); } + if let GrantObject::Warehouse(_) = object { + return Err(ErrorCode::IllegalUser(format!( + "Cannot grant warehouse privileges to user `{}`", + user.username + ))); + } let client = self.user_api(tenant); client .update_user_with(user, MatchSeq::GE(1), |ui: &mut UserInfo| { @@ -205,6 +211,12 @@ impl UserApiProvider { user.username ))); } + if let GrantObject::Warehouse(_) = object { + return Err(ErrorCode::IllegalUser(format!( + "Cannot grant warehouse privileges to user `{}`", + user.username + ))); + } let client = self.user_api(tenant); client .update_user_with(user, MatchSeq::GE(1), |ui: &mut UserInfo| { diff --git a/src/query/users/src/visibility_checker.rs b/src/query/users/src/visibility_checker.rs index 898ccd839bd2..a5face0632f1 100644 --- a/src/query/users/src/visibility_checker.rs +++ b/src/query/users/src/visibility_checker.rs @@ -31,6 +31,7 @@ use itertools::Itertools; /// It is used in `SHOW DATABASES` and `SHOW TABLES` statements. pub struct GrantObjectVisibilityChecker { granted_global_udf: bool, + granted_global_ws: bool, granted_global_db_table: bool, granted_global_stage: bool, granted_global_read_stage: bool, @@ -44,6 +45,7 @@ pub struct GrantObjectVisibilityChecker { granted_udfs: HashSet, granted_write_stages: HashSet, granted_read_stages: HashSet, + granted_ws: HashSet, } impl GrantObjectVisibilityChecker { @@ -53,12 +55,14 @@ impl GrantObjectVisibilityChecker { ownership_objects: &[OwnershipObject], ) -> Self { let mut granted_global_udf = false; + let mut granted_global_ws = false; let mut granted_global_db_table = false; let mut granted_global_stage = false; let mut granted_global_read_stage = false; let mut granted_databases = HashSet::new(); let mut granted_tables = HashSet::new(); let mut granted_udfs = HashSet::new(); + let mut granted_ws = HashSet::new(); let mut granted_write_stages = HashSet::new(); let mut granted_read_stages = HashSet::new(); let mut extra_databases = HashSet::new(); @@ -95,6 +99,15 @@ impl GrantObjectVisibilityChecker { }, ); + check_privilege( + &mut granted_global_ws, + ent.privileges().iter(), + |privilege| { + UserPrivilegeSet::available_privileges_on_warehouse() + .has_privilege(privilege) + }, + ); + check_privilege( &mut granted_global_stage, ent.privileges().iter(), @@ -156,6 +169,9 @@ impl GrantObjectVisibilityChecker { granted_read_stages.insert(stage.to_string()); } } + GrantObject::Warehouse(w) => { + granted_ws.insert(w.to_string()); + } } } } @@ -189,6 +205,7 @@ impl GrantObjectVisibilityChecker { Self { granted_global_udf, + granted_global_ws, granted_global_db_table, granted_global_stage, granted_global_read_stage, @@ -205,6 +222,7 @@ impl GrantObjectVisibilityChecker { ("default".to_string(), "information_schema".to_string()), ("default".to_string(), "system".to_string()), ]), + granted_ws, } } @@ -241,6 +259,17 @@ impl GrantObjectVisibilityChecker { false } + pub fn check_warehouse_visibility(&self, udf: &str) -> bool { + if self.granted_global_ws { + return true; + } + + if self.granted_ws.contains(udf) { + return true; + } + false + } + pub fn check_database_visibility(&self, catalog: &str, db: &str, db_id: u64) -> bool { // skip information_schema privilege check if db.to_lowercase() == "information_schema" || db.to_lowercase() == "system" { diff --git a/tests/sqllogictests/suites/base/05_ddl/05_0017_ddl_grant_role.test b/tests/sqllogictests/suites/base/05_ddl/05_0017_ddl_grant_role.test index ec443184cf0d..4ad34d0048c1 100644 --- a/tests/sqllogictests/suites/base/05_ddl/05_0017_ddl_grant_role.test +++ b/tests/sqllogictests/suites/base/05_ddl/05_0017_ddl_grant_role.test @@ -222,3 +222,45 @@ show grants for 'u@05_0017'; statement ok drop user if exists 'u@05_0017'; + +statement ok +drop role if exists role1; + +statement ok +drop role if exists role2; + +statement ok +create role role1; + +statement ok +create role role2; + +statement ok +grant usage on warehouse a to role role1; + +statement ok +grant usage on warehouse b to role role1; + +statement error 2217 +grant usage on warehouse a to role role2; + +statement ok +grant usage on warehouse c to role role2; + +statement ok +drop user if exists u1; + +statement ok +create user u1 identified by '123'; + +statement error 2218 +grant usage on warehouse a to u1; + +statement ok +drop user if exists u1; + +statement ok +drop role if exists role1; + +statement ok +drop role if exists role2; diff --git a/tests/suites/0_stateless/18_rbac/18_0001_udf_priv.result b/tests/suites/0_stateless/18_rbac/18_0001_udf_priv.result index 8511a27b3112..2f5bc74f89c4 100644 --- a/tests/suites/0_stateless/18_rbac/18_0001_udf_priv.result +++ b/tests/suites/0_stateless/18_rbac/18_0001_udf_priv.result @@ -1,42 +1,42 @@ === test UDF priv === Only Has Privilege on f2 === -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. 2 -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. select 1 from (select f2(f1(10))); -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. select * from system.one where f2(f1(1)); -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. 1 NULL -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f1 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. === Only Has Privilege on f1 === -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. 2 -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. 1 NULL -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF f2 for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. === Has Privilege on f1, f2 === 1 2 @@ -55,4 +55,4 @@ Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is requ 100 200 4 -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF b for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF b for user 'test-user'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. diff --git a/tests/suites/0_stateless/18_rbac/18_0002_ownership_cover.result b/tests/suites/0_stateless/18_rbac/18_0002_ownership_cover.result index 52667dc6f592..ed06eb7e20a2 100644 --- a/tests/suites/0_stateless/18_rbac/18_0002_ownership_cover.result +++ b/tests/suites/0_stateless/18_rbac/18_0002_ownership_cover.result @@ -11,8 +11,8 @@ 0 200 === test role r_0002 === -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF a for user 'owner'@'%' with roles [public,r_0002]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE hello for user 'owner'@'%' with roles [public,r_0002]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Usage] is required on UDF a for user 'owner'@'%' with roles [public,r_0002]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE hello for user 'owner'@'%' with roles [public,r_0002]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. Error: APIError: QueryFailed: [1063]Permission denied: privilege [Select] is required on 'default'.'d_0002'.'t' for user 'owner'@'%' with roles [public,r_0002] === test ownership: show stmt === public 0 false false diff --git a/tests/suites/0_stateless/18_rbac/18_0007_privilege_access.result b/tests/suites/0_stateless/18_rbac/18_0007_privilege_access.result index bbc48f633549..d5e57fd5e0c9 100644 --- a/tests/suites/0_stateless/18_rbac/18_0007_privilege_access.result +++ b/tests/suites/0_stateless/18_rbac/18_0007_privilege_access.result @@ -96,10 +96,10 @@ Error: APIError: QueryFailed: [1063]Permission denied: No privilege on table roo Error: APIError: QueryFailed: [1063]Permission denied: No privilege on table root_table for user b. 1 1 356 Error: APIError: QueryFailed: [1063]Permission denied: privilege [Select] is required on 'default'.'default'.'t1' for user 'b'@'%' with roles [public] -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s3 for user 'b'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s3 for user 'b'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. Error: APIError: QueryFailed: [1063]Permission denied: privilege [Select] is required on 'default'.'default'.'t' for user 'b'@'%' with roles [public] -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s3 for user 'b'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s3 for user 'b'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s3 for user 'b'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s3 for user 'b'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. Error: APIError: QueryFailed: [1063]Permission denied: privilege [Select] is required on 'default'.'default'.'t1' for user 'b'@'%' with roles [public] a b/data_UUID_0000_00000000.parquet 1 0 NULL NULL === check db/table_id === diff --git a/tests/suites/0_stateless/18_rbac/18_0009_set_role.result b/tests/suites/0_stateless/18_rbac/18_0009_set_role.result index 2613072ba8dd..648b29ce7a35 100644 --- a/tests/suites/0_stateless/18_rbac/18_0009_set_role.result +++ b/tests/suites/0_stateless/18_rbac/18_0009_set_role.result @@ -20,8 +20,8 @@ testrole1 -- test 10: set default role as nonexisting_role, will fail Error: APIError: QueryFailed: [2206]Invalid role nonexistedrole for current session, available: public,testrole1,testrole2,testrole3 -- test 11: set secondary All | None, create object only check current role -Error: APIError: QueryFailed: [1063]Permission denied: privilege [CreateDatabase] is required on *.* for user 'test_c'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. -Error: APIError: QueryFailed: [1063]Permission denied: privilege [CreateDatabase] is required on *.* for user 'test_c'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [CreateDatabase] is required on *.* for user 'test_c'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [CreateDatabase] is required on *.* for user 'test_c'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. OWNERSHIP db_c ROLE role_c GRANT OWNERSHIP ON 'default'.'db_c'.* TO ROLE `role_c` OWNERSHIP db_d ROLE role_c GRANT OWNERSHIP ON 'default'.'db_d'.* TO ROLE `role_c` OWNERSHIP db_e ROLE public GRANT OWNERSHIP ON 'default'.'db_e'.* TO ROLE `public` diff --git a/tests/suites/0_stateless/18_rbac/18_0012_temp_table.result b/tests/suites/0_stateless/18_rbac/18_0012_temp_table.result index ac8703d0df12..c0989c15f9f5 100644 --- a/tests/suites/0_stateless/18_rbac/18_0012_temp_table.result +++ b/tests/suites/0_stateless/18_rbac/18_0012_temp_table.result @@ -5,7 +5,7 @@ >>>> create or replace database test >>>> grant role role1 to owner mysql: [Warning] Using a password on the command line interface can be insecure. -ERROR 1105 (HY000) at line 1: PermissionDenied. Code: 1063, Text = Permission denied: privilege [Create] is required on 'default'.'test'.* for user 'owner'@'%' with roles [role1]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage.. +ERROR 1105 (HY000) at line 1: PermissionDenied. Code: 1063, Text = Permission denied: privilege [Create] is required on 'default'.'test'.* for user 'owner'@'%' with roles [role1]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage.. mysql: [Warning] Using a password on the command line interface can be insecure. 2 1 diff --git a/tests/suites/1_stateful/00_stage/00_0012_stage_priv.result b/tests/suites/1_stateful/00_stage/00_0012_stage_priv.result index 87d27703b77f..1d1d6fa1d178 100644 --- a/tests/suites/1_stateful/00_stage/00_0012_stage_priv.result +++ b/tests/suites/1_stateful/00_stage/00_0012_stage_priv.result @@ -1,24 +1,24 @@ ==== check internal stage write priv === -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Write] is required on STAGE s2 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Write] is required on STAGE s2 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. Error: APIError: QueryFailed: [1063]Permission denied: privilege [Select] is required on 'default'.'default'.'test_table' for user 'u1'@'%' with roles [public] 20 160 160 1 ==== check external stage priv === -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Write] is required on STAGE s1 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Write] is required on STAGE s1 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. 20 160 160 -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s1 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s1 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. csv/data_UUID_0000_00000000.csv 20 0 NULL NULL ==== check internal stage read priv === -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s2 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s2 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. data_UUID_0000_00000000.csv 20 0 NULL NULL === check presign === -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Write] is required on STAGE presign_stage for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Write] is required on STAGE presign_stage for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. 000 -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE presign_stage for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE presign_stage for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. 000 -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Write] is required on STAGE s3 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Write] is required on STAGE s3 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. 1 1 356 -Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s3 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Database|Table|UDF|Stage. +Error: APIError: QueryFailed: [1063]Permission denied: privilege [Read] is required on STAGE s3 for user 'u1'@'%' with roles [public]. Note: Please ensure that your current role have the appropriate permissions to create a new Warehouse|Database|Table|UDF|Stage. Error: APIError: QueryFailed: [1063]Permission denied: privilege READ is required on stage s3 for user 'u1'@'%' Error: APIError: QueryFailed: [1063]Permission denied: privilege READ is required on stage s3 for user 'u1'@'%' Error: APIError: QueryFailed: [1063]Permission denied: privilege READ is required on stage s3 for user 'u1'@'%'