diff --git a/regression-test/data/auth_call/multi_load_cm.sh b/regression-test/data/auth_call/multi_load_cm.sh new file mode 100644 index 00000000000000..ec1274dd1eb457 --- /dev/null +++ b/regression-test/data/auth_call/multi_load_cm.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# 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. diff --git a/regression-test/data/auth_call/multi_load_data_1.csv b/regression-test/data/auth_call/multi_load_data_1.csv new file mode 100644 index 00000000000000..8e6b6f5ab16547 --- /dev/null +++ b/regression-test/data/auth_call/multi_load_data_1.csv @@ -0,0 +1,3 @@ +1,111 +2,222 +3,333 diff --git a/regression-test/data/auth_call/multi_load_data_2.csv b/regression-test/data/auth_call/multi_load_data_2.csv new file mode 100644 index 00000000000000..502600b75544df --- /dev/null +++ b/regression-test/data/auth_call/multi_load_data_2.csv @@ -0,0 +1,2 @@ +4,444 +5,555 diff --git a/regression-test/data/auth_call/routine_load_data.csv b/regression-test/data/auth_call/routine_load_data.csv new file mode 100644 index 00000000000000..33a3e989bb3833 --- /dev/null +++ b/regression-test/data/auth_call/routine_load_data.csv @@ -0,0 +1,2 @@ +1,2 +3,5 diff --git a/regression-test/data/auth_call/stream_load_cm.sh b/regression-test/data/auth_call/stream_load_cm.sh new file mode 100644 index 00000000000000..ec1274dd1eb457 --- /dev/null +++ b/regression-test/data/auth_call/stream_load_cm.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# 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. diff --git a/regression-test/data/auth_call/stream_load_data.csv b/regression-test/data/auth_call/stream_load_data.csv new file mode 100644 index 00000000000000..8e6b6f5ab16547 --- /dev/null +++ b/regression-test/data/auth_call/stream_load_data.csv @@ -0,0 +1,3 @@ +1,111 +2,222 +3,333 diff --git a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy index fec337f59ed54c..91604477becb45 100644 --- a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy +++ b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy @@ -1247,6 +1247,28 @@ class Suite implements GroovyInterceptable { Assert.assertEquals("SUCCESS", status) } + void waitingMVTaskFinishedByMvName(String dbName, String tableName) { + Thread.sleep(2000) + String showTasks = "SHOW ALTER TABLE MATERIALIZED VIEW from ${dbName} where TableName='${tableName}' ORDER BY CreateTime ASC" + String status = "NULL" + List> result + long startTime = System.currentTimeMillis() + long timeoutTimestamp = startTime + 5 * 60 * 1000 // 5 min + do { + result = sql(showTasks) + logger.info("result: " + result.toString()) + if (!result.isEmpty()) { + status = result.last().get(8) + } + logger.info("The state of ${showTasks} is ${status}") + Thread.sleep(1000); + } while (timeoutTimestamp > System.currentTimeMillis() && (status != 'FINISHED')) + if (status != "FINISHED") { + logger.info("status is not success") + } + Assert.assertEquals("FINISHED", status) + } + void waitingPartitionIsExpected(String tableName, String partitionName, boolean expectedStatus) { Thread.sleep(2000); String showPartitions = "show partitions from ${tableName}" diff --git a/regression-test/suites/auth_call/data/multi_table_csv.csv b/regression-test/suites/auth_call/data/multi_table_csv.csv new file mode 100644 index 00000000000000..bf47fc91d70a42 --- /dev/null +++ b/regression-test/suites/auth_call/data/multi_table_csv.csv @@ -0,0 +1,2 @@ +test_dml_multi_routine_load_auth_tb1|49|2023-08-08|FALSE|\N|16275|-2144851675|-2303421957908954634|-46526938720058765|-13141.142578|-686632233.230200|229942298.0|-152553823.0|2022-09-01 00:16:01|2023-03-25|2022-09-07 14:59:03|s||yvuILR2iNxfe8RRml|{"student": true, "name": "Alice", "grade": 9, "subjects": ["math", "science", "history"]}|true|1|2|3|4|5|6.0|7.0|888888888|999999999|2023-08-24|2023-08-24 12:00:00|2023-08-24|2023-08-24 12:00:00|我能吞下玻璃而不伤身体|我能吞下玻璃而不伤身体|我能吞下玻璃而不伤身体|{} +test_dml_multi_routine_load_auth_tb2|49|2023-08-08|FALSE|\N|16275|-2144851675|-2303421957908954634|-46526938720058765|-13141.142578|-686632233.230200|229942298.0|-152553823.0|2022-09-01 00:16:01|2023-03-25|2022-09-07 14:59:03|s||yvuILR2iNxfe8RRml|{"student": true, "name": "Alice", "grade": 9, "subjects": ["math", "science", "history"]}|true|1|2|3|4|5|6.0|7.0|888888888|999999999|2023-08-24|2023-08-24 12:00:00|2023-08-24|2023-08-24 12:00:00|我能吞下玻璃而不伤身体|我能吞下玻璃而不伤身体|我能吞下玻璃而不伤身体|{} diff --git a/regression-test/suites/auth_call/ddl/test_dml_multi_routine_load_auth_tb1.sql b/regression-test/suites/auth_call/ddl/test_dml_multi_routine_load_auth_tb1.sql new file mode 100644 index 00000000000000..91721ea0ccc525 --- /dev/null +++ b/regression-test/suites/auth_call/ddl/test_dml_multi_routine_load_auth_tb1.sql @@ -0,0 +1,46 @@ +CREATE TABLE test_dml_multi_routine_load_auth_tb1 +( + k00 INT NOT NULL, + k01 DATE NOT NULL, + k02 BOOLEAN NULL, + k03 TINYINT NULL, + k04 SMALLINT NULL, + k05 INT NULL, + k06 BIGINT NULL, + k07 LARGEINT NULL, + k08 FLOAT NULL, + k09 DOUBLE NULL, + k10 DECIMAL(9,1) NULL, + k11 DECIMALV3(9,1) NULL, + k12 DATETIME NULL, + k13 DATEV2 NULL, + k14 DATETIMEV2 NULL, + k15 CHAR NULL, + k16 VARCHAR NULL, + k17 STRING NULL, + k18 JSON NULL, + + INDEX idx_inverted_k104 (`k05`) USING INVERTED, + INDEX idx_inverted_k110 (`k11`) USING INVERTED, + INDEX idx_inverted_k113 (`k13`) USING INVERTED, + INDEX idx_inverted_k114 (`k14`) USING INVERTED, + INDEX idx_inverted_k117 (`k17`) USING INVERTED PROPERTIES("parser" = "english"), + INDEX idx_ngrambf_k115 (`k15`) USING NGRAM_BF PROPERTIES("gram_size"="3", "bf_size"="256"), + INDEX idx_ngrambf_k116 (`k16`) USING NGRAM_BF PROPERTIES("gram_size"="3", "bf_size"="256"), + INDEX idx_ngrambf_k117 (`k17`) USING NGRAM_BF PROPERTIES("gram_size"="3", "bf_size"="256"), + + INDEX idx_bitmap_k104 (`k02`) USING BITMAP + +) +DUPLICATE KEY(k00) +PARTITION BY RANGE(k01) +( + PARTITION p1 VALUES [('2023-08-01'), ('2023-08-11')), + PARTITION p2 VALUES [('2023-08-11'), ('2023-08-21')), + PARTITION p3 VALUES [('2023-08-21'), ('2023-09-01')) +) +DISTRIBUTED BY HASH(k00) BUCKETS 32 +PROPERTIES ( + "bloom_filter_columns"="k05", + "replication_num" = "1" +); diff --git a/regression-test/suites/auth_call/ddl/test_dml_multi_routine_load_auth_tb2.sql b/regression-test/suites/auth_call/ddl/test_dml_multi_routine_load_auth_tb2.sql new file mode 100644 index 00000000000000..e6230c2b4a29bf --- /dev/null +++ b/regression-test/suites/auth_call/ddl/test_dml_multi_routine_load_auth_tb2.sql @@ -0,0 +1,46 @@ +CREATE TABLE test_dml_multi_routine_load_auth_tb2 +( + k00 INT NOT NULL, + k01 DATE NOT NULL, + k02 BOOLEAN NULL, + k03 TINYINT NULL, + k04 SMALLINT NULL, + k05 INT NULL, + k06 BIGINT NULL, + k07 LARGEINT NULL, + k08 FLOAT NULL, + k09 DOUBLE NULL, + k10 DECIMAL(9,1) NULL, + k11 DECIMALV3(9,1) NULL, + k12 DATETIME NULL, + k13 DATEV2 NULL, + k14 DATETIMEV2 NULL, + k15 CHAR NULL, + k16 VARCHAR NULL, + k17 STRING NULL, + k18 JSON NULL, + + INDEX idx_inverted_k104 (`k05`) USING INVERTED, + INDEX idx_inverted_k110 (`k11`) USING INVERTED, + INDEX idx_inverted_k113 (`k13`) USING INVERTED, + INDEX idx_inverted_k114 (`k14`) USING INVERTED, + INDEX idx_inverted_k117 (`k17`) USING INVERTED PROPERTIES("parser" = "english"), + INDEX idx_ngrambf_k115 (`k15`) USING NGRAM_BF PROPERTIES("gram_size"="3", "bf_size"="256"), + INDEX idx_ngrambf_k116 (`k16`) USING NGRAM_BF PROPERTIES("gram_size"="3", "bf_size"="256"), + INDEX idx_ngrambf_k117 (`k17`) USING NGRAM_BF PROPERTIES("gram_size"="3", "bf_size"="256"), + + INDEX idx_bitmap_k104 (`k02`) USING BITMAP + +) +DUPLICATE KEY(k00) +PARTITION BY RANGE(k01) +( + PARTITION p1 VALUES [('2023-08-01'), ('2023-08-11')), + PARTITION p2 VALUES [('2023-08-11'), ('2023-08-21')), + PARTITION p3 VALUES [('2023-08-21'), ('2023-09-01')) +) +DISTRIBUTED BY HASH(k00) BUCKETS 32 +PROPERTIES ( + "bloom_filter_columns"="k05", + "replication_num" = "1" +); diff --git a/regression-test/suites/auth_call/test_account_management_grant_auth.groovy b/regression-test/suites/auth_call/test_account_management_grant_auth.groovy new file mode 100644 index 00000000000000..28cb71cdeacadb --- /dev/null +++ b/regression-test/suites/auth_call/test_account_management_grant_auth.groovy @@ -0,0 +1,100 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_account_management_grant_auth","p0,auth_call") { + + String user = 'test_account_management_grant_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_account_management_grant_auth_db' + String user_derive = 'test_account_management_grant_user_derive_role' + String role_derive = 'test_account_management_grant_role_derive_role' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql("DROP USER ${user_derive}") + try_sql """drop database if exists ${dbName}""" + + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE USER ${user_derive} IDENTIFIED BY '${pwd}';""" + exception "denied" + } + test { + sql """ALTER USER ${user_derive} IDENTIFIED BY "${pwd}";""" + exception "denied" + } + test { + sql """SET PASSWORD FOR '${user_derive}' = PASSWORD('${pwd}')""" + exception "denied" + } + test { + sql """SET PROPERTY FOR '${user_derive}' 'max_user_connections' = '1000';""" + exception "denied" + } + test { + sql """DROP user ${user_derive}""" + exception "denied" + } + test { + sql """SET LDAP_ADMIN_PASSWORD = PASSWORD('${pwd}')""" + exception "denied" + } + } + sql """grant grant_priv on *.*.* to '${user}'""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE USER ${user_derive} IDENTIFIED BY '${pwd}';""" + sql """ALTER USER ${user_derive} IDENTIFIED BY "${pwd}";""" + sql """SET PASSWORD FOR '${user_derive}' = PASSWORD('${pwd}')""" + test { + sql """SET PROPERTY FOR '${user_derive}' 'max_user_connections' = '1000';""" + exception "denied" + } + sql """DROP user ${user_derive}""" + test { + sql """SET LDAP_ADMIN_PASSWORD = PASSWORD('${pwd}')""" + exception "denied" + } + } + sql """revoke grant_priv on *.*.* from '${user}'""" + sql """grant admin_priv on *.*.* to '${user}'""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE USER ${user_derive} IDENTIFIED BY '${pwd}';""" + sql """ALTER USER ${user_derive} IDENTIFIED BY "${pwd}";""" + sql """SET PASSWORD FOR '${user_derive}' = PASSWORD('${pwd}')""" + sql """SET PROPERTY FOR '${user_derive}' 'max_user_connections' = '1000';""" + sql """DROP user ${user_derive}""" + sql """SET LDAP_ADMIN_PASSWORD = PASSWORD('${pwd}')""" + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") + try_sql("DROP role ${user_derive}") +} diff --git a/regression-test/suites/auth_call/test_account_management_role_auth.groovy b/regression-test/suites/auth_call/test_account_management_role_auth.groovy new file mode 100644 index 00000000000000..2a90eeedf67bc6 --- /dev/null +++ b/regression-test/suites/auth_call/test_account_management_role_auth.groovy @@ -0,0 +1,73 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_account_management_role_auth","p0,auth_call") { + + String user = 'test_account_management_role_auth_user' + String role = 'test_account_management_role_auth_role' + String pwd = 'C123_567p' + String dbName = 'test_account_management_role_auth_db' + + String role_derive = 'test_account_management_role_auth_derive_role' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql("DROP role ${role}") + try_sql("DROP role ${role_derive}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE ROLE ${role}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """GRANT '${role}' TO ${user};""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE ROLE ${role_derive}""" + exception "denied" + } + test { + sql """ALTER ROLE ${role_derive} COMMENT "this is my first role";""" + exception "denied" + } + test { + sql """DROP ROLE ${role_derive}""" + exception "denied" + } + } + sql """grant grant_priv on *.*.* to ROLE '${role}'""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE ROLE ${role_derive}""" + sql """ALTER ROLE ${role_derive} COMMENT "this is my first role";""" + sql """DROP ROLE ${role_derive}""" + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") + try_sql("DROP role ${role}") + try_sql("DROP role ${role_derive}") +} diff --git a/regression-test/suites/auth_call/test_account_management_user_auth.groovy b/regression-test/suites/auth_call/test_account_management_user_auth.groovy new file mode 100644 index 00000000000000..e6b0c203dd367e --- /dev/null +++ b/regression-test/suites/auth_call/test_account_management_user_auth.groovy @@ -0,0 +1,99 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_account_management_user_auth","p0,auth_call") { + + String user = 'test_account_management_user_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_account_management_user_auth_db' + String user_derive = 'test_account_management_user_derive_role' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql("DROP USER ${user_derive}") + try_sql """drop database if exists ${dbName}""" + + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE USER ${user_derive} IDENTIFIED BY '${pwd}';""" + exception "denied" + } + test { + sql """ALTER USER ${user_derive} IDENTIFIED BY "${pwd}";""" + exception "denied" + } + test { + sql """SET PASSWORD FOR '${user_derive}' = PASSWORD('${pwd}')""" + exception "denied" + } + test { + sql """SET PROPERTY FOR '${user_derive}' 'max_user_connections' = '1000';""" + exception "denied" + } + test { + sql """DROP user ${user_derive}""" + exception "denied" + } + test { + sql """SET LDAP_ADMIN_PASSWORD = PASSWORD('${pwd}')""" + exception "denied" + } + } + sql """grant grant_priv on *.*.* to '${user}'""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE USER ${user_derive} IDENTIFIED BY '${pwd}';""" + sql """ALTER USER ${user_derive} IDENTIFIED BY "${pwd}";""" + sql """SET PASSWORD FOR '${user_derive}' = PASSWORD('${pwd}')""" + test { + sql """SET PROPERTY FOR '${user_derive}' 'max_user_connections' = '1000';""" + exception "denied" + } + sql """DROP user ${user_derive}""" + test { + sql """SET LDAP_ADMIN_PASSWORD = PASSWORD('${pwd}')""" + exception "denied" + } + } + sql """revoke grant_priv on *.*.* from '${user}'""" + sql """grant admin_priv on *.*.* to '${user}'""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE USER ${user_derive} IDENTIFIED BY '${pwd}';""" + sql """ALTER USER ${user_derive} IDENTIFIED BY "${pwd}";""" + sql """SET PASSWORD FOR '${user_derive}' = PASSWORD('${pwd}')""" + sql """SET PROPERTY FOR '${user_derive}' 'max_user_connections' = '1000';""" + sql """DROP user ${user_derive}""" + sql """SET LDAP_ADMIN_PASSWORD = PASSWORD('${pwd}')""" + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") + try_sql("DROP role ${user_derive}") +} diff --git a/regression-test/suites/auth_call/test_assistant_command_auth.groovy b/regression-test/suites/auth_call/test_assistant_command_auth.groovy new file mode 100644 index 00000000000000..339bd86a6c1645 --- /dev/null +++ b/regression-test/suites/auth_call/test_assistant_command_auth.groovy @@ -0,0 +1,96 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_assistant_command_auth","p0,auth_call") { + + String user = 'test_assistant_command_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_assistant_command_auth_db' + String tableName = 'test_assistant_command_auth_tb' + String catalogName = 'test_assistant_command_auth_catalog' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + PARTITION BY RANGE(id) () + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + sql """alter table ${dbName}.${tableName} add partition p1 VALUES [("1"), ("2"));""" + def insert_res = sql """insert into ${dbName}.${tableName} values (1, "111");""" + logger.info("insert_res: " + insert_res) + + sql """create catalog if not exists ${catalogName} properties ( + 'type'='hms' + );""" + + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """use ${dbName}""" + exception "denied" + } + + test { + sql """DESC ${dbName}.${tableName} ALL;""" + exception "denied" + } + + sql """switch internal;""" + test { + sql """REFRESH CATALOG ${catalogName};""" + exception "denied" + } + + sql """SYNC;""" + } + + sql """grant select_PRIV on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """DESC ${dbName}.${tableName} ALL;""" + } + + sql """grant select_PRIV on ${catalogName}.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """REFRESH CATALOG ${catalogName};""" + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_cluster_management_auth.groovy b/regression-test/suites/auth_call/test_cluster_management_auth.groovy new file mode 100644 index 00000000000000..396bcdc0f9a544 --- /dev/null +++ b/regression-test/suites/auth_call/test_cluster_management_auth.groovy @@ -0,0 +1,138 @@ +// 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. + +import org.junit.Assert; + +suite ("test_cluster_management_auth","nonConcurrent,p0,auth_call") { + + def follower_ip = "" + def follower_host = "" + def observer_ip = "" + def observer_host = "" + def backend_ip = "" + def backend_host = "" + def backend_id = "" + + def is_exists_follower = { + def res = sql """show frontends;""" + for (int i = 0; i < res.size(); i++) { + if (res[i][7] == "FOLLOWER" && res[i][8] == "false" && res[i][11] == "true") { + follower_ip = res[i][1] + follower_host = res[i][2] + return true + } + } + return false; + } + def is_exists_observer = { + def res = sql """show frontends;""" + for (int i = 0; i < res.size(); i++) { + if (res[i][7] == "OBSERVER" && res[i][8] == "false" && res[i][11] == "true") { + observer_ip = res[i][1] + observer_host = res[i][2] + return true; + } + } + return false; + } + def is_exists_backends = { + def res = sql """show backends;""" + assertTrue(res.size() > 0) + backend_ip = res[0][1] + backend_host = res[0][2] + backend_id = res[0][0] + return true + } + + String user = 'test_cluster_management_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + // pipeline can't support delete node, it can affect other case + if (is_exists_follower()) { + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """show frontends""" + exception "denied" + } + test { + sql """ALTER SYSTEM add FOLLOWER '${follower_ip}:${follower_host}'""" + exception "denied" + } + test { + sql """ALTER SYSTEM DROP FOLLOWER '${follower_ip}:${follower_host}'""" + exception "denied" + } + } + } + + if (is_exists_observer()) { + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """show frontends""" + exception "denied" + } + test { + sql """ALTER SYSTEM add OBSERVER '${observer_ip}:${observer_host}'""" + exception "denied" + } + test { + sql """ALTER SYSTEM DROP OBSERVER '${observer_ip}:${observer_host}'""" + exception "denied" + } + } + } + + if (is_exists_backends()) { + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """show backends""" + exception "denied" + } + test { + sql """ALTER SYSTEM add backend '${backend_ip}:${backend_host}'""" + exception "denied" + } + test { + sql """ALTER SYSTEM MODIFY BACKEND "${backend_id}" SET ("tag.location" = "default");""" + exception "denied" + } + test { + sql """ALTER SYSTEM DECOMMISSION BACKEND '${backend_id}'""" + exception "denied" + } + test { + sql """ALTER SYSTEM DROP backend '${backend_ip}:${backend_host}'""" + exception "denied" + } + } + } + + try_sql("DROP USER ${user}") + +} diff --git a/regression-test/suites/auth_call/test_database_management_auth.groovy b/regression-test/suites/auth_call/test_database_management_auth.groovy new file mode 100644 index 00000000000000..33a26959619e5f --- /dev/null +++ b/regression-test/suites/auth_call/test_database_management_auth.groovy @@ -0,0 +1,143 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_database_management_auth","p0,auth_call") { + + String user = 'test_database_management_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_database_management_auth_db' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW FRONTEND CONFIG""" + exception "denied" + } + test { + sql """ADMIN SET FRONTEND CONFIG ("disable_balance" = "true");""" + exception "denied" + } + test { + sql """SET global time_zone = "Asia/Shanghai";""" + exception "denied" + } + test { + sql """INSTALL PLUGIN FROM "";""" + exception "denied" + } + test { + sql """UNINSTALL PLUGIN demo;""" + exception "denied" + } + test { + sql """ADMIN SET REPLICA STATUS PROPERTIES("tablet_id" = "000", "backend_id" = "000", "status" = "ok");""" + exception "denied" + } + test { + sql """ADMIN SET REPLICA VERSION PROPERTIES("tablet_id" = "0", "backend_id" = "0", "version" = "0");""" + exception "denied" + } + test { + sql """ADMIN SET TABLE tb PARTITION VERSION PROPERTIES("partition_id" = "0", "visible_version" = "0");""" + exception "denied" + } + test { + sql """admin set table tbl status properties("state" = "NORMAL");""" + exception "denied" + } + test { + sql """SHOW REPLICA DISTRIBUTION FROM tbl;""" + exception "denied" + } + test { + sql """SHOW REPLICA STATUS FROM db1.tbl1;""" + exception "denied" + } + test { + sql """ADMIN REPAIR TABLE tbl;""" + exception "denied" + } + test { + sql """ADMIN CANCEL REPAIR TABLE tbl PARTITION(p1);""" + exception "denied" + } + test { + sql """ADMIN CHECK TABLET (10000, 10001) PROPERTIES("type" = "consistency");""" + exception "denied" + } + test { + sql """SHOW TABLET DIAGNOSIS 0;""" + exception "denied" + } + test { + sql """ADMIN COPY TABLET 10010 PROPERTIES("backend_id" = "10001");""" + exception "denied" + } + test { + sql """show tablet storage format verbose;""" + exception "denied" + } + test { + sql """ADMIN CLEAN TRASH;""" + exception "denied" + } + test { + sql """RECOVER DATABASE db_name;""" + exception "denied" + } + test { + sql """ADMIN REBALANCE DISK;""" + exception "denied" + } + test { + sql """ADMIN CANCEL REBALANCE DISK;""" + exception "denied" + } + test { + sql """UNSET GLOBAL VARIABLE ALL;""" + exception "denied" + } + test { + sql """clean all query stats;""" + exception "denied" + } + test { + sql """REFRESH LDAP ALL;""" + exception "denied" + } + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_backup_auth.groovy b/regression-test/suites/auth_call/test_ddl_backup_auth.groovy new file mode 100644 index 00000000000000..3f5d1056e3d838 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_backup_auth.groovy @@ -0,0 +1,129 @@ +// 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. + +import org.junit.Assert; +import java.util.UUID + +suite("test_ddl_backup_auth","p0,auth_call") { + UUID uuid = UUID.randomUUID() + String randomValue = uuid.toString() + int hashCode = randomValue.hashCode() + hashCode = hashCode > 0 ? hashCode : hashCode * (-1) + + String user = 'test_ddl_backup_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_backup_auth_db' + String tableName = 'test_ddl_backup_auth_tb' + String repositoryName = 'test_ddl_backup_auth_rps' + String backupLabelName = 'test_ddl_backup_auth_backup_label' + hashCode.toString() + + String ak = getS3AK() + String sk = getS3SK() + String endpoint = getS3Endpoint() + String region = getS3Region() + String bucket = context.config.otherConfigs.get("s3BucketName") + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql("""DROP REPOSITORY `${repositoryName}`;""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + insert into ${dbName}.`${tableName}` values + (1, "111"), + (2, "222"), + (3, "333"); + """ + + sql """CREATE REPOSITORY `${repositoryName}` + WITH S3 + ON LOCATION "s3://${bucket}/${repositoryName}" + PROPERTIES + ( + "s3.endpoint" = "http://${endpoint}", + "s3.region" = "${region}", + "s3.access_key" = "${ak}", + "s3.secret_key" = "${sk}" + )""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """BACKUP SNAPSHOT ${dbName}.${backupLabelName} + TO ${repositoryName} + ON (${tableName}) + PROPERTIES ("type" = "full");""" + exception "denied" + } + test { + sql """CANCEL BACKUP FROM ${dbName};""" + exception "denied" + } + + test { + sql """SHOW BACKUP FROM ${dbName};""" + exception "denied" + } + + test { + sql """SHOW SNAPSHOT ON ${repositoryName};""" + exception "denied" + } + } + sql """grant LOAD_PRIV on ${dbName}.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """BACKUP SNAPSHOT ${dbName}.${backupLabelName} + TO ${repositoryName} + ON (${tableName}) + PROPERTIES ("type" = "full");""" + def res = sql """SHOW BACKUP FROM ${dbName};""" + logger.info("res: " + res) + assertTrue(res.size() == 1) + + sql """CANCEL BACKUP FROM ${dbName};""" + res = sql """SHOW BACKUP FROM ${dbName};""" + logger.info("res: " + res) + assertTrue(res[0][3] == "CANCELLED") + + test { + sql """SHOW SNAPSHOT ON ${repositoryName};""" + exception "denied" + } + } + + try_sql("""DROP REPOSITORY `${repositoryName}`;""") + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_catalog_auth.groovy b/regression-test/suites/auth_call/test_ddl_catalog_auth.groovy new file mode 100644 index 00000000000000..87c256c770e3b3 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_catalog_auth.groovy @@ -0,0 +1,113 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_catalog_auth","p0,auth_call") { + String user = 'test_ddl_catalog_auth_user' + String pwd = 'C123_567p' + String catalogName = 'test_ddl_catalog_auth_catalog' + String catalogNameNew = 'test_ddl_catalog_auth_catalog_new' + String catalogNameOther = 'test_ddl_catalog_auth_catalog_other' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + sql """create catalog if not exists ${catalogNameOther} properties ( + 'type'='hms' + );""" + + try_sql("DROP USER ${user}") + try_sql """drop catalog if exists ${catalogName}""" + try_sql """drop catalog if exists ${catalogNameNew}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + // ddl create + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create catalog if not exists ${catalogName} properties ( + 'type'='hms' + );""" + exception "denied" + } + def ctl_res = sql """show catalogs;""" + assertTrue(ctl_res.size() == 1) + } + sql """create catalog if not exists ${catalogName} properties ( + 'type'='hms' + );""" + sql """grant Create_priv on ${catalogName}.*.* to ${user}""" + sql """drop catalog ${catalogName}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """create catalog if not exists ${catalogName} properties ( + 'type'='hms' + );""" + sql """show create catalog ${catalogName}""" + def ctl_res = sql """show catalogs;""" + assertTrue(ctl_res.size() == 2) + } + + // ddl alter + // user alter + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ALTER CATALOG ${catalogName} RENAME ${catalogNameNew};""" + exception "denied" + } + } + sql """grant ALTER_PRIV on ${catalogName}.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ALTER CATALOG ${catalogName} RENAME ${catalogNameNew};""" + test { + sql """show create catalog ${catalogNameNew}""" + exception "denied" + } + def ctl_res = sql """show catalogs;""" + assertTrue(ctl_res.size() == 1) + } + // root alter + sql """ALTER CATALOG ${catalogNameNew} RENAME ${catalogName};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """show create catalog ${catalogName}""" + def ctl_res = sql """show catalogs;""" + assertTrue(ctl_res.size() == 2) + } + + // ddl drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """drop CATALOG ${catalogName};""" + exception "denied" + } + } + sql """grant DROP_PRIV on ${catalogName}.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """drop CATALOG ${catalogName};""" + def ctl_res = sql """show catalogs;""" + assertTrue(ctl_res.size() == 1) + } + + sql """drop catalog if exists ${catalogName}""" + sql """drop catalog if exists ${catalogNameOther}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_colocate_group_auth.groovy b/regression-test/suites/auth_call/test_ddl_colocate_group_auth.groovy new file mode 100644 index 00000000000000..d52519ced0aa4a --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_colocate_group_auth.groovy @@ -0,0 +1,70 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_colocate_group_auth","p0,auth_call") { + String user = 'test_ddl_colocate_group_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_colocate_group_auth_db' + String tableName = 'test_ddl_colocate_group_auth_tb' + String colocateGroupName = 'test_ddl_colocate_group_auth_cg' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1", + "colocate_with" = "${colocateGroupName}" + );""" + + // ddl create + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ALTER COLOCATE GROUP ${dbName}.${colocateGroupName} + SET ( + "replication_num"="1" + );""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ALTER COLOCATE GROUP ${dbName}.${colocateGroupName} + SET ( + "replication_num"="1" + );""" + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_database_auth.groovy b/regression-test/suites/auth_call/test_ddl_database_auth.groovy new file mode 100644 index 00000000000000..d4dc7356244dfd --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_database_auth.groovy @@ -0,0 +1,103 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_database_auth","p0,auth_call") { + String user = 'test_ddl_database_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_database_auth_db' + String dbNameNew = 'test_ddl_database_auth_db_new' + String tableName = 'test_ddl_database_auth_tb' + String tableNameNew = 'test_ddl_database_auth_tb_new' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql """drop database if exists ${dbNameNew}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + // ddl create + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create database ${dbName};""" + exception "denied" + } + def db_res = sql """show databases;""" + assertTrue(db_res.size() == 3) + } + sql """create database ${dbName};""" + sql """grant Create_priv on ${dbName}.* to ${user}""" + sql """drop database ${dbName};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """create database ${dbName};""" + sql """show create database ${dbName}""" + def db_res = sql """show databases;""" + assertTrue(db_res.size() == 4) + } + + // ddl alter + // user alter + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ALTER database ${dbName} RENAME ${dbNameNew};""" + exception "denied" + } + } + sql """grant ALTER_PRIV on ${dbName}.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ALTER database ${dbName} RENAME ${dbNameNew};""" + test { + sql """show create database ${dbNameNew}""" + exception "denied" + } + def db_res = sql """show databases;""" + assertTrue(db_res.size() == 3) + } + // root alter + sql """ALTER database ${dbNameNew} RENAME ${dbName};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """show create database ${dbName}""" + def db_res = sql """show databases;""" + assertTrue(db_res.size() == 4) + } + + // ddl drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """drop database ${dbName};""" + exception "denied" + } + } + sql """grant DROP_PRIV on ${dbName}.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """drop database ${dbName};""" + def ctl_res = sql """show databases;""" + assertTrue(ctl_res.size() == 3) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_encryptkey_auth.groovy b/regression-test/suites/auth_call/test_ddl_encryptkey_auth.groovy new file mode 100644 index 00000000000000..e24c88d55864b5 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_encryptkey_auth.groovy @@ -0,0 +1,72 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_encryptkey_auth","p0,auth_call") { + String user = 'test_ddl_encryptkey_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_encryptkey_auth_db' + String encryptkeyName = 'test_ddl_encryptkey_auth_ecyk' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE ENCRYPTKEY ${encryptkeyName} AS "ABCD123456789";""" + exception "denied" + } + test { + sql """SHOW ENCRYPTKEYS FROM ${dbName}""" + exception "denied" + } + test { + sql """DROP ENCRYPTKEY ${encryptkeyName};""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """CREATE ENCRYPTKEY ${encryptkeyName} AS "ABCD123456789";""" + def res = sql """SHOW ENCRYPTKEYS FROM ${dbName}""" + assertTrue(res.size() == 1) + def cur_secret_data = sql """SELECT HEX(AES_ENCRYPT("Doris is Great", KEY ${encryptkeyName}));""" + def cur_decrypt_data = sql """SELECT AES_DECRYPT(UNHEX('${cur_secret_data[0][0]}'), KEY ${encryptkeyName});""" + logger.info("cur_decrypt_data: " + cur_decrypt_data) + assertTrue(cur_decrypt_data[0][0] == "Doris is Great") + sql """DROP ENCRYPTKEY ${encryptkeyName};""" + res = sql """SHOW ENCRYPTKEYS FROM ${dbName}""" + assertTrue(res.size() == 0) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_file_auth.groovy b/regression-test/suites/auth_call/test_ddl_file_auth.groovy new file mode 100644 index 00000000000000..77ca5e6703f977 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_file_auth.groovy @@ -0,0 +1,89 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_file_auth","p0,auth_call") { + String user = 'test_ddl_file_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_file_auth_db' + String fileName = 'test_ddl_file_auth_file' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + String s3_endpoint = getS3Endpoint() + String bucket = context.config.otherConfigs.get("s3BucketName"); + def dataFilePath = "https://"+"${bucket}"+"."+"${s3_endpoint}"+"/regression/auth_test.key" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE FILE "${fileName}" IN ${dbName} + PROPERTIES + ( + "url" = "${dataFilePath}", + "catalog" = "internal" + );""" + exception "denied" + } + test { + sql """SHOW FILE FROM ${dbName};""" + exception "denied" + } + test { + sql """DROP FILE "${fileName}" from ${dbName} properties("catalog" = "internal");""" + exception "denied" + } + } + sql """grant select_priv on ${dbName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """SHOW FILE FROM ${dbName};""" + } + sql """revoke select_priv on ${dbName} from ${user}""" + + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE FILE "${fileName}" IN ${dbName} + PROPERTIES + ( + "url" = "${dataFilePath}", + "catalog" = "internal" + );""" + sql """use ${dbName}""" + def res = sql """SHOW FILE FROM ${dbName};""" + assertTrue(res.size() == 1) + + sql """DROP FILE "${fileName}" from ${dbName} properties("catalog" = "internal");""" + res = sql """SHOW FILE FROM ${dbName};""" + assertTrue(res.size() == 0) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_function_auth.groovy b/regression-test/suites/auth_call/test_ddl_function_auth.groovy new file mode 100644 index 00000000000000..f8fd51cf1cf641 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_function_auth.groovy @@ -0,0 +1,87 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_function_auth","p0,auth_call") { + String user = 'test_ddl_function_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_function_auth_db' + String functionName = 'test_ddl_function_auth_fct' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql("""DROP FUNCTION ${dbName}.${functionName}(INT)""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """grant select_priv on ${dbName}.* to ${user}""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE ALIAS FUNCTION ${dbName}.${functionName}(INT) WITH PARAMETER(id) AS CONCAT(LEFT(id, 3), '****', RIGHT(id, 4));""" + exception "denied" + } + + sql """use ${dbName}""" + def res = sql """show functions""" + assertTrue(res.size() == 0) + + test { + sql """DROP FUNCTION ${dbName}.${functionName}(INT)""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE ALIAS FUNCTION ${dbName}.${functionName}(INT) WITH PARAMETER(id) AS CONCAT(LEFT(id, 3), '****', RIGHT(id, 4));""" + sql """use ${dbName}""" + def res = sql """show functions""" + assertTrue(res.size() == 1) + + sql """select ${functionName}(1)""" + sql """DROP FUNCTION ${dbName}.${functionName}(INT)""" + res = sql """show functions""" + assertTrue(res.size() == 0) + } + sql """revoke admin_priv on *.*.* from ${user}""" + + // show + sql """CREATE ALIAS FUNCTION ${dbName}.${functionName}(INT) WITH PARAMETER(id) AS CONCAT(LEFT(id, 3), '****', RIGHT(id, 4));""" + sql """use ${dbName}""" + def func_res = sql """show functions""" + assertTrue(func_res.size() == 1) + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + def res = sql """SHOW CREATE FUNCTION ${dbName}.${functionName}(INT)""" + logger.info("res: " + res) + assertTrue(res.size() == 1) + } + + try_sql("""DROP FUNCTION ${dbName}.${functionName}(INT)""") + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_index_auth.groovy b/regression-test/suites/auth_call/test_ddl_index_auth.groovy new file mode 100644 index 00000000000000..93e6570c3a4b1d --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_index_auth.groovy @@ -0,0 +1,90 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_index_auth","p0,auth_call") { + String user = 'test_ddl_index_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_index_auth_db' + String tableName = 'test_ddl_index_auth_tb' + String indexName = 'test_ddl_index_auth_index' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """ + CREATE TABLE IF NOT EXISTS ${dbName}.${tableName} ( + id BIGINT, + username1 VARCHAR(30), + username2 VARCHAR(30), + username3 VARCHAR(30) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + ); + """ + def index_res_tmp = sql """SHOW INDEX FROM ${dbName}.${tableName};""" + assertTrue(index_res_tmp.size() == 0) + + // ddl create + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE INDEX IF NOT EXISTS ${indexName} ON ${dbName}.${tableName} (username3) USING INVERTED COMMENT 'balabala';""" + exception "denied" + } + + test { + sql """DROP INDEX IF EXISTS ${indexName} ON ${dbName}.${tableName};""" + exception "denied" + } + + test { + sql """show index FROM ${dbName}.${tableName};""" + exception "denied" + } + } + sql """grant ALTER_PRIV on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """CREATE INDEX IF NOT EXISTS ${indexName} ON ${dbName}.${tableName} (username3) USING INVERTED COMMENT 'balabala';""" + sql """show create table ${tableName}""" + def index_res = sql """SHOW INDEX FROM ${tableName};""" + assertTrue(index_res.size() == 1) + + sql """DROP INDEX IF EXISTS ${indexName} ON ${dbName}.${tableName};""" + index_res = sql """SHOW INDEX FROM ${tableName};""" + assertTrue(index_res.size() == 0) + + def show_index_res = sql """show index FROM ${dbName}.${tableName};""" + logger.info("show_index_res: " + show_index_res) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_job_auth.groovy b/regression-test/suites/auth_call/test_ddl_job_auth.groovy new file mode 100644 index 00000000000000..376cf8efbe90a6 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_job_auth.groovy @@ -0,0 +1,99 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_job_auth","p0,auth_call") { + String user = 'test_ddl_job_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_job_auth_db' + String tableName = 'test_ddl_job_auth_tb' + String tableNameDst = 'test_ddl_job_auth_tb_dst' + String jobName = 'test_ddl_job_auth_job' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql("""DROP JOB where jobName='${jobName}';""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """create table ${dbName}.${tableNameDst} like ${dbName}.${tableName}""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE JOB ${jobName} ON SCHEDULE AT '2020-01-01 00:00:00' DO INSERT INTO ${dbName}.${tableNameDst} SELECT * FROM ${dbName}.${tableName};""" + exception "denied" + } + test { + sql """PAUSE JOB where jobname='${jobName}';""" + exception "denied" + } + test { + sql """RESUME JOB where jobName= '${jobName}';""" + exception "denied" + } + + test { + sql """DROP JOB where jobName='${jobName}';""" + exception "denied" + } + + test { + sql """select * from jobs("type"="insert") where Name="${jobName}";""" + exception "ADMIN priv" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE JOB ${jobName} ON SCHEDULE AT '2100-01-01 00:00:00' DO INSERT INTO ${dbName}.${tableNameDst} SELECT * FROM ${dbName}.${tableName};""" + def res = sql """select * from jobs("type"="insert") where Name="${jobName}";""" + assertTrue(res.size() == 1) + + sql """PAUSE JOB where jobname='${jobName}';""" + res = sql """select * from jobs("type"="insert") where Name="${jobName}";""" + assertTrue(res[0][5] == "PAUSED") + + sql """RESUME JOB where jobName= '${jobName}';""" + res = sql """select * from jobs("type"="insert") where Name="${jobName}";""" + assertTrue(res[0][5] == "RUNNING") + + sql """DROP JOB where jobName='${jobName}';""" + res = sql """select * from jobs("type"="insert") where Name="${jobName}";""" + assertTrue(res.size() == 0) + } + + try_sql("""DROP JOB where jobName='${jobName}';""") + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_mask_view_auth.groovy b/regression-test/suites/auth_call/test_ddl_mask_view_auth.groovy new file mode 100644 index 00000000000000..319eec2963ee4d --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_mask_view_auth.groovy @@ -0,0 +1,74 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_mask_view_auth","p0,auth_call") { + String user = 'test_ddl_mask_view_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_mask_view_auth_db' + String tableName = 'test_ddl_mask_view_auth_tb' + String viewName = 'test_ddl_mask_view_auth_view' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + INSERT INTO ${dbName}.${tableName} (id, username) + VALUES (1, "111aaaAAA"), + (2, "222bbbBBB"), + (3, "333cccCCC") + """ + sql """CREATE VIEW ${dbName}.${viewName} (k1, v1) + AS + SELECT mask(id) as k1, mask(username) as v1 FROM ${dbName}.${tableName} GROUP BY k1, v1;""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """select * from ${dbName}.${viewName};""" + exception "denied" + } + } + sql """grant select_PRIV on ${dbName}.${viewName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """select * from ${dbName}.${viewName};""" + assertTrue(res[0][0] == "n") + assertTrue(res[0][1] == "nnnxxxXXX") + } + + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_mtmv_auth.groovy b/regression-test/suites/auth_call/test_ddl_mtmv_auth.groovy new file mode 100644 index 00000000000000..3aa146f58890e5 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_mtmv_auth.groovy @@ -0,0 +1,189 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_mtmv_auth","p0,auth_call") { + String user = 'test_ddl_mtmv_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_mtmv_auth_db' + String tableName = 'test_ddl_mtmv_auth_tb' + String mtmvName = 'test_ddl_mtmv_auth_mtmv' + String mtmvNameNew = 'test_ddl_mtmv_auth_mtmv_new' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + // ddl create + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE MATERIALIZED VIEW ${dbName}.${mtmvName} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + DISTRIBUTED BY RANDOM BUCKETS 1 + PROPERTIES ('replication_num' = '1') + AS select username, sum(id) as sum_id from ${dbName}.${tableName} group by username""" + exception "denied" + } + } + sql """CREATE MATERIALIZED VIEW ${dbName}.${mtmvName} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + DISTRIBUTED BY RANDOM BUCKETS 1 + PROPERTIES ('replication_num' = '1') + AS select username, sum(id) as sum_id from ${dbName}.${tableName} group by username""" + sql """grant Create_priv on ${dbName}.${mtmvName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE MATERIALIZED VIEW ${dbName}.${mtmvName} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + DISTRIBUTED BY RANDOM BUCKETS 1 + PROPERTIES ('replication_num' = '1') + AS select username, sum(id) as sum_id from ${dbName}.${tableName} group by username""" + exception "denied" + } + } + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + sql """drop MATERIALIZED VIEW ${dbName}.${mtmvName};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE MATERIALIZED VIEW ${dbName}.${mtmvName} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + DISTRIBUTED BY RANDOM BUCKETS 1 + PROPERTIES ('replication_num' = '1') + AS select username, sum(id) as sum_id from ${dbName}.${tableName} group by username""" + sql """show create materialized view ${dbName}.${mtmvName}""" + sql """use ${dbName}""" + def tb_res = sql """show tables;""" + assertTrue(tb_res.size() == 2) + } + sql """revoke select_priv on ${dbName}.${tableName} from ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """refresh MATERIALIZED VIEW ${mtmvName} auto;""" + + // insert and refresh mtmv + def job_name = getJobName(dbName, mtmvName) + + // cancel + def mv_tasks_res = sql """select * from tasks("type"="mv") where MvName="${mtmvName}";""" + assertTrue(mv_tasks_res.size() > 0) + try { + sql """CANCEL MATERIALIZED VIEW TASK ${mv_tasks_res[0][0]} on ${mtmvName};""" + } catch (Exception e) { + log.info(e.getMessage()) + assertTrue(e.getMessage().contains("no running task")) + } + + // pause + def job_status = sql """select * from jobs("type"="mv") where Name="${job_name}";""" + assertTrue(job_status[0][8] == "RUNNING") + sql """PAUSE MATERIALIZED VIEW JOB ON ${mtmvName};""" + job_status = sql """select * from jobs("type"="mv") where Name="${job_name}";""" + assertTrue(job_status[0][8] == "PAUSED") + + // resume + sql """RESUME MATERIALIZED VIEW JOB ON ${mtmvName};""" + job_status = sql """select * from jobs("type"="mv") where Name="${job_name}";""" + assertTrue(job_status[0][8] == "RUNNING") + } + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + + // ddl alter + // user alter + sql """revoke Create_priv on ${dbName}.${mtmvName} from ${user};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ALTER MATERIALIZED VIEW ${mtmvName} rename ${mtmvNameNew};""" + exception "denied" + } + test { + sql """show create materialized view ${dbName}.${mtmvName}""" + exception "denied" + } + } + sql """grant ALTER_PRIV on ${dbName}.${mtmvName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """show create materialized view ${mtmvName}""" + sql """ALTER MATERIALIZED VIEW ${mtmvName} rename ${mtmvNameNew};""" + test { + sql """show create materialized view ${mtmvNameNew}""" + exception "denied" + } + def tb_res = sql """show tables;""" + assertTrue(tb_res.size() == 1) + } + + // root alter + sql """use ${dbName}""" + sql """ALTER MATERIALIZED VIEW ${mtmvNameNew} RENAME ${mtmvName};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """show create materialized view ${mtmvName}""" + def db_res = sql """show tables;""" + assertTrue(db_res.size() == 2) + } + + // dml select + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """select username from ${dbName}.${mtmvName}""" + exception "denied" + } + } + sql """grant select_priv(username) on ${dbName}.${mtmvName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """select username from ${dbName}.${mtmvName}""" + } + sql """revoke select_priv(username) on ${dbName}.${mtmvName} from ${user}""" + + // ddl drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """use ${dbName}""" + sql """drop materialized view ${mtmvName};""" + exception "denied" + } + } + sql """grant DROP_PRIV on ${dbName}.${mtmvName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """drop materialized view ${mtmvName};""" + def ctl_res = sql """show tables;""" + assertTrue(ctl_res.size() == 1) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_mv_auth.groovy b/regression-test/suites/auth_call/test_ddl_mv_auth.groovy new file mode 100644 index 00000000000000..485343df67392c --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_mv_auth.groovy @@ -0,0 +1,117 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_mv_auth","p0,auth_call") { + String user = 'test_ddl_mv_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_mv_auth_db' + String tableName = 'test_ddl_mv_auth_tb' + String mvName = 'test_ddl_mv_auth_mv' + String rollupName = 'test_ddl_mv_auth_rollup' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + insert into ${dbName}.`${tableName}` values + (1, "111"), + (2, "222"), + (3, "333"); + """ + + // ddl create + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create materialized view ${mvName} as select username from ${dbName}.${tableName};""" + exception "denied" + } + test { + sql """alter table ${dbName}.${tableName} add rollup ${rollupName}(username)""" + exception "denied" + } + } + sql """grant select_priv(username) on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + test { + sql """create materialized view ${mvName} as select username from ${dbName}.${tableName};""" + exception "denied" + } + test { + sql """alter table ${dbName}.${tableName} add rollup ${rollupName}(username)""" + exception "denied" + } + } + sql """grant alter_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """create materialized view ${mvName} as select username from ${dbName}.${tableName};""" + waitingMVTaskFinishedByMvName(dbName, tableName) + sql """alter table ${dbName}.${tableName} add rollup ${rollupName}(username)""" + waitingMVTaskFinishedByMvName(dbName, tableName) + + def mv_res = sql """desc ${dbName}.${tableName} all;""" + logger.info("mv_res: " + mv_res) + assertTrue(mv_res.size() == 6) + } + sql """revoke alter_priv on ${dbName}.${tableName} from ${user}""" + sql """revoke select_priv(username) on ${dbName}.${tableName} from ${user}""" + + // ddl drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """DROP MATERIALIZED VIEW IF EXISTS ${mvName} ON ${dbName}.${tableName};""" + exception "denied" + } + test { + sql """ALTER TABLE ${dbName}.${tableName} DROP ROLLUP ${rollupName};""" + exception "denied" + } + } + sql """grant alter_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """DROP MATERIALIZED VIEW IF EXISTS ${mvName} ON ${tableName};""" + sql """ALTER TABLE ${dbName}.${tableName} DROP ROLLUP ${rollupName};""" + def mv_res = sql """desc ${dbName}.${tableName} all;""" + logger.info("mv_res: " + mv_res) + assertTrue(mv_res.size() == 2) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_part_table_auth.groovy b/regression-test/suites/auth_call/test_ddl_part_table_auth.groovy new file mode 100644 index 00000000000000..0d1bfb8551fb11 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_part_table_auth.groovy @@ -0,0 +1,80 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_part_table_auth","p0,auth_call") { + String user = 'test_ddl_part_table_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_part_table_auth_db' + String tableName = 'test_ddl_part_table_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + PARTITION BY RANGE(id) () + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + sql """alter table ${dbName}.${tableName} add partition p1 VALUES [("1"), ("2"));""" + def insert_res = sql """insert into ${dbName}.${tableName} values (1, "111");""" + logger.info("insert_res: " + insert_res) + + def partition_info = sql """show partitions from ${dbName}.${tableName}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """show partitions from ${dbName}.${tableName}""" + exception "denied" + } + test { + sql """show partition ${partition_info[0][0]}""" + exception "denied" + } + } + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """show partitions from ${dbName}.${tableName}""" + sql """show query stats""" + } + sql """revoke select_priv on ${dbName}.${tableName} from ${user}""" + + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """show partition ${partition_info[0][0]}""" + assertTrue(res.size() == 1) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_policy_storage_auth.groovy b/regression-test/suites/auth_call/test_ddl_policy_storage_auth.groovy new file mode 100644 index 00000000000000..bd87feb3148f53 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_policy_storage_auth.groovy @@ -0,0 +1,99 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_policy_storage_auth","p0,auth_call") { + String user = 'test_ddl_policy_storage_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_policy_storage_auth_db' + String storagePolicyName = 'test_ddl_policy_storage_auth_policy' + String resourceName = 'test_ddl_policy_storage_auth_rs' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql """DROP STORAGE POLICY if exists ${storagePolicyName}""" + try_sql("""DROP RESOURCE '${resourceName}'""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """CREATE RESOURCE IF NOT EXISTS "${resourceName}" + PROPERTIES( + "type" = "s3", + "AWS_ENDPOINT" = "bj.s3.comaaaa", + "AWS_REGION" = "bj", + "AWS_ROOT_PATH" = "path/to/rootaaaa", + "AWS_ACCESS_KEY" = "bbba", + "AWS_SECRET_KEY" = "aaaa", + "AWS_MAX_CONNECTIONS" = "50", + "AWS_REQUEST_TIMEOUT_MS" = "3000", + "AWS_CONNECTION_TIMEOUT_MS" = "1000", + "AWS_BUCKET" = "test-bucket", + "s3_validity_check" = "false" + );""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use regression_test;""" + test { + sql """CREATE STORAGE POLICY ${storagePolicyName} + PROPERTIES( + "storage_resource" = "${resourceName}", + "cooldown_datetime" = "2022-06-08 00:00:00" + );""" + exception "denied" + } + test { + sql """ALTER STORAGE POLICY ${storagePolicyName} PROPERTIES("cooldown_datetime" = "2023-06-09 00:00:00");""" + exception "denied" + } + test { + sql """DROP STORAGE POLICY ${storagePolicyName}""" + exception "denied" + } + test { + sql """SHOW STORAGE POLICY;""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE STORAGE POLICY ${storagePolicyName} + PROPERTIES( + "storage_resource" = "${resourceName}", + "cooldown_datetime" = "2022-06-08 00:00:00" + );""" + def res = sql """SHOW STORAGE POLICY;""" + assertTrue(res.size() >= 1) + sql """ALTER STORAGE POLICY ${storagePolicyName} PROPERTIES("cooldown_datetime" = "2023-06-09 00:00:00");""" + sql """DROP STORAGE POLICY ${storagePolicyName}""" + sql """SHOW STORAGE POLICY;""" + } + + try_sql("""DROP RESOURCE '${resourceName}'""") + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_repository_auth.groovy b/regression-test/suites/auth_call/test_ddl_repository_auth.groovy new file mode 100644 index 00000000000000..d41e2e3f1f4a1c --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_repository_auth.groovy @@ -0,0 +1,96 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_repository_auth","p0,auth_call") { + String user = 'test_ddl_repository_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_repository_auth_db' + String repositoryName = 'test_ddl_repository_auth_rps' + + String ak = getS3AK() + String sk = getS3SK() + String endpoint = getS3Endpoint() + String region = getS3Region() + String bucket = context.config.otherConfigs.get("s3BucketName"); + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql("""DROP REPOSITORY `${repositoryName}`;""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE REPOSITORY `${repositoryName}` + WITH S3 + ON LOCATION "s3://${bucket}/${repositoryName}" + PROPERTIES + ( + "s3.endpoint" = "http://${endpoint}", + "s3.region" = "${region}", + "s3.access_key" = "${ak}", + "s3.secret_key" = "${sk}" + )""" + exception "denied" + } + test { + sql """SHOW CREATE REPOSITORY for ${repositoryName};""" + exception "denied" + } + + test { + sql """DROP REPOSITORY `${repositoryName}`;""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE REPOSITORY `${repositoryName}` + WITH S3 + ON LOCATION "s3://${bucket}/${repositoryName}" + PROPERTIES + ( + "s3.endpoint" = "http://${endpoint}", + "s3.region" = "${region}", + "s3.access_key" = "${ak}", + "s3.secret_key" = "${sk}" + )""" + def res = sql """SHOW CREATE REPOSITORY for ${repositoryName};""" + assertTrue(res.size() > 0) + + sql """DROP REPOSITORY `${repositoryName}`;""" + test { + sql """SHOW CREATE REPOSITORY for ${repositoryName};""" + exception "repository not exist" + } + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_resource_auth.groovy b/regression-test/suites/auth_call/test_ddl_resource_auth.groovy new file mode 100644 index 00000000000000..c5fa8b78143478 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_resource_auth.groovy @@ -0,0 +1,100 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_resource_auth","p0,auth_call") { + String user = 'test_ddl_resource_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_resource_auth_db' + String resourceName = 'test_ddl_resource_auth_rs' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql("""DROP RESOURCE '${resourceName}'""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE RESOURCE IF NOT EXISTS "${resourceName}" + PROPERTIES( + "type" = "s3", + "AWS_ENDPOINT" = "bj.s3.comaaaa", + "AWS_REGION" = "bj", + "AWS_ROOT_PATH" = "path/to/rootaaaa", + "AWS_ACCESS_KEY" = "bbba", + "AWS_SECRET_KEY" = "aaaa", + "AWS_MAX_CONNECTIONS" = "50", + "AWS_REQUEST_TIMEOUT_MS" = "3000", + "AWS_CONNECTION_TIMEOUT_MS" = "1000", + "AWS_BUCKET" = "test-bucket", + "s3_validity_check" = "false" + );""" + exception "denied" + } + test { + sql """ALTER RESOURCE '${resourceName}' PROPERTIES ("s3.connection.maximum" = "100");""" + exception "denied" + } + + def res = sql """SHOW RESOURCES WHERE NAME = '${resourceName}'""" + assertTrue(res.size() == 0) + + test { + sql """DROP RESOURCE '${resourceName}'""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE RESOURCE IF NOT EXISTS "${resourceName}" + PROPERTIES( + "type" = "s3", + "AWS_ENDPOINT" = "bj.s3.comaaaa", + "AWS_REGION" = "bj", + "AWS_ROOT_PATH" = "path/to/rootaaaa", + "AWS_ACCESS_KEY" = "bbba", + "AWS_SECRET_KEY" = "aaaa", + "AWS_MAX_CONNECTIONS" = "50", + "AWS_REQUEST_TIMEOUT_MS" = "3000", + "AWS_CONNECTION_TIMEOUT_MS" = "1000", + "AWS_BUCKET" = "test-bucket", + "s3_validity_check" = "false" + );""" + def res = sql """SHOW RESOURCES WHERE NAME = '${resourceName}'""" + assertTrue(res.size() > 0) + sql """ALTER RESOURCE '${resourceName}' PROPERTIES ("s3.connection.maximum" = "100");""" + sql """DROP RESOURCE '${resourceName}'""" + res = sql """SHOW RESOURCES WHERE NAME = '${resourceName}'""" + assertTrue(res.size() == 0) + } + + try_sql("""DROP RESOURCE '${resourceName}'""") + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_restore_auth.groovy b/regression-test/suites/auth_call/test_ddl_restore_auth.groovy new file mode 100644 index 00000000000000..81658e76aa450f --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_restore_auth.groovy @@ -0,0 +1,184 @@ +// 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. + +import org.junit.Assert; +import java.util.UUID + +suite("test_ddl_restore_auth","p0,auth_call") { + UUID uuid = UUID.randomUUID() + String randomValue = uuid.toString() + int hashCode = randomValue.hashCode() + hashCode = hashCode > 0 ? hashCode : hashCode * (-1) + + def waitingBackupTaskFinished = { def curDbName -> + Thread.sleep(2000) + String showTasks = "SHOW BACKUP FROM ${curDbName};" + String status = "NULL" + List> result + long startTime = System.currentTimeMillis() + long timeoutTimestamp = startTime + 5 * 60 * 1000 // 5 min + do { + result = sql(showTasks) + logger.info("result: " + result.toString()) + assertTrue(result.size() == 1) + if (!result.isEmpty()) { + status = result.last().get(3) + } + logger.info("The state of ${showTasks} is ${status}") + Thread.sleep(1000); + } while (timeoutTimestamp > System.currentTimeMillis() && (status != 'FINISHED')) + if (status != "FINISHED") { + logger.info("status is not success") + } + assertTrue(status == "FINISHED") + return result[0][1] + } + + String user = 'test_ddl_restore_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_restore_auth_db' + String tableName = 'test_ddl_restore_auth_tb' + String repositoryName = 'test_ddl_restore_auth_rps' + String restoreLabelName = 'test_ddl_restore_auth_restore_label' + hashCode.toString() + + String ak = getS3AK() + String sk = getS3SK() + String endpoint = getS3Endpoint() + String region = getS3Region() + String bucket = context.config.otherConfigs.get("s3BucketName"); + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql("""DROP REPOSITORY `${repositoryName}`;""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + insert into ${dbName}.`${tableName}` values + (1, "111"), + (2, "222"), + (3, "333"); + """ + + sql """CREATE REPOSITORY `${repositoryName}` + WITH S3 + ON LOCATION "s3://${bucket}/${repositoryName}" + PROPERTIES + ( + "s3.endpoint" = "http://${endpoint}", + "s3.region" = "${region}", + "s3.access_key" = "${ak}", + "s3.secret_key" = "${sk}", + "delete_if_exists" = "true" + )""" + sql """BACKUP SNAPSHOT ${dbName}.${restoreLabelName} + TO ${repositoryName} + ON (${tableName}) + PROPERTIES ("type" = "full");""" + def real_label = waitingBackupTaskFinished(dbName) + def backup_timestamp = sql """SHOW SNAPSHOT ON ${repositoryName};""" + logger.info("backup_timestamp: " + backup_timestamp) + def real_timestamp + for (int i = 0; i < backup_timestamp.size(); i++) { + if (backup_timestamp[i][0] == real_label) { + real_timestamp = backup_timestamp[i][1] + break + } + } + + sql """truncate table ${dbName}.`${tableName}`""" + + sql """grant admin_PRIV on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def show_snapshot_res = sql """SHOW SNAPSHOT ON ${repositoryName};""" + logger.info("show_snapshot_res: " + show_snapshot_res) + } + sql """revoke admin_PRIV on *.*.* from ${user}""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW SNAPSHOT ON ${repositoryName};""" + exception "denied" + } + test { + sql """RESTORE SNAPSHOT ${dbName}.`${restoreLabelName}` + FROM `${repositoryName}` + ON ( `${tableName}` ) + PROPERTIES + ( + "backup_timestamp"="${real_timestamp}", + "replication_num" = "1" + );""" + exception "denied" + } + test { + sql """CANCEL RESTORE FROM ${dbName};""" + exception "denied" + } + test { + sql """SHOW RESTORE FROM ${dbName};""" + exception "denied" + } + test { + sql """SHOW SYNC JOB FROM `${dbName}`;""" + exception "denied" + } + } + sql """grant LOAD_PRIV on ${dbName}.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """RESTORE SNAPSHOT ${dbName}.`${restoreLabelName}` + FROM `${repositoryName}` + ON ( `${tableName}` ) + PROPERTIES + ( + "backup_timestamp"="${real_timestamp}", + "replication_num" = "1" + );""" + def res = sql """SHOW RESTORE FROM ${dbName};""" + logger.info("res: " + res) + assertTrue(res.size() == 1) + + sql """CANCEL RESTORE FROM ${dbName};""" + res = sql """SHOW RESTORE FROM ${dbName};""" + logger.info("res: " + res) + assertTrue(res[0][4] == "CANCELLED") + + sql """SHOW SYNC JOB FROM `${dbName}`;""" + } + + try_sql("""DROP REPOSITORY `${repositoryName}`;""") + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_row_policy_auth.groovy b/regression-test/suites/auth_call/test_ddl_row_policy_auth.groovy new file mode 100644 index 00000000000000..106e22d20e9024 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_row_policy_auth.groovy @@ -0,0 +1,90 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_row_policy_auth","p0,auth_call") { + String user = 'test_ddl_row_policy_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_row_policy_auth_db' + String tableName = 'test_ddl_row_policy_auth_tb' + String rowPolicyName = 'test_ddl_row_policy_auth_rp' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql """DROP ROW POLICY ${rowPolicyName} on ${dbName}.${tableName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + // ddl create + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE ROW POLICY ${rowPolicyName} ON ${dbName}.${tableName} AS RESTRICTIVE TO ${user} USING (id = 1);""" + exception "denied" + } + test { + sql """SHOW ROW POLICY FOR ${user}""" + exception "denied" + } + test { + sql """DROP ROW POLICY ${rowPolicyName} on ${dbName}.${tableName} for ${user}""" + exception "denied" + } + + } + sql """grant grant_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE ROW POLICY ${rowPolicyName} ON ${dbName}.${tableName} AS RESTRICTIVE TO ${user} USING (id = 1);""" + + test { + sql """SHOW ROW POLICY FOR ${user}""" + exception "denied" + } + + sql """DROP ROW POLICY ${rowPolicyName} on ${dbName}.${tableName} for ${user}""" + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE ROW POLICY ${rowPolicyName} ON ${dbName}.${tableName} AS RESTRICTIVE TO ${user} USING (id = 1);""" + def res = sql """SHOW ROW POLICY FOR ${user}""" + assertTrue(res.size() == 1) + + sql """DROP ROW POLICY ${rowPolicyName} on ${dbName}.${tableName} for ${user}""" + res = sql """SHOW ROW POLICY FOR ${user}""" + assertTrue(res.size() == 0) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_sql_block_rule_auth.groovy b/regression-test/suites/auth_call/test_ddl_sql_block_rule_auth.groovy new file mode 100644 index 00000000000000..f5693686fada17 --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_sql_block_rule_auth.groovy @@ -0,0 +1,102 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_sql_block_rule_auth","p0,auth_call") { + String user = 'test_ddl_sbr_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_sbr_auth_db' + String tableName = 'test_ddl_sbr_auth_tb' + String sqlBlockRuleName = 'test_ddl_sbr_auth_sbr' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql("""DROP SQL_BLOCK_RULE ${sqlBlockRuleName};""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE SQL_BLOCK_RULE ${sqlBlockRuleName} + PROPERTIES( + "sql"="select \\* from ${dbName}.${tableName}", + "partition_num" = "30", + "global"="false", + "enable"="true" + );""" + exception "denied" + } + test { + sql """ALTER SQL_BLOCK_RULE ${sqlBlockRuleName} PROPERTIES("partition_num" = "10")""" + exception "denied" + } + + test { + sql """SHOW SQL_BLOCK_RULE FOR ${sqlBlockRuleName};""" + exception "denied" + } + + test { + sql """DROP SQL_BLOCK_RULE ${sqlBlockRuleName};""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE SQL_BLOCK_RULE ${sqlBlockRuleName} + PROPERTIES( + "sql"="select \\\\* from ${dbName}\\\\.${tableName}", + "global"="false", + "enable"="true" + );""" + def res = sql """SHOW SQL_BLOCK_RULE FOR ${sqlBlockRuleName};""" + assertTrue(res.size() > 0) + sql """SET PROPERTY FOR '${user}' 'sql_block_rules' = '${sqlBlockRuleName}';""" + test { + sql """select * from ${dbName}.${tableName}""" + exception "sql block rule" + } + sql """ALTER SQL_BLOCK_RULE ${sqlBlockRuleName} PROPERTIES("enable"="true")""" + sql """DROP SQL_BLOCK_RULE ${sqlBlockRuleName};""" + res = sql """SHOW SQL_BLOCK_RULE FOR ${sqlBlockRuleName};""" + assertTrue(res.size() == 0) + sql """select * from ${dbName}.${tableName}""" + } + + try_sql("""DROP SQL_BLOCK_RULE ${sqlBlockRuleName};""") + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_table_auth.groovy b/regression-test/suites/auth_call/test_ddl_table_auth.groovy new file mode 100644 index 00000000000000..4c74699f55fcbf --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_table_auth.groovy @@ -0,0 +1,267 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_table_auth","p0,auth_call") { + String user = 'test_ddl_table_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_table_auth_db' + String tableName = 'test_ddl_table_auth_tb' + String tableNameNew = 'test_ddl_table_auth_tb_new' + String cteLikeDstDb = 'test_ddl_table_cte_like_dst_db' + String cteLikeDstTb = 'test_ddl_table_cte_like_dst_tb' + String cteSelectDstDb = 'test_ddl_table_cte_select_dst_db' + String cteSelectDstTb = 'test_ddl_table_cte_select_dst_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql """drop database if exists ${cteLikeDstDb}""" + try_sql """drop database if exists ${cteSelectDstDb}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + def waitingChangeTaskFinished = { def curDb -> + Thread.sleep(2000) + sql """use ${curDb}""" + String showTasks = "SHOW ALTER TABLE COLUMN order by CreateTime;" + String status = "NULL" + List> result + long startTime = System.currentTimeMillis() + long timeoutTimestamp = startTime + 5 * 60 * 1000 // 5 min + do { + result = sql(showTasks) + logger.info("result: " + result.toString()) + if (!result.isEmpty()) { + status = result.last().get(9) + } + logger.info("The state of ${showTasks} is ${status}") + Thread.sleep(1000); + } while (timeoutTimestamp > System.currentTimeMillis() && (status != 'FINISHED')) + if (status != "FINISHED") { + logger.info("status is not success") + } + Assert.assertEquals("FINISHED", status) + } + + // ddl create + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + exception "denied" + } + def res = sql """show query stats;""" + logger.info("res:" + res) + + test { + sql """SHOW FULL COLUMNS FROM ${dbName}.${tableName};""" + exception "denied" + } + } + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """grant Create_priv on ${dbName}.${tableName} to ${user}""" + sql """drop table ${dbName}.${tableName};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """use ${dbName}""" + sql """show create table ${tableName}""" + def db_res = sql """show tables;""" + assertTrue(db_res.size() == 1) + + def col_res = sql """SHOW FULL COLUMNS FROM ${dbName}.${tableName};""" + logger.info("col_res: " + col_res) + assertTrue(col_res.size() == 2) + } + + // ddl alter + // user alter + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ALTER table ${tableName} RENAME ${tableNameNew};""" + exception "denied" + } + test { + sql """ALTER TABLE ${dbName}.${tableName} ADD COLUMN new_col INT KEY DEFAULT "0";""" + exception "denied" + } + def res = sql """SHOW ALTER TABLE COLUMN;""" + assertTrue(res.size() == 0) + } + sql """grant ALTER_PRIV on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """ALTER table ${tableName} RENAME ${tableNameNew};""" + + test { + sql """show create table ${tableNameNew}""" + exception "denied" + } + def tb_res = sql """show tables;""" + assertTrue(tb_res.size() == 0) + } + // root alter + sql """use ${dbName}""" + sql """ALTER table ${tableNameNew} RENAME ${tableName};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """show create table ${tableName}""" + def db_res = sql """show tables;""" + assertTrue(db_res.size() == 1) + } + + // show + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """ALTER TABLE ${tableName} ADD COLUMN new_col INT KEY DEFAULT "0";""" + def res = sql """SHOW ALTER TABLE COLUMN;""" + assertTrue(res.size() == 1) + } + + // dml select + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """select id from ${dbName}.${tableName}""" + exception "denied" + } + } + sql """grant select_priv(id) on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """select id from ${dbName}.${tableName}""" + } + sql """revoke select_priv(id) on ${dbName}.${tableName} from ${user}""" + + // ddl create table like + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create table ${cteLikeDstDb}.${cteLikeDstTb} like ${dbName}.${tableName};""" + exception "denied" + } + } + sql """create database ${cteLikeDstDb}""" + sql """create table ${cteLikeDstDb}.${cteLikeDstTb} like ${dbName}.${tableName};""" + sql """grant Create_priv on ${cteLikeDstDb}.${cteLikeDstTb} to ${user}""" + sql """drop table ${cteLikeDstDb}.${cteLikeDstTb};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create table ${cteLikeDstDb}.${cteLikeDstTb} like ${dbName}.${tableName};""" + exception "denied" + } + } + sql """grant SELECT_PRIV on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """create table ${cteLikeDstDb}.${cteLikeDstTb} like ${dbName}.${tableName};""" + } + sql """revoke SELECT_PRIV on ${dbName}.${tableName} from ${user}""" + + // ddl create table select + sql """create database ${cteSelectDstDb}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create table ${cteSelectDstDb}.${cteSelectDstTb}(username) PROPERTIES("replication_num" = "1") as select username from ${dbName}.${tableName};""" + exception "denied" + } + } + sql """create table ${cteSelectDstDb}.${cteSelectDstTb}(username) PROPERTIES("replication_num" = "1") as select username from ${dbName}.${tableName};""" + sql """grant Create_priv on ${cteSelectDstDb}.${cteSelectDstTb} to ${user}""" + sql """drop table ${cteSelectDstDb}.${cteSelectDstTb}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create table ${cteSelectDstDb}.${cteSelectDstTb}(username) PROPERTIES("replication_num" = "1") as select username from ${dbName}.${tableName};""" + exception "denied" + } + } + sql """create table ${cteSelectDstDb}.${cteSelectDstTb}(username) PROPERTIES("replication_num" = "1") as select username from ${dbName}.${tableName};""" + sql """grant LOAD_PRIV on ${cteSelectDstDb}.${cteSelectDstTb} to ${user}""" + sql """drop table ${cteSelectDstDb}.${cteSelectDstTb}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create table ${cteSelectDstDb}.${cteSelectDstTb}(username) PROPERTIES("replication_num" = "1") as select username from ${dbName}.${tableName};""" + exception "denied" + } + } + sql """grant select_priv(username) on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """create table ${cteSelectDstDb}.${cteSelectDstTb}(username) PROPERTIES("replication_num" = "1") as select username from ${dbName}.${tableName};""" + } + + waitingChangeTaskFinished(dbName) + // ddl truncate + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """use ${dbName}""" + sql """truncate table ${tableName};""" + exception "denied" + } + } + sql """grant LOAD_PRIV on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """truncate table ${tableName};""" + } + + // ddl drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """use ${dbName}""" + sql """drop table ${tableName};""" + exception "denied" + } + } + sql """grant DROP_PRIV on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """drop table ${tableName};""" + def ctl_res = sql """show tables;""" + assertTrue(ctl_res.size() == 0) + } + + + sql """drop database if exists ${dbName}""" + sql """drop database if exists ${cteLikeDstDb}""" + sql """drop database if exists ${cteSelectDstDb}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_view_auth.groovy b/regression-test/suites/auth_call/test_ddl_view_auth.groovy new file mode 100644 index 00000000000000..bf967e54fcb02c --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_view_auth.groovy @@ -0,0 +1,154 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_view_auth","p0,auth_call") { + String user = 'test_ddl_view_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_view_auth_db' + String tableName = 'test_ddl_view_auth_tb' + String viewName = 'test_ddl_view_auth_view' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + INSERT INTO ${dbName}.${tableName} (id, username) + VALUES (1, "111"), + (2, "222"), + (3, "333") + """ + + // ddl create + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE VIEW ${dbName}.${viewName} (k1, v1) + AS + SELECT id as k1, SUM(id) FROM ${dbName}.${tableName} + WHERE id = 1 GROUP BY k1;""" + exception "denied" + } + test { + sql """SHOW VIEW from ${tableName} from ${dbName}""" + exception 'denied' + } + } + sql """grant select_priv(id) on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE VIEW ${dbName}.${viewName} (k1, v1) + AS + SELECT id as k1, SUM(id) FROM ${dbName}.${tableName} + WHERE id = 1 GROUP BY k1;""" + exception 'denied' + } + def res = sql """SHOW VIEW from ${tableName} from ${dbName}""" + assertTrue(res.size() == 0) + } + sql """CREATE VIEW ${dbName}.${viewName} (k1, v1) + AS + SELECT id as k1, SUM(id) FROM ${dbName}.${tableName} + WHERE id = 1 GROUP BY k1;""" + sql """grant Create_priv on ${dbName}.${viewName} to ${user}""" + sql """drop view ${dbName}.${viewName}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE VIEW ${dbName}.${viewName} (k1, v1) + AS + SELECT id as k1, SUM(id) FROM ${dbName}.${tableName} + WHERE id = 1 GROUP BY k1;""" + + def res = sql """SHOW VIEW from ${tableName} from ${dbName}""" + assertTrue(res.size() == 1) + } + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE VIEW ${dbName}.${viewName} (k1, v1) + AS + SELECT username as k1, SUM(id) FROM ${dbName}.${tableName} + WHERE id = 1 GROUP BY k1;""" + exception 'denied' + } + } + + // ddl alter + // user alter + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """alter VIEW ${dbName}.${viewName} (k1, v1) + AS + SELECT id as k1, SUM(id) FROM ${dbName}.${tableName} + WHERE id = 1 GROUP BY k1;""" + exception 'denied' + } + } + sql """grant ALTER_PRIV on ${dbName}.${viewName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """alter VIEW ${dbName}.${viewName} (k1, v1) + AS + SELECT id as k1, SUM(id) FROM ${dbName}.${tableName} + WHERE id = 1 GROUP BY k1;""" + } + + // dml show + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """select * from ${dbName}.${viewName};""" + exception "denied" + } + } + sql """grant select_PRIV on ${dbName}.${viewName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """select * from ${dbName}.${viewName};""" + } + + // ddl drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """drop table ${dbName}.${viewName};""" + exception 'denied' + } + } + sql """grant DROP_PRIV on ${dbName}.${viewName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """drop view ${viewName};""" + def ctl_res = sql """show tables;""" + assertTrue(ctl_res.size() == 1) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_ddl_workload_group_auth.groovy b/regression-test/suites/auth_call/test_ddl_workload_group_auth.groovy new file mode 100644 index 00000000000000..7657055d9d4fcb --- /dev/null +++ b/regression-test/suites/auth_call/test_ddl_workload_group_auth.groovy @@ -0,0 +1,86 @@ +// 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. + +import org.junit.Assert; + +suite("test_ddl_workload_group_auth","p0,auth_call") { + String user = 'test_ddl_wg_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_ddl_wg_auth_db' + String workloadGroupName = 'test_ddl_wg_auth_wg' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql("""drop workload group if exists ${workloadGroupName};""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + // ddl create,show,drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """CREATE WORKLOAD GROUP "${workloadGroupName}" + PROPERTIES ( + "cpu_share"="10" + );""" + exception "denied" + } + test { + sql """alter workload group ${workloadGroupName} + properties ( + "cpu_share"="20" + );""" + exception "denied" + } + + def res = sql """show workload groups like '${workloadGroupName}'""" + assertTrue(res.size() == 0) + + test { + sql """drop workload group if exists ${workloadGroupName};""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """CREATE WORKLOAD GROUP "${workloadGroupName}" + PROPERTIES ( + "cpu_share"="10" + );""" + def res = sql """show workload groups like '${workloadGroupName}'""" + assertTrue(res.size() > 0) + sql """alter workload group ${workloadGroupName} + properties ( + "cpu_share"="20" + );""" + sql """drop workload group if exists ${workloadGroupName};""" + res = sql """show workload groups like '${workloadGroupName}'""" + assertTrue(res.size() == 0) + } + + try_sql("""drop workload group if exists ${workloadGroupName};""") + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_analyze_auth.groovy b/regression-test/suites/auth_call/test_dml_analyze_auth.groovy new file mode 100644 index 00000000000000..5db5da61f945f0 --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_analyze_auth.groovy @@ -0,0 +1,93 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_analyze_auth","p0,auth_call") { + + String user = 'test_dml_analyze_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_analyze_auth_db' + String tableName = 'test_dml_analyze_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ + analyze table ${dbName}.${tableName} with sync; + """ + exception "denied" + } + test { + sql """show table stats ${dbName}.${tableName};""" + exception "denied" + } + test { + sql """show table status from ${dbName};""" + exception "denied" + } + test { + sql """show column stats ${dbName}.${tableName};""" + exception "denied" + } + } + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ + analyze table ${dbName}.${tableName} with sync; + """ + def col_stats = sql """show column stats ${dbName}.${tableName};""" + logger.info("col_stats: " + col_stats) + assertTrue(col_stats.size() == 2) + + sql """show table stats ${dbName}.${tableName};""" + } + sql """grant select_priv on ${dbName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """show table status from ${dbName};""" + } + + def res = sql """show column stats ${dbName}.${tableName};""" + logger.info("res: " + res) + assertTrue(res.size() == 2) + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_broker_load_auth.groovy b/regression-test/suites/auth_call/test_dml_broker_load_auth.groovy new file mode 100644 index 00000000000000..cb9d6cd7f2a189 --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_broker_load_auth.groovy @@ -0,0 +1,184 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_broker_load_auth","p0,auth_call") { + + UUID uuid = UUID.randomUUID() + String randomValue = uuid.toString() + int hashCode = randomValue.hashCode() + hashCode = hashCode > 0 ? hashCode : hashCode * (-1) + + String user = 'test_dml_broker_load_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_broker_load_auth_db' + String tableName = 'test_dml_broker_load_auth_tb' + String loadLabelName = 'test_dml_broker_load_auth_label' + hashCode.toString() + + String ak = getS3AK() + String sk = getS3SK() + String endpoint = getS3Endpoint() + String region = getS3Region() + String bucket = getS3BucketName() + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """CREATE TABLE IF NOT EXISTS ${dbName}.${tableName} ( + C_CUSTKEY INTEGER NOT NULL, + C_NAME VARCHAR(25) NOT NULL, + C_ADDRESS VARCHAR(40) NOT NULL, + C_NATIONKEY INTEGER NOT NULL, + C_PHONE CHAR(15) NOT NULL, + C_ACCTBAL DECIMAL(15,2) NOT NULL, + C_MKTSEGMENT CHAR(10) NOT NULL, + C_COMMENT VARCHAR(117) NOT NULL + ) + DUPLICATE KEY(C_CUSTKEY, C_NAME) + DISTRIBUTED BY HASH(C_CUSTKEY) BUCKETS 32 + PROPERTIES ( + "replication_num" = "1" + );""" + + sql """use ${dbName}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ + LOAD LABEL ${loadLabelName} ( + DATA INFILE("s3://${bucket}/regression/tpch/sf0.01/customer.csv.gz") + INTO TABLE ${tableName} + COLUMNS TERMINATED BY "|" + (c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_mktsegment, c_comment, temp) + ) + WITH S3 ( + "AWS_ACCESS_KEY" = "$ak", + "AWS_SECRET_KEY" = "$sk", + "AWS_ENDPOINT" = "$endpoint", + "AWS_REGION" = "$region", + "compress_type" = "GZ" + ) + properties( + "timeout" = "28800", + "exec_mem_limit" = "8589934592" + ) + """ + exception "denied" + } + + def res = sql """SHOW LOAD FROM ${dbName} WHERE LABEL LIKE '${loadLabelName}'""" + assertTrue(res.size() == 0) + + res = sql """SHOW STREAM LOAD FROM ${dbName} WHERE LABEL = "${loadLabelName}";""" + assertTrue(res.size() == 0) + + test { + sql """CLEAN LABEL ${loadLabelName} FROM ${dbName};""" + exception "denied" + } + } + sql """grant load_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName};""" + sql """ + LOAD LABEL ${loadLabelName} ( + DATA INFILE("s3://${bucket}/regression/tpch/sf0.01/customer.csv.gz") + INTO TABLE ${tableName} + COLUMNS TERMINATED BY "|" + (c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_mktsegment, c_comment, temp) + ) + WITH S3 ( + "AWS_ACCESS_KEY" = "$ak", + "AWS_SECRET_KEY" = "$sk", + "AWS_ENDPOINT" = "$endpoint", + "AWS_REGION" = "$region", + "compress_type" = "GZ" + ) + properties( + "timeout" = "28800", + "exec_mem_limit" = "8589934592" + ) + """ + + def res = sql """SHOW LOAD FROM ${dbName} WHERE LABEL LIKE '${loadLabelName}'""" + logger.info("res: " + res) + assertTrue(res.size() == 0) + + test { + sql """CANCEL LOAD + FROM ${dbName} + WHERE LABEL = "${loadLabelName}";""" + exception "denied" + } + + test { + sql """CLEAN LABEL ${loadLabelName} FROM ${dbName};""" + exception "denied" + } + } + def warn_res = sql """SHOW LOAD WARNINGS FROM ${dbName} WHERE LABEL = '${loadLabelName}';""" + logger.info("warn_res: " + warn_res) + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW LOAD WARNINGS FROM ${dbName} WHERE LABEL = '${loadLabelName}';""" + exception 'job is not exist' + } + } + sql """grant load_priv on ${dbName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def show_warn_res = sql """SHOW LOAD WARNINGS FROM ${dbName} WHERE LABEL = '${loadLabelName}';""" + logger.info("show_warn_res: " + show_warn_res) + } + sql """revoke load_priv on ${dbName} from ${user}""" + + sql """grant load_priv on ${dbName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """SHOW LOAD FROM ${dbName} WHERE LABEL LIKE '${loadLabelName}'""" + logger.info("res: " + res) + assertTrue(res.size() == 1) + + test { + sql """SHOW TRANSACTION WHERE LABEL = "${loadLabelName}";""" + exception "denied" + } + + sql """CANCEL LOAD + FROM ${dbName} + WHERE LABEL = "${loadLabelName}";""" + res = sql """SHOW LOAD FROM ${dbName} WHERE LABEL LIKE '${loadLabelName}'""" + logger.info("res: " + res) + + sql """CLEAN LABEL ${loadLabelName} FROM ${dbName};""" + } + sql """revoke load_priv on ${dbName} from ${user}""" + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_cancel_profile_auth.groovy b/regression-test/suites/auth_call/test_dml_cancel_profile_auth.groovy new file mode 100644 index 00000000000000..82656726e659ce --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_cancel_profile_auth.groovy @@ -0,0 +1,54 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_cancel_profile_auth","p0,auth_call,nonConcurrent") { + + String user = 'test_dml_cancel_profile_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ + CLEAN ALL PROFILE; + """ + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ + CLEAN ALL PROFILE; + """ + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_delete_table_auth.groovy b/regression-test/suites/auth_call/test_dml_delete_table_auth.groovy new file mode 100644 index 00000000000000..405e9c830ebe03 --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_delete_table_auth.groovy @@ -0,0 +1,151 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_delete_table_auth","p0,auth_call") { + + String user = 'test_dml_delete_table_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_delete_table_auth_db' + String tableName = 'test_dml_delete_table_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + insert into ${dbName}.`${tableName}` values + (1, "111"), + (2, "222"), + (3, "333"); + """ + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """DELETE FROM ${dbName}.${tableName} WHERE id = 3;""" + exception "denied" + } + + def del_res = sql """show DELETE from ${dbName}""" + assertTrue(del_res.size() == 0) + } + sql """grant load_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """DELETE FROM ${dbName}.${tableName} WHERE id = 3;""" + exception "denied" + } + def del_res = sql """show DELETE from ${dbName}""" + assertTrue(del_res.size() == 0) + } + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """DELETE FROM ${dbName}.${tableName} WHERE id = 3;""" + def del_res = sql """show DELETE from ${dbName}""" + logger.info("del_res: " + del_res) + assertTrue(del_res.size() == 1) + } + + def res = sql """select count(*) from ${dbName}.${tableName};""" + assertTrue(res[0][0] == 2) + + String tableName1 = 'test_dml_delete_table_auth_tb1' + String tableName2 = 'test_dml_delete_table_auth_tb2' + String tableName3 = 'test_dml_delete_table_auth_tb3' + sql """CREATE TABLE ${dbName}.${tableName1} + (id INT, c1 BIGINT, c2 STRING, c3 DOUBLE, c4 DATE) + UNIQUE KEY (id) + DISTRIBUTED BY HASH (id) + PROPERTIES('replication_num'='1', "function_column.sequence_col" = "c4");""" + sql """CREATE TABLE ${dbName}.${tableName2} + (id INT, c1 BIGINT, c2 STRING, c3 DOUBLE, c4 DATE) + DISTRIBUTED BY HASH (id) + PROPERTIES('replication_num'='1');""" + sql """CREATE TABLE ${dbName}.${tableName3} + (id INT) + DISTRIBUTED BY HASH (id) + PROPERTIES('replication_num'='1');""" + sql """INSERT INTO ${dbName}.${tableName1} VALUES + (1, 1, '1', 1.0, '2000-01-01'), + (2, 2, '2', 2.0, '2000-01-02'), + (3, 3, '3', 3.0, '2000-01-03');""" + sql """INSERT INTO ${dbName}.${tableName2} VALUES + (1, 10, '10', 10.0, '2000-01-10'), + (2, 20, '20', 20.0, '2000-01-20'), + (3, 30, '30', 30.0, '2000-01-30'), + (4, 4, '4', 4.0, '2000-01-04'), + (5, 5, '5', 5.0, '2000-01-05');""" + sql """INSERT INTO ${dbName}.${tableName3} VALUES + (1), + (4), + (5);""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """DELETE FROM ${dbName}.${tableName1} + USING ${dbName}.${tableName2} INNER JOIN ${dbName}.${tableName3} + ON ${dbName}.${tableName2}.id = ${dbName}.${tableName3}.id + WHERE ${dbName}.${tableName1}.id = ${dbName}.${tableName2}.id;""" + exception "denied" + } + } + sql """grant load_priv on ${dbName}.${tableName1} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """DELETE FROM ${dbName}.${tableName1} + USING ${dbName}.${tableName2} INNER JOIN ${dbName}.${tableName3} + ON ${dbName}.${tableName2}.id = ${dbName}.${tableName3}.id + WHERE ${dbName}.${tableName1}.id = ${dbName}.${tableName2}.id;""" + exception "denied" + } + } + sql """grant select_priv on ${dbName}.${tableName1} to ${user}""" + sql """grant select_priv on ${dbName}.${tableName2} to ${user}""" + sql """grant select_priv on ${dbName}.${tableName3} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """DELETE FROM ${dbName}.${tableName1} + USING ${dbName}.${tableName2} INNER JOIN ${dbName}.${tableName3} + ON ${dbName}.${tableName2}.id = ${dbName}.${tableName3}.id + WHERE ${dbName}.${tableName1}.id = ${dbName}.${tableName2}.id;""" + } + res = sql """select count(*) from ${dbName}.${tableName1};""" + assertTrue(res[0][0] == 2) + + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_export_table_auth.groovy b/regression-test/suites/auth_call/test_dml_export_table_auth.groovy new file mode 100644 index 00000000000000..8d13bc4bddb71b --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_export_table_auth.groovy @@ -0,0 +1,132 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_export_table_auth","p0,auth_call") { + + UUID uuid = UUID.randomUUID() + String randomValue = uuid.toString() + int hashCode = randomValue.hashCode() + hashCode = hashCode > 0 ? hashCode : hashCode * (-1) + + String user = 'test_dml_export_table_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_export_table_auth_db' + String tableName = 'test_dml_export_table_auth_tb' + String exportLabel = 'test_dml_export_table_auth_label' + hashCode.toString() + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + UNIQUE KEY (id) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + insert into ${dbName}.`${tableName}` values + (1, "111"), + (2, "222"), + (3, "333"); + """ + String ak = getS3AK() + String sk = getS3SK() + String endpoint = getS3Endpoint() + String region = getS3Region() + String bucket = context.config.otherConfigs.get("s3BucketName"); + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """EXPORT TABLE ${dbName}.${tableName} TO "s3://${bucket}/test_outfile/exp_${exportLabel}" + PROPERTIES( + "format" = "csv", + "max_file_size" = "2048MB" + ) + WITH s3 ( + "s3.endpoint" = "${endpoint}", + "s3.region" = "${region}", + "s3.secret_key"="${sk}", + "s3.access_key" = "${ak}" + );""" + exception "denied" + } + try { + sql """CANCEL EXPORT + FROM ${dbName} + WHERE STATE = "EXPORTING";""" + } catch (Exception e) { + log.info(e.getMessage()) + assertTrue(e.getMessage().indexOf("denied") == -1) + } + } + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """EXPORT TABLE ${dbName}.${tableName} TO "s3://${bucket}/test_outfile/exp_${exportLabel}" + PROPERTIES( + "format" = "csv", + "max_file_size" = "2048MB" + ) + WITH s3 ( + "s3.endpoint" = "${endpoint}", + "s3.region" = "${region}", + "s3.secret_key"="${sk}", + "s3.access_key" = "${ak}" + );""" + sql """use ${dbName}""" + def res = sql """show export;""" + logger.info("res: " + res) + assertTrue(res.size() == 1) + } + sql """grant select_priv on ${dbName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + def res = sql """show export;""" + logger.info("res: " + res) + assertTrue(res.size() == 1) + res = sql """show grants;""" + logger.info("res:" + res) + try { + sql """CANCEL EXPORT + FROM ${dbName} + WHERE STATE = "EXPORTING";""" + } catch (Exception e) { + log.info(e.getMessage()) + assertTrue(e.getMessage().indexOf("not exist") != -1) + } + + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_insert_auth.groovy b/regression-test/suites/auth_call/test_dml_insert_auth.groovy new file mode 100644 index 00000000000000..6a04281b1c0aeb --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_insert_auth.groovy @@ -0,0 +1,121 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_insert_auth","p0,auth_call") { + + String user = 'test_dml_insert_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_insert_auth_db' + String tableName = 'test_dml_insert_auth_tb' + String srcTableName = 'test_dml_insert_auth_tb_src' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """create table ${dbName}.${srcTableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + INSERT INTO ${dbName}.${srcTableName} (id, username) + VALUES (1, "111"), + (2, "222"), + (3, "333") + """ + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def insert_res = sql """SHOW LAST INSERT""" + logger.info("insert_res: " + insert_res) + test { + sql """ + INSERT INTO ${dbName}.${tableName} (id, username) + VALUES (1, "111"), + (2, "222"), + (3, "333") + """ + exception "denied" + } + test { + sql """ + INSERT OVERWRITE table ${dbName}.${tableName} VALUES (4, "444"); + """ + exception "denied" + } + } + sql """grant load_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ + INSERT INTO ${dbName}.${tableName} (id, username) + VALUES (1, "111"), + (2, "222"), + (3, "333") + """ + def insert_res = sql """SHOW LAST INSERT""" + logger.info("insert_res: " + insert_res) + test { + sql """select count() from ${dbName}.${tableName}""" + exception "denied" + } + } + def rows = sql """select count() from ${dbName}.${tableName}""" + assertTrue(rows[0][0] == 3) + + // insert overwrite + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ + INSERT OVERWRITE table ${dbName}.${tableName} VALUES (4, "444"); + """ + } + rows = sql """select count() from ${dbName}.${tableName}""" + assertTrue(rows[0][0] == 1) + + sql """grant select_priv on ${dbName}.${srcTableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """INSERT OVERWRITE table ${dbName}.${tableName} SELECT * FROM ${dbName}.${srcTableName};""" + } + rows = sql """select count() from ${dbName}.${tableName}""" + assertTrue(rows[0][0] == 3) + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_multi_routine_load_auth.groovy b/regression-test/suites/auth_call/test_dml_multi_routine_load_auth.groovy new file mode 100644 index 00000000000000..1d9c6b8395603d --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_multi_routine_load_auth.groovy @@ -0,0 +1,160 @@ +// 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. + +import org.junit.Assert; +import org.apache.kafka.clients.producer.KafkaProducer +import org.apache.kafka.clients.producer.ProducerRecord +import org.apache.kafka.clients.producer.ProducerConfig + +suite("test_dml_multi_routine_load_auth","p0,auth_call") { + + String user = 'test_dml_multi_routine_load_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_multi_routine_load_auth_db' + String tableName1 = 'test_dml_multi_routine_load_auth_tb1' + String tableName2 = 'test_dml_multi_routine_load_auth_tb2' + String labelName = 'test_dml_multi_routine_load_auth_label' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + String enabled = context.config.otherConfigs.get("enableKafkaTest") + String kafka_port = context.config.otherConfigs.get("kafka_port") + String externalEnvIp = context.config.otherConfigs.get("externalEnvIp") + def kafka_broker = "${externalEnvIp}:${kafka_port}" + if (enabled != null && enabled.equalsIgnoreCase("true")) { + // define kafka + String topic = "zfr_test_dml_multi_routine_load_auth_topic" + def props = new Properties() + props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "${kafka_broker}".toString()) + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer") + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer") + def producer = new KafkaProducer<>(props) + def txt = new File("""${context.file.parent}/data/multi_table_csv.csv""").text + def lines = txt.readLines() + lines.each { line -> + logger.info("=====${line}========") + def record = new ProducerRecord<>(topic, null, line) + producer.send(record) + } + + sql """use ${dbName}""" + sql "drop table if exists ${tableName1}" + sql "drop table if exists ${tableName2}" + sql new File("""${context.file.parent}/ddl/${tableName1}.sql""").text + sql new File("""${context.file.parent}/ddl/${tableName2}.sql""").text + + connect(user = user, password = "${pwd}", url = context.config.jdbcUrl) { + test { + sql """ + CREATE ROUTINE LOAD ${dbName}.${labelName} + COLUMNS TERMINATED BY "|" + PROPERTIES + ( + "max_batch_interval" = "5", + "max_batch_rows" = "300000", + "max_batch_size" = "209715200" + ) + FROM KAFKA + ( + "kafka_broker_list" = "${externalEnvIp}:${kafka_port}", + "kafka_topic" = "${topic}", + "property.kafka_default_offsets" = "OFFSET_BEGINNING" + ); + """ + exception "denied" + } + } + + sql """grant load_priv on ${dbName}.${tableName1} to ${user}""" + connect(user = user, password = "${pwd}", url = context.config.jdbcUrl) { + test { + sql """ + CREATE ROUTINE LOAD ${dbName}.${labelName} + COLUMNS TERMINATED BY "|" + PROPERTIES + ( + "max_batch_interval" = "5", + "max_batch_rows" = "300000", + "max_batch_size" = "209715200" + ) + FROM KAFKA + ( + "kafka_broker_list" = "${externalEnvIp}:${kafka_port}", + "kafka_topic" = "${topic}", + "property.kafka_default_offsets" = "OFFSET_BEGINNING" + ); + """ + exception "denied" + } + } + sql """grant load_priv on ${dbName}.${tableName2} to ${user}""" + connect(user = user, password = "${pwd}", url = context.config.jdbcUrl) { + test { + sql """ + CREATE ROUTINE LOAD ${dbName}.${labelName} + COLUMNS TERMINATED BY "|" + PROPERTIES + ( + "max_batch_interval" = "5", + "max_batch_rows" = "300000", + "max_batch_size" = "209715200" + ) + FROM KAFKA + ( + "kafka_broker_list" = "${externalEnvIp}:${kafka_port}", + "kafka_topic" = "${topic}", + "property.kafka_default_offsets" = "OFFSET_BEGINNING" + ); + """ + exception "denied" + } + } + sql """grant load_priv on ${dbName}.* to ${user}""" + connect(user = user, password = "${pwd}", url = context.config.jdbcUrl) { + sql """ + CREATE ROUTINE LOAD ${dbName}.${labelName} + COLUMNS TERMINATED BY "|" + PROPERTIES + ( + "max_batch_interval" = "5", + "max_batch_rows" = "300000", + "max_batch_size" = "209715200" + ) + FROM KAFKA + ( + "kafka_broker_list" = "${externalEnvIp}:${kafka_port}", + "kafka_topic" = "${topic}", + "property.kafka_default_offsets" = "OFFSET_BEGINNING" + );""" + } + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_mysql_load_auth.groovy b/regression-test/suites/auth_call/test_dml_mysql_load_auth.groovy new file mode 100644 index 00000000000000..6010b4b8b744d9 --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_mysql_load_auth.groovy @@ -0,0 +1,84 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_mysql_load_auth","p0,auth_call") { + + String user = 'test_dml_mysql_load_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_mysql_load_auth_db' + String tableName = 'test_dml_mysql_load_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + sql """use ${dbName}""" + def path_file = "${context.file.parent}/../../data/auth_call/stream_load_data.csv" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ + LOAD DATA LOCAL + INFILE '${path_file}' + INTO TABLE ${dbName}.${tableName} + COLUMNS TERMINATED BY ',' + (a,b) + PROPERTIES ("timeout"="100") + """ + exception "denied" + } + } + sql """grant load_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName};""" + sql """ + LOAD DATA LOCAL + INFILE '${path_file}' + INTO TABLE ${dbName}.${tableName} + COLUMNS TERMINATED BY ',' + (a,b) + PROPERTIES ("timeout"="100") + """ + } + + def rows = sql """select count() from ${dbName}.${tableName}""" + assertTrue(rows[0][0] == 3) + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_outfile_auth.groovy b/regression-test/suites/auth_call/test_dml_outfile_auth.groovy new file mode 100644 index 00000000000000..5318b1dbe31ccf --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_outfile_auth.groovy @@ -0,0 +1,92 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_outfile_auth","p0,auth_call") { + UUID uuid = UUID.randomUUID() + String randomValue = uuid.toString() + int hashCode = randomValue.hashCode() + hashCode = hashCode > 0 ? hashCode : hashCode * (-1) + + String user = 'test_dml_outfile_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_outfile_auth_db' + String tableName = 'test_dml_outfile_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + String ak = getS3AK() + String sk = getS3SK() + String s3_endpoint = getS3Endpoint() + String region = getS3Region() + String bucket = context.config.otherConfigs.get("s3BucketName") + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ + SELECT * FROM ${dbName}.${tableName} t ORDER BY id + INTO OUTFILE "s3://${bucket}/outfile/auth/exp_${hashCode}" + FORMAT AS parquet + PROPERTIES ( + "s3.endpoint" = "${s3_endpoint}", + "s3.region" = "${region}", + "s3.secret_key"="${sk}", + "s3.access_key" = "${ak}" + );""" + exception "denied" + } + } + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ + SELECT * FROM ${dbName}.${tableName} t ORDER BY id + INTO OUTFILE "s3://${bucket}/outfile/auth/exp_" + FORMAT AS parquet + PROPERTIES ( + "s3.endpoint" = "${s3_endpoint}", + "s3.region" = "${region}", + "s3.secret_key"="${sk}", + "s3.access_key" = "${ak}" + );""" + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_routine_load_auth.groovy b/regression-test/suites/auth_call/test_dml_routine_load_auth.groovy new file mode 100644 index 00000000000000..8ee5236960baa7 --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_routine_load_auth.groovy @@ -0,0 +1,153 @@ +// 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. + +import org.junit.Assert; +import org.apache.kafka.clients.producer.KafkaProducer +import org.apache.kafka.clients.producer.ProducerRecord +import org.apache.kafka.clients.producer.ProducerConfig + +suite("test_dml_routine_load_auth","p0,auth_call") { + + String user = 'test_dml_routine_load_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_routine_load_auth_db' + String tableName = 'test_dml_routine_load_auth_tb' + String labelName = 'test_dml_routine_load_auth_label' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + String enabled = context.config.otherConfigs.get("enableKafkaTest") + String kafka_port = context.config.otherConfigs.get("kafka_port") + String externalEnvIp = context.config.otherConfigs.get("externalEnvIp") + def kafka_broker = "${externalEnvIp}:${kafka_port}" + if (enabled != null && enabled.equalsIgnoreCase("true")) { + // define kafka + String topic = "zfr_test_dml_routine_load_auth_topic" + def props = new Properties() + props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "${kafka_broker}".toString()) + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer") + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer") + def producer = new KafkaProducer<>(props) + def filepath = getLoalFilePath "routine_load_data.csv" + def txt = new File("${filepath}").text + def lines = txt.readLines() + lines.each { line -> + logger.info("=====${line}========") + def record = new ProducerRecord<>(topic, null, line) + producer.send(record) + } + sql "drop table if exists ${tableName}" + sql """create table ${dbName}.${tableName}(a int,c double generated always as (abs(a+b)) not null,b int, d int generated always as(c+1)) + DISTRIBUTED BY HASH(a) + PROPERTIES("replication_num" = "1"); + ;""" + + connect(user = user, password = "${pwd}", url = context.config.jdbcUrl) { + test { + sql """ + CREATE ROUTINE LOAD ${dbName}.${labelName} ON ${tableName} + COLUMNS(a,b), + COLUMNS TERMINATED BY "," + FROM KAFKA + ( + "kafka_broker_list" = "${externalEnvIp}:${kafka_port}", + "kafka_topic" = "${topic}", + "property.kafka_default_offsets" = "OFFSET_BEGINNING" + ); + """ + exception "denied" + } + } + + sql """grant load_priv on ${dbName}.${tableName} to ${user}""" + connect(user = user, password = "${pwd}", url = context.config.jdbcUrl) { + sql """ + CREATE ROUTINE LOAD ${dbName}.${labelName} ON ${tableName} + COLUMNS(a,b), + COLUMNS TERMINATED BY "," + FROM KAFKA + ( + "kafka_broker_list" = "${externalEnvIp}:${kafka_port}", + "kafka_topic" = "${topic}", + "property.kafka_default_offsets" = "OFFSET_BEGINNING" + ); + """ + } + sql """revoke load_priv on ${dbName}.${tableName} from ${user}""" + + connect(user = user, password = "${pwd}", url = context.config.jdbcUrl) { + test { + sql """ + ALTER ROUTINE LOAD FOR ${dbName}.${labelName} + PROPERTIES + ( + "desired_concurrent_number" = "1" + ); + """ + exception "denied" + } + test { + sql """PAUSE ROUTINE LOAD FOR ${dbName}.${labelName};""" + exception "denied" + } + test { + sql """RESUME ROUTINE LOAD FOR ${dbName}.${labelName};""" + exception "denied" + } + test { + sql """STOP ROUTINE LOAD FOR ${dbName}.${labelName};""" + exception "denied" + } + test { + sql """show routine load for ${dbName}.${labelName}""" + exception "no job" + } + } + sql """grant load_priv on ${dbName}.${tableName} to ${user}""" + connect(user = user, password = "${pwd}", url = context.config.jdbcUrl) { + sql """PAUSE ROUTINE LOAD FOR ${dbName}.${labelName};""" + sql """ + ALTER ROUTINE LOAD FOR ${dbName}.${labelName} + PROPERTIES + ( + "desired_concurrent_number" = "1" + ); + """ + sql """RESUME ROUTINE LOAD FOR ${dbName}.${labelName};""" + sql """STOP ROUTINE LOAD FOR ${dbName}.${labelName};""" + sql """use ${dbName};""" + def res = sql """show all routine load""" + assertTrue(res.size() == 1) + } + sql """revoke load_priv on ${dbName}.${tableName} from ${user}""" + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_select_udf_auth.groovy b/regression-test/suites/auth_call/test_dml_select_udf_auth.groovy new file mode 100644 index 00000000000000..72413b3e292ceb --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_select_udf_auth.groovy @@ -0,0 +1,77 @@ +// 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. + +import org.codehaus.groovy.runtime.IOGroovyMethods + +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Paths + +suite("test_dml_select_udf_auth","p0,auth_call") { + + String user = 'test_dml_select_udf_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_select_udf_auth_db' + String tableName = 'test_dml_select_udf_auth_tb' + String udfName = 'test_dml_select_udf_auth_udf' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + def jarPath = """${context.file.parent}/../javaudf_p0/jars/java-udf-case-jar-with-dependencies.jar""" + scp_udf_file_to_all_be(jarPath) + log.info("Jar path: ${jarPath}".toString()) + + sql """ CREATE FUNCTION ${dbName}.${udfName}(string) RETURNS int PROPERTIES ( + "file"="file://${jarPath}", + "symbol"="org.apache.doris.udf.collect.MurmurHash3UDF", + "type"="JAVA_UDF" + ); """ + + sql """ + CREATE TABLE ${dbName}.${tableName} ( + `col_1` varchar(10) NOT NULL + ) + DISTRIBUTED BY HASH(col_1) PROPERTIES("replication_num" = "1"); + """ + sql """ INSERT INTO ${dbName}.${tableName} VALUES ("abc"), ("123"), ("123"); """ + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ SELECT ${dbName}.${udfName}(col_1) as a FROM ${dbName}.${tableName} ORDER BY a; """ + exception "Can not found function" + } + } + sql """grant select_priv on ${dbName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ SELECT ${dbName}.${udfName}(col_1) as a FROM ${dbName}.${tableName} ORDER BY a; """ + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_stream_load_auth.groovy b/regression-test/suites/auth_call/test_dml_stream_load_auth.groovy new file mode 100644 index 00000000000000..240fdde6f6926d --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_stream_load_auth.groovy @@ -0,0 +1,115 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_stream_load_auth","p0,auth_call") { + String user = 'test_dml_stream_load_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_stream_load_auth_db' + String tableName = 'test_dml_stream_load_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + def write_to_file = { cur_path, content -> + File file = new File(cur_path) + file.write(content) + } + + def jdbcUrl = context.config.jdbcUrl + def urlWithoutSchema = jdbcUrl.substring(jdbcUrl.indexOf("://") + 3) + def sql_ip = urlWithoutSchema.substring(0, urlWithoutSchema.indexOf(":")) + String feHttpAddress = context.config.feHttpAddress + def http_port = feHttpAddress.substring(feHttpAddress.indexOf(":") + 1) + + def path_file = "${context.file.parent}/../../data/auth_call/stream_load_data.csv" + def load_path = "${context.file.parent}/../../data/auth_call/stream_load_cm.sh" + def cm = """curl --location-trusted -u ${user}:${pwd} -H "column_separator:," -T ${path_file} http://${sql_ip}:${http_port}/api/${dbName}/${tableName}/_stream_load""" + logger.info("cm: " + cm) + write_to_file(load_path, cm) + cm = "bash " + load_path + logger.info("cm:" + cm) + + + def proc = cm.execute() + def sout = new StringBuilder(), serr = new StringBuilder() + proc.consumeProcessOutput(sout, serr) + proc.waitForOrKill(7200000) + logger.info("std out: " + sout + "std err: " + serr) + assertTrue(sout.toString().indexOf("FAILED") != -1) + assertTrue(sout.toString().indexOf("denied") != -1) + + + sql """grant load_priv on ${dbName}.${tableName} to ${user}""" + + proc = cm.execute() + sout = new StringBuilder() + serr = new StringBuilder() + proc.consumeProcessOutput(sout, serr) + proc.waitForOrKill(7200000) + logger.info("std out: " + sout + "std err: " + serr) + assertTrue(sout.toString().indexOf("Success") != -1) + + int pos1 = sout.indexOf("TxnId") + int pos2 = sout.indexOf(",", pos1) + int pos3 = sout.indexOf(":", pos1) + def tsc_id = sout.substring(pos3+2, pos2) + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW TRANSACTION FROM ${dbName} WHERE ID=${tsc_id};""" + exception "denied" + } + } + + def res = sql """select count() from ${dbName}.${tableName}""" + assertTrue(res[0][0] == 3) + + def stream_res = sql """SHOW STREAM LOAD FROM ${dbName};""" + logger.info("stream_res: " + stream_res) + + sql """grant admin_priv on *.*.* to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def transaction_res = sql """SHOW TRANSACTION FROM ${dbName} WHERE ID=${tsc_id};""" + assertTrue(transaction_res.size() == 1) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_dml_update_table_auth.groovy b/regression-test/suites/auth_call/test_dml_update_table_auth.groovy new file mode 100644 index 00000000000000..10c9a3fcb80f2a --- /dev/null +++ b/regression-test/suites/auth_call/test_dml_update_table_auth.groovy @@ -0,0 +1,81 @@ +// 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. + +import org.junit.Assert; +import org.codehaus.groovy.runtime.IOGroovyMethods + +suite("test_dml_update_table_auth","p0,auth_call") { + + String user = 'test_dml_update_table_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_dml_update_table_auth_db' + String tableName = 'test_dml_update_table_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + UNIQUE KEY (id) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + insert into ${dbName}.`${tableName}` values + (1, "111"), + (2, "222"), + (3, "333"); + """ + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """UPDATE ${dbName}.${tableName} SET username = "444" WHERE id=1;""" + exception "denied" + } + } + sql """grant load_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """UPDATE ${dbName}.${tableName} SET username = "444" WHERE id=1;""" + exception "denied" + } + } + sql """grant select_priv(id) on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """UPDATE ${dbName}.${tableName} SET username = "444" WHERE id=1;""" + } + + def res = sql """select count(*) from ${dbName}.${tableName};""" + logger.info("res: " + res) + assertTrue(res[0][0] == 3) + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_hive_base_case_auth.groovy b/regression-test/suites/auth_call/test_hive_base_case_auth.groovy new file mode 100644 index 00000000000000..b1f432ddfb293d --- /dev/null +++ b/regression-test/suites/auth_call/test_hive_base_case_auth.groovy @@ -0,0 +1,200 @@ +// 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. + +suite("test_hive_base_case_auth", "p0,auth_call") { + + String user = 'test_hive_base_case_auth_user' + String pwd = 'C123_567p' + String catalogName = 'test_hive_base_case_auth_catalog' + String dbName = 'test_hive_base_case_auth_db' + String tableName = 'test_hive_base_case_auth_tb' + String tableNameNew = 'test_hive_base_case_auth_tb_new' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + String enabled = context.config.otherConfigs.get("enableHiveTest") + if (enabled == null || !enabled.equalsIgnoreCase("true")) { + logger.info("diable Hive test.") + return; + } + + for (String hivePrefix : ["hive2", "hive3"]) { + setHivePrefix(hivePrefix) + + String hms_port = context.config.otherConfigs.get(hivePrefix + "HmsPort") + String hdfs_port = context.config.otherConfigs.get(hivePrefix + "HdfsPort") + String externalEnvIp = context.config.otherConfigs.get("externalEnvIp") + + try_sql("DROP USER ${user}") + try_sql """drop catalog if exists ${catalogName}""" + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + // create catalog + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create catalog if not exists ${catalogName} properties ( + 'type'='hms' + );""" + exception "denied" + } + def ctl_res = sql """show catalogs;""" + assertTrue(ctl_res.size() == 1) + } + sql """create catalog if not exists ${catalogName} properties ( + 'type'='hms' + );""" + sql """grant Create_priv on ${catalogName}.*.* to ${user}""" + try_sql """drop catalog if exists ${catalogName}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """create catalog if not exists ${catalogName} properties ( + 'type'='hms', + 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}', + 'fs.defaultFS' = 'hdfs://${externalEnvIp}:${hdfs_port}', + 'use_meta_cache' = 'true' + );""" + sql """show create catalog ${catalogName}""" + def ctl_res = sql """show catalogs;""" + assertTrue(ctl_res.size() == 2) + } + sql """revoke Create_priv on ${catalogName}.*.* from ${user}""" + + // create database + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create database ${catalogName}.${dbName};""" + exception "denied" + } + } + sql """create database ${catalogName}.${dbName};""" + sql """grant Create_priv on ${catalogName}.${dbName}.* to ${user}""" + sql """drop table if exists ${catalogName}.${dbName}.${tableName};""" + sql """drop database ${catalogName}.${dbName};""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """create database ${catalogName}.${dbName};""" + } + sql """revoke Create_priv on ${catalogName}.${dbName}.* from ${user}""" + + // create table + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """create table ${catalogName}.${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) ENGINE=hive + PROPERTIES ( + 'file_format'='parquet' + );""" + exception "denied" + } + } + sql """create table ${catalogName}.${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) ENGINE=hive + PROPERTIES ( + 'file_format'='parquet' + );""" + sql """grant Create_priv on ${catalogName}.${dbName}.${tableName} to ${user}""" + sql """drop table ${catalogName}.${dbName}.${tableName}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """create table ${catalogName}.${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) ENGINE=hive + PROPERTIES ( + 'file_format'='parquet' + );""" + sql """switch ${catalogName}""" + sql """use ${dbName}""" + sql """show create table ${tableName}""" + def db_res = sql """show tables;""" + assertTrue(db_res.size() == 1) + } + sql """revoke Create_priv on ${catalogName}.${dbName}.${tableName} from ${user}""" + + // load + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """ + insert into ${catalogName}.${dbName}.${tableName} values + (1, "111"), + (2, "222"); + """ + exception "denied" + } + } + sql """grant LOAD_PRIV on ${catalogName}.${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """ + insert into ${catalogName}.${dbName}.${tableName} values + (1, "111"), + (2, "222"); + """ + } + sql """revoke LOAD_PRIV on ${catalogName}.${dbName}.${tableName} from ${user}""" + + // alter +// connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { +// test { +// sql """ALTER table ${catalogName}.${dbName}.${tableName} RENAME ${tableNameNew};""" +// exception "denied" +// } +// } +// sql """grant ALTER_PRIV on ${catalogName}.${dbName}.${tableName} to ${user}""" +// connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { +// sql """ALTER table ${catalogName}.${dbName}.${tableName} RENAME ${tableNameNew};""" +// } +// sql """revoke ALTER_PRIV on ${catalogName}.${dbName}.${tableName} from ${user}""" +// sql """ALTER table ${catalogName}.${dbName}.${tableNameNew} RENAME ${tableName};""" + + // drop + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """drop catalog ${catalogName}""" + exception "denied" + } + test { + sql """drop database ${catalogName}.${dbName}""" + exception "denied" + } + test { + sql """drop table ${catalogName}.${dbName}.${tableName}""" + exception "denied" + } + } + sql """grant DROP_PRIV on ${catalogName}.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """drop table ${catalogName}.${dbName}.${tableName}""" + sql """drop database ${catalogName}.${dbName}""" + sql """drop catalog ${catalogName}""" + } + + sql """drop catalog if exists ${catalogName}""" + try_sql("DROP USER ${user}") + } + + + +} diff --git a/regression-test/suites/auth_call/test_show_backend_auth.groovy b/regression-test/suites/auth_call/test_show_backend_auth.groovy new file mode 100644 index 00000000000000..16df2a6c10b398 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_backend_auth.groovy @@ -0,0 +1,49 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_backend_auth","p0,auth_call") { + String user = 'test_show_backend_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW BACKENDS""" + exception "denied" + } + } + sql """grant node_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """SHOW BACKENDS""" + assertTrue(res.size() > 0) + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_broker_auth.groovy b/regression-test/suites/auth_call/test_show_broker_auth.groovy new file mode 100644 index 00000000000000..6ce1c4b361ac66 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_broker_auth.groovy @@ -0,0 +1,48 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_broker_auth","p0,auth_call") { + String user = 'test_show_broker_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW BROKER;""" + exception "denied" + } + } + sql """grant node_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """SHOW BROKER;""" + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_charset_auth.groovy b/regression-test/suites/auth_call/test_show_charset_auth.groovy new file mode 100644 index 00000000000000..803810dc204ab2 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_charset_auth.groovy @@ -0,0 +1,79 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_no_auth","p0,auth_call") { + String user = 'test_show_charset_auth_user' + String user1 = 'test_show_charset_auth_user1' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql("DROP USER ${user1}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """CREATE USER '${user1}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """SHOW CHARSET""" + sql """SHOW DATA TYPES""" + sql """SHOW ENGINES""" + sql """show collation;""" + sql """show variables;""" + sql """SHOW PROPERTY;""" + def res1 = sql """SHOW PROCESSLIST""" + logger.info("res1: " + res1) + assertTrue(res1.size() >= 1) + + test { + sql """show PROPERTY for ${user1}""" + exception "denied" + } + test { + sql """SHOW TRASH;""" + exception "denied" + } + } + sql """grant grant_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """show PROPERTY for ${user1}""" + logger.info("res: " + res) + assertTrue(res.size() > 0) + + def res1 = sql """SHOW PROCESSLIST""" + logger.info("res1: " + res1) + assertTrue(res1.size() == 1) + } + sql """revoke grant_priv on *.*.* from ${user}""" + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """SHOW TRASH;""" + logger.info("res: " + res) + assertTrue(res.size() >= 1) + } + + try_sql("DROP USER ${user}") + try_sql("DROP USER ${user1}") +} diff --git a/regression-test/suites/auth_call/test_show_convert_light_sc_auth.groovy b/regression-test/suites/auth_call/test_show_convert_light_sc_auth.groovy new file mode 100644 index 00000000000000..c7a765fe9a3599 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_convert_light_sc_auth.groovy @@ -0,0 +1,48 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_convert_light_sc_auth","p0,auth_call") { + String user = 'test_show_convert_light_sc_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW CONVERT_LIGHT_SCHEMA_CHANGE_PROCESS;""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """SHOW CONVERT_LIGHT_SCHEMA_CHANGE_PROCESS;""" + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_create_table_auth.groovy b/regression-test/suites/auth_call/test_show_create_table_auth.groovy new file mode 100644 index 00000000000000..6152806ce6fbb6 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_create_table_auth.groovy @@ -0,0 +1,92 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_create_table_auth","p0,auth_call") { + String user = 'test_show_create_table_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_show_create_table_auth_db' + String tableName = 'test_show_create_table_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """show create table ${dbName}.${tableName}""" + exception "denied" + } + test { + sql """SHOW DATA SKEW FROM ${dbName}.${tableName};""" + exception "denied" + } + } + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """show create table ${tableName}""" + sql """SHOW DATA SKEW FROM ${tableName};""" + } + sql """revoke select_priv on ${dbName}.${tableName} from ${user}""" + + sql """grant create_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """show create table ${tableName}""" + sql """SHOW DATA SKEW FROM ${tableName};""" + } + sql """revoke create_priv on ${dbName}.${tableName} from ${user}""" + + sql """grant drop_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """show create table ${tableName}""" + sql """SHOW DATA SKEW FROM ${tableName};""" + } + sql """revoke drop_priv on ${dbName}.${tableName} from ${user}""" + + sql """grant alter_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """show create table ${tableName}""" + sql """SHOW DATA SKEW FROM ${tableName};""" + } + sql """revoke alter_priv on ${dbName}.${tableName} from ${user}""" + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_data_auth.groovy b/regression-test/suites/auth_call/test_show_data_auth.groovy new file mode 100644 index 00000000000000..84bf9497f546e8 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_data_auth.groovy @@ -0,0 +1,89 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_data_auth","p0,auth_call") { + String user = 'test_show_data_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_show_data_auth_db' + String tableName = 'test_show_data_auth_tb' + String tableName2 = 'test_show_data_auth_tb2' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + sql """create table ${dbName}.${tableName2} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """show data from ${dbName}.${tableName}""" + exception "denied" + } + test { + sql """show data from ${dbName}.${tableName2}""" + exception "denied" + } + sql """SHOW DATA;""" + } + + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use ${dbName}""" + sql """show data from ${dbName}.${tableName}""" + test { + sql """show data from ${dbName}.${tableName2}""" + exception "denied" + } + sql """SHOW DATA;""" + } + sql """revoke select_priv on ${dbName}.${tableName} from ${user}""" + + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """SHOW DATA;""" + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_database_id_auth.groovy b/regression-test/suites/auth_call/test_show_database_id_auth.groovy new file mode 100644 index 00000000000000..0a0d44be07476d --- /dev/null +++ b/regression-test/suites/auth_call/test_show_database_id_auth.groovy @@ -0,0 +1,63 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_database_id_auth","p0,auth_call") { + String user = 'test_show_database_id_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_show_database_id_auth_db' + String tableName = 'test_show_database_id_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """show database 1001""" + exception "denied" + } + test { + sql """show table 1001""" + exception "denied" + } + test { + sql """SHOW CATALOG RECYCLE BIN;""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """show database 1001""" + sql """show table 1001""" + sql """SHOW CATALOG RECYCLE BIN;""" + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_dynamic_table_auth.groovy b/regression-test/suites/auth_call/test_show_dynamic_table_auth.groovy new file mode 100644 index 00000000000000..e144d87749c193 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_dynamic_table_auth.groovy @@ -0,0 +1,67 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_dynamic_table_auth","p0,auth_call") { + String user = 'test_show_dynamic_table_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_show_dynamic_table_auth_db' + String tableName = 'test_show_dynamic_table_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + PARTITION BY RANGE(id) () + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1", + "dynamic_partition.enable" = "true", + "dynamic_partition.time_unit" = "MONTH", + "dynamic_partition.end" = "2", + "dynamic_partition.prefix" = "p", + "dynamic_partition.buckets" = "8", + "dynamic_partition.start_day_of_month" = "3" + );""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """SHOW DYNAMIC PARTITION TABLES from ${dbName};""" + assertTrue(res.size() == 0) + } + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """SHOW DYNAMIC PARTITION TABLES from ${dbName};""" + assertTrue(res.size() == 1) + } + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_frontend_auth.groovy b/regression-test/suites/auth_call/test_show_frontend_auth.groovy new file mode 100644 index 00000000000000..2844ee992c2a98 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_frontend_auth.groovy @@ -0,0 +1,55 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_frontend_auth","p0,auth_call") { + String user = 'test_show_frontend_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW frontends""" + exception "denied" + } + test { + sql """show frontends disks""" + exception "denied" + } + } + sql """grant node_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """SHOW frontends""" + assertTrue(res.size() > 0) + + sql """show frontends disks""" + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_grant_auth.groovy b/regression-test/suites/auth_call/test_show_grant_auth.groovy new file mode 100644 index 00000000000000..5c6c3f069e32bf --- /dev/null +++ b/regression-test/suites/auth_call/test_show_grant_auth.groovy @@ -0,0 +1,56 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_grant_auth","p0,auth_call") { + String user = 'test_show_grant_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """show grants;""" + test { + sql """show all grants;""" + exception "denied" + } + + test { + sql """show roles;""" + exception "denied" + } + } + sql """grant grant_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """show grants;""" + sql """show all grants;""" + sql """show roles;""" + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_proc_auth.groovy b/regression-test/suites/auth_call/test_show_proc_auth.groovy new file mode 100644 index 00000000000000..725a9785a7af5c --- /dev/null +++ b/regression-test/suites/auth_call/test_show_proc_auth.groovy @@ -0,0 +1,48 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_proc_auth","p0,auth_call") { + String user = 'test_show_proc_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW PROC "/";""" + exception "denied" + } + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """SHOW PROC "/";""" + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_query_stats_auth.groovy b/regression-test/suites/auth_call/test_show_query_stats_auth.groovy new file mode 100644 index 00000000000000..1a9e8898fff432 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_query_stats_auth.groovy @@ -0,0 +1,43 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_query_stats_auth","p0,auth_call") { + String user = 'test_show_query_stats_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + logger.info("context.config.jdbcUrl: " + context.config.jdbcUrl) + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """show query stats;""" + logger.info("res:" + res) + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_repository_auth.groovy b/regression-test/suites/auth_call/test_show_repository_auth.groovy new file mode 100644 index 00000000000000..beb073226fe160 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_repository_auth.groovy @@ -0,0 +1,78 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_repository_auth","p0,auth_call") { + String user = 'test_show_repository_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_show_repository_auth_db' + String repositoryName = 'test_show_repository_auth_rps' + + String ak = getS3AK() + String sk = getS3SK() + String endpoint = getS3Endpoint() + String region = getS3Region() + String bucket = context.config.otherConfigs.get("s3BucketName"); + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + try_sql("""DROP REPOSITORY `${repositoryName}`;""") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + + sql """CREATE REPOSITORY `${repositoryName}` + WITH S3 + ON LOCATION "s3://${bucket}/${repositoryName}" + PROPERTIES + ( + "s3.endpoint" = "http://${endpoint}", + "s3.region" = "${region}", + "s3.access_key" = "${ak}", + "s3.secret_key" = "${sk}" + )""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW CREATE REPOSITORY for ${repositoryName};""" + exception "denied" + } + test { + sql """SHOW REPOSITORIES;""" + exception "denied" + } + + } + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """SHOW CREATE REPOSITORY for ${repositoryName};""" + + def res = sql """SHOW REPOSITORIES;""" + logger.info("res: " + res) + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_tablet_auth.groovy b/regression-test/suites/auth_call/test_show_tablet_auth.groovy new file mode 100644 index 00000000000000..03f8ed58a8ed40 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_tablet_auth.groovy @@ -0,0 +1,91 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_tablet_auth","p0,auth_call") { + String user = 'test_show_tablet_auth_user' + String pwd = 'C123_567p' + String dbName = 'test_show_tablet_auth_db' + String tableName = 'test_show_tablet_auth_tb' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + try_sql """drop database if exists ${dbName}""" + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + sql """create database ${dbName}""" + sql """create table ${dbName}.${tableName} ( + id BIGINT, + username VARCHAR(20) + ) + DISTRIBUTED BY HASH(id) BUCKETS 2 + PROPERTIES ( + "replication_num" = "1" + );""" + sql """ + insert into ${dbName}.`${tableName}` values + (1, "111"), + (2, "222"), + (3, "333"); + """ + + sql """grant select_priv on ${dbName}.${tableName} to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + test { + sql """SHOW TABLETS FROM ${dbName}.${tableName}""" + exception "denied" + } + test { + sql """SHOW TABLET 1000""" + exception "denied" + } + test { + sql """SHOW TABLETS BELONG 1000""" + exception "denied" + } + test { + sql """SHOW PLUGINS""" + exception "denied" + } + } + sql """revoke select_priv on ${dbName}.${tableName} from ${user}""" + + sql """grant admin_priv on *.*.* to ${user}""" + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + def res = sql """SHOW TABLETS FROM ${dbName}.${tableName}""" + + def tablet_res = sql """SHOW TABLET ${res[0][0]}""" + assertTrue(tablet_res.size() == 1) + + tablet_res = sql """SHOW TABLETS BELONG ${res[0][0]}""" + assertTrue(tablet_res.size() == 1) + + sql """SHOW PLUGINS""" + } + + + sql """drop database if exists ${dbName}""" + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_call/test_show_typecast_auth.groovy b/regression-test/suites/auth_call/test_show_typecast_auth.groovy new file mode 100644 index 00000000000000..104e8107e1fb76 --- /dev/null +++ b/regression-test/suites/auth_call/test_show_typecast_auth.groovy @@ -0,0 +1,42 @@ +// 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. + +import org.junit.Assert; + +suite("test_show_typecast_auth","p0,auth_call") { + String user = 'test_show_typecast_auth_user' + String pwd = 'C123_567p' + + //cloud-mode + if (isCloudMode()) { + def clusters = sql " SHOW CLUSTERS; " + assertTrue(!clusters.isEmpty()) + def validCluster = clusters[0][0] + sql """GRANT USAGE_PRIV ON CLUSTER ${validCluster} TO ${user}"""; + } + + try_sql("DROP USER ${user}") + sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'""" + sql """grant select_priv on regression_test to ${user}""" + + connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { + sql """use regression_test""" + sql """show type_cast;""" + } + + try_sql("DROP USER ${user}") +} diff --git a/regression-test/suites/auth_p0/test_master_slave_consistency_auth.groovy b/regression-test/suites/auth_p0/test_master_slave_consistency_auth.groovy index 6c8f7e520b8fbd..6bb089683c3911 100644 --- a/regression-test/suites/auth_p0/test_master_slave_consistency_auth.groovy +++ b/regression-test/suites/auth_p0/test_master_slave_consistency_auth.groovy @@ -320,12 +320,18 @@ suite ("test_follower_consistent_auth","p0,auth") { } sql """GRANT USAGE_PRIV ON RESOURCE ${rg} TO ${user};""" connect(user=user, password="${pwd}", url=context.config.jdbcUrl) { - def res = sql """SHOW RESOURCES;""" - assertTrue(res.size == 10) + ArrayList res = sql """SHOW RESOURCES;""" + logger.info("res:" + res) + logger.info("res1: " + res.getClass()) + logger.info("res2: " + res.getClass().getName()) + assertTrue(res.size() == 10) } connect(user=user, password="${pwd}", url=new_jdbc_url) { - def res = sql """SHOW RESOURCES;""" - assertTrue(res.size == 10) + ArrayList res = sql """SHOW RESOURCES;""" + logger.info("res:" + res) + logger.info("res1: " + res.getClass()) + logger.info("res2: " + res.getClass().getName()) + assertTrue(res.size() == 10) } try_sql("DROP USER ${user}")