Skip to content

Commit 2849d72

Browse files
branch-4.0: [fix](regression) Add auth regression tests for Iceberg/Paimon system tables #58298 (#58400)
Cherry-picked from #58298 Co-authored-by: Socrates <[email protected]>
1 parent 8a164ff commit 2849d72

File tree

2 files changed

+367
-0
lines changed

2 files changed

+367
-0
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
suite("test_iceberg_sys_table_auth", "p0,external,doris,external_docker,external_docker_doris") {
19+
20+
String enabled = context.config.otherConfigs.get("enableIcebergTest")
21+
if (enabled == null || !enabled.equalsIgnoreCase("true")) {
22+
logger.info("disable iceberg test.")
23+
return
24+
}
25+
26+
String catalog_name = "test_iceberg_systable_auth_ctl"
27+
String db_name = "test_db"
28+
String rest_port = context.config.otherConfigs.get("iceberg_rest_uri_port")
29+
String minio_port = context.config.otherConfigs.get("iceberg_minio_port")
30+
String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
31+
sql """drop catalog if exists ${catalog_name}"""
32+
sql """
33+
CREATE CATALOG ${catalog_name} PROPERTIES (
34+
'type'='iceberg',
35+
'iceberg.catalog.type'='rest',
36+
'uri' = 'http://${externalEnvIp}:${rest_port}',
37+
"s3.access_key" = "admin",
38+
"s3.secret_key" = "password",
39+
"s3.endpoint" = "http://${externalEnvIp}:${minio_port}",
40+
"s3.region" = "us-east-1"
41+
);"""
42+
43+
sql """switch ${catalog_name}"""
44+
sql """use ${db_name}"""
45+
46+
// Create test table
47+
sql """drop table if exists test_iceberg_systable_auth_tbl1;"""
48+
sql """create table test_iceberg_systable_auth_tbl1 (id int);"""
49+
sql """insert into test_iceberg_systable_auth_tbl1 values(1);"""
50+
sql """insert into test_iceberg_systable_auth_tbl1 values(2);"""
51+
sql """insert into test_iceberg_systable_auth_tbl1 values(3);"""
52+
sql """insert into test_iceberg_systable_auth_tbl1 values(4);"""
53+
sql """insert into test_iceberg_systable_auth_tbl1 values(5);"""
54+
55+
// Create test user without table permission
56+
String user = "test_iceberg_systable_auth_user"
57+
String pwd = 'C123_567p'
58+
try_sql("DROP USER '${user}'@'%'")
59+
sql """CREATE USER '${user}'@'%' IDENTIFIED BY '${pwd}'"""
60+
61+
if (isCloudMode()) {
62+
def clusters = sql " SHOW CLUSTERS; "
63+
assertTrue(!clusters.isEmpty())
64+
def validCluster = clusters[0][0]
65+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO '${user}'@'%'""";
66+
}
67+
68+
sql """create database if not exists internal.regression_test"""
69+
sql """GRANT SELECT_PRIV ON internal.regression_test.* TO '${user}'@'%'"""
70+
71+
// Test that user without table permission cannot query system tables
72+
connect(user, "${pwd}", context.config.jdbcUrl) {
73+
// Test snapshots system table via iceberg_meta function
74+
test {
75+
sql """
76+
select committed_at, snapshot_id, parent_id, operation from iceberg_meta(
77+
"table" = "${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1",
78+
"query_type" = "snapshots");
79+
"""
80+
exception "denied"
81+
}
82+
// Test snapshots system table via direct access
83+
test {
84+
sql """
85+
select committed_at, snapshot_id, parent_id, operation from ${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1\$snapshots
86+
"""
87+
exception "denied"
88+
}
89+
// Test files system table via iceberg_meta function
90+
test {
91+
sql """
92+
select * from iceberg_meta(
93+
"table" = "${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1",
94+
"query_type" = "files");
95+
"""
96+
exception "denied"
97+
}
98+
// Test files system table via direct access
99+
test {
100+
sql """
101+
select * from ${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1\$files
102+
"""
103+
exception "denied"
104+
}
105+
// Test entries system table via iceberg_meta function
106+
test {
107+
sql """
108+
select * from iceberg_meta(
109+
"table" = "${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1",
110+
"query_type" = "entries");
111+
"""
112+
exception "denied"
113+
}
114+
// Test entries system table via direct access
115+
test {
116+
sql """
117+
select * from ${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1\$entries
118+
"""
119+
exception "denied"
120+
}
121+
// Test history system table via iceberg_meta function
122+
test {
123+
sql """
124+
select * from iceberg_meta(
125+
"table" = "${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1",
126+
"query_type" = "history");
127+
"""
128+
exception "denied"
129+
}
130+
// Test history system table via direct access
131+
test {
132+
sql """
133+
select * from ${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1\$history
134+
"""
135+
exception "denied"
136+
}
137+
}
138+
139+
// Grant permission and verify user can query system tables
140+
sql """GRANT SELECT_PRIV ON ${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1 TO '${user}'@'%'"""
141+
connect(user, "${pwd}", context.config.jdbcUrl) {
142+
// Test snapshots system table with permission
143+
sql """
144+
select committed_at, snapshot_id, parent_id, operation from iceberg_meta(
145+
"table" = "${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1",
146+
"query_type" = "snapshots");
147+
"""
148+
sql """select committed_at, snapshot_id, parent_id, operation from ${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1\$snapshots"""
149+
150+
// Test files system table with permission
151+
sql """
152+
select * from iceberg_meta(
153+
"table" = "${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1",
154+
"query_type" = "files");
155+
"""
156+
sql """select * from ${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1\$files"""
157+
158+
// Test entries system table with permission
159+
sql """
160+
select * from iceberg_meta(
161+
"table" = "${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1",
162+
"query_type" = "entries");
163+
"""
164+
sql """select * from ${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1\$entries"""
165+
166+
// Test history system table with permission
167+
sql """
168+
select * from iceberg_meta(
169+
"table" = "${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1",
170+
"query_type" = "history");
171+
"""
172+
sql """select * from ${catalog_name}.${db_name}.test_iceberg_systable_auth_tbl1\$history"""
173+
}
174+
try_sql("DROP USER '${user}'@'%'")
175+
}
176+
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
suite("test_paimon_system_table_auth", "p0,external,doris,external_docker,external_docker_doris") {
19+
20+
String enabled = context.config.otherConfigs.get("enablePaimonTest")
21+
if (enabled == null || !enabled.equalsIgnoreCase("true")) {
22+
logger.info("disabled paimon test")
23+
return
24+
}
25+
26+
String catalog_name = "test_paimon_systable_auth"
27+
try {
28+
String db_name = "flink_paimon"
29+
String minio_port = context.config.otherConfigs.get("iceberg_minio_port")
30+
String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
31+
32+
sql """drop catalog if exists ${catalog_name}"""
33+
sql """CREATE CATALOG ${catalog_name} PROPERTIES (
34+
'type'='paimon',
35+
'warehouse' = 's3://warehouse/wh/',
36+
"s3.access_key" = "admin",
37+
"s3.secret_key" = "password",
38+
"s3.endpoint" = "http://${externalEnvIp}:${minio_port}",
39+
"s3.region" = "us-east-1"
40+
);"""
41+
42+
logger.info("catalog " + catalog_name + " created")
43+
sql """switch ${catalog_name};"""
44+
logger.info("switched to catalog " + catalog_name)
45+
sql """use ${db_name};"""
46+
logger.info("use " + db_name)
47+
48+
// Use fixed table for stable test results
49+
logger.info("Testing permission checks for Paimon system tables")
50+
String tableName = "ts_scale_orc"
51+
List<List<Object>> paimonTableList = sql """ show tables; """
52+
boolean targetTableExists = paimonTableList.any { row ->
53+
row.size() > 0 && row[0].toString().equals(tableName)
54+
}
55+
assertTrue(targetTableExists, "Target table '${tableName}' not found in database '${db_name}'")
56+
logger.info("Using table: " + tableName)
57+
58+
// Create test user without table permission
59+
String user = "test_paimon_systable_auth_user"
60+
String pwd = 'C123_567p'
61+
try_sql("DROP USER '${user}'@'%'")
62+
sql """CREATE USER '${user}'@'%' IDENTIFIED BY '${pwd}'"""
63+
64+
if (isCloudMode()) {
65+
def clusters = sql " SHOW CLUSTERS; "
66+
assertTrue(!clusters.isEmpty())
67+
def validCluster = clusters[0][0]
68+
sql """GRANT USAGE_PRIV ON CLUSTER `${validCluster}` TO '${user}'@'%'""";
69+
}
70+
71+
sql """create database if not exists internal.regression_test"""
72+
sql """GRANT SELECT_PRIV ON internal.regression_test.* TO '${user}'@'%'"""
73+
74+
// Test that user without table permission cannot query system tables
75+
connect(user, "${pwd}", context.config.jdbcUrl) {
76+
// Test snapshots system table via paimon_meta function
77+
test {
78+
sql """
79+
select * from paimon_meta(
80+
"table" = "${catalog_name}.${db_name}.${tableName}",
81+
"query_type" = "snapshots");
82+
"""
83+
exception "denied"
84+
}
85+
// Test snapshots system table via direct access
86+
test {
87+
sql """
88+
select * from ${catalog_name}.${db_name}.${tableName}\$snapshots
89+
"""
90+
exception "denied"
91+
}
92+
// Test files system table via paimon_meta function
93+
test {
94+
sql """
95+
select * from paimon_meta(
96+
"table" = "${catalog_name}.${db_name}.${tableName}",
97+
"query_type" = "files");
98+
"""
99+
exception "denied"
100+
}
101+
// Test files system table via direct access
102+
test {
103+
sql """
104+
select * from ${catalog_name}.${db_name}.${tableName}\$files
105+
"""
106+
exception "denied"
107+
}
108+
// Test schemas system table via paimon_meta function
109+
test {
110+
sql """
111+
select * from paimon_meta(
112+
"table" = "${catalog_name}.${db_name}.${tableName}",
113+
"query_type" = "schemas");
114+
"""
115+
exception "denied"
116+
}
117+
// Test schemas system table via direct access
118+
test {
119+
sql """
120+
select * from ${catalog_name}.${db_name}.${tableName}\$schemas
121+
"""
122+
exception "denied"
123+
}
124+
// Test partitions system table via paimon_meta function
125+
test {
126+
sql """
127+
select * from paimon_meta(
128+
"table" = "${catalog_name}.${db_name}.${tableName}",
129+
"query_type" = "partitions");
130+
"""
131+
exception "denied"
132+
}
133+
// Test partitions system table via direct access
134+
test {
135+
sql """
136+
select * from ${catalog_name}.${db_name}.${tableName}\$partitions
137+
"""
138+
exception "denied"
139+
}
140+
}
141+
142+
// Grant permission and verify user can query system tables
143+
sql """GRANT SELECT_PRIV ON ${catalog_name}.${db_name}.${tableName} TO '${user}'@'%'"""
144+
connect(user, "${pwd}", context.config.jdbcUrl) {
145+
// Test snapshots system table with permission
146+
sql """
147+
select * from paimon_meta(
148+
"table" = "${catalog_name}.${db_name}.${tableName}",
149+
"query_type" = "snapshots");
150+
"""
151+
sql """select * from ${catalog_name}.${db_name}.${tableName}\$snapshots"""
152+
153+
// Test files system table with permission
154+
sql """
155+
select * from paimon_meta(
156+
"table" = "${catalog_name}.${db_name}.${tableName}",
157+
"query_type" = "files");
158+
"""
159+
sql """select * from ${catalog_name}.${db_name}.${tableName}\$files"""
160+
161+
// Test schemas system table with permission
162+
sql """
163+
select * from paimon_meta(
164+
"table" = "${catalog_name}.${db_name}.${tableName}",
165+
"query_type" = "schemas");
166+
"""
167+
sql """select * from ${catalog_name}.${db_name}.${tableName}\$schemas"""
168+
169+
// Test partitions system table with permission
170+
sql """
171+
select * from paimon_meta(
172+
"table" = "${catalog_name}.${db_name}.${tableName}",
173+
"query_type" = "partitions");
174+
"""
175+
sql """select * from ${catalog_name}.${db_name}.${tableName}\$partitions"""
176+
}
177+
try_sql("DROP USER '${user}'@'%'")
178+
179+
} catch (Exception e) {
180+
logger.error("Paimon system table auth test failed: " + e.getMessage())
181+
throw e
182+
} finally {
183+
// clean resource
184+
try {
185+
sql """drop catalog if exists ${catalog_name}"""
186+
} catch (Exception e) {
187+
logger.warn("Failed to cleanup catalog: " + e.getMessage())
188+
}
189+
}
190+
}
191+

0 commit comments

Comments
 (0)