branch-2.1:[fix](auth)Fix the issue of incorrectly checking base table permissio… (#54005)
…ns when querying external views (#53786) pick: https://github.com/apache/doris/pull/53786
This commit is contained in:
@ -49,7 +49,7 @@ import java.util.List;
|
||||
* Refreshing or invalidating a view will reload the view's definition but will not
|
||||
* affect the metadata of the underlying tables (if any).
|
||||
*/
|
||||
public class View extends Table {
|
||||
public class View extends Table implements ViewIf {
|
||||
private static final Logger LOG = LogManager.getLogger(View.class);
|
||||
|
||||
// The original SQL-string given as view definition. Set during analysis.
|
||||
@ -207,6 +207,11 @@ public class View extends Table {
|
||||
return colLabels != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getViewText() {
|
||||
return inlineViewDef;
|
||||
}
|
||||
|
||||
// Get the md5 of signature string of this view.
|
||||
// This method is used to determine whether the views have the same schema.
|
||||
// Contains:
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
// 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.
|
||||
|
||||
package org.apache.doris.catalog;
|
||||
|
||||
public interface ViewIf extends TableIf {
|
||||
String getViewText();
|
||||
}
|
||||
|
||||
@ -0,0 +1,204 @@
|
||||
// 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.
|
||||
|
||||
package org.apache.doris.datasource;
|
||||
|
||||
import org.apache.doris.catalog.Column;
|
||||
import org.apache.doris.catalog.DatabaseIf;
|
||||
import org.apache.doris.catalog.ViewIf;
|
||||
import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.statistics.AnalysisInfo;
|
||||
import org.apache.doris.statistics.BaseAnalysisTask;
|
||||
import org.apache.doris.statistics.ColumnStatistic;
|
||||
import org.apache.doris.statistics.TableStatsMeta;
|
||||
import org.apache.doris.thrift.TTableDescriptor;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public class ExternalView implements ViewIf {
|
||||
private String viewText;
|
||||
private ExternalTable externalTable;
|
||||
|
||||
public ExternalView(ExternalTable externalTable, String viewText) {
|
||||
this.viewText = viewText;
|
||||
this.externalTable = externalTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getViewText() {
|
||||
return viewText;
|
||||
}
|
||||
|
||||
public ExternalTable getExternalTable() {
|
||||
return externalTable;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return externalTable.getId();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return externalTable.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableType getType() {
|
||||
return externalTable.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Column> getFullSchema() {
|
||||
return externalTable.getFullSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Column> getBaseSchema() {
|
||||
return externalTable.getBaseSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Column> getSchemaAllIndexes(boolean full) {
|
||||
return externalTable.getSchemaAllIndexes(full);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Column> getBaseSchema(boolean full) {
|
||||
return externalTable.getBaseSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNewFullSchema(List<Column> newSchema) {
|
||||
externalTable.setNewFullSchema(newSchema);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Column getColumn(String name) {
|
||||
return externalTable.getColumn(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMysqlType() {
|
||||
return externalTable.getMysqlType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEngine() {
|
||||
return externalTable.getEngine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment() {
|
||||
return externalTable.getComment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCreateTime() {
|
||||
return externalTable.getCreateTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUpdateTime() {
|
||||
return externalTable.getUpdateTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRowCount() {
|
||||
return externalTable.getRowCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCachedRowCount() {
|
||||
return externalTable.getCachedRowCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long fetchRowCount() {
|
||||
return externalTable.fetchRowCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDataLength() {
|
||||
return externalTable.getDataLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAvgRowLength() {
|
||||
return externalTable.getAvgRowLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastCheckTime() {
|
||||
return externalTable.getLastCheckTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment(boolean escapeQuota) {
|
||||
return externalTable.getComment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TTableDescriptor toThrift() {
|
||||
return externalTable.toThrift();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseAnalysisTask createAnalysisTask(AnalysisInfo info) {
|
||||
return externalTable.createAnalysisTask(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseIf getDatabase() {
|
||||
return externalTable.getDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ColumnStatistic> getColumnStatistic(String colName) {
|
||||
return externalTable.getColumnStatistic(colName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needReAnalyzeTable(TableStatsMeta tblStats) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pair<String, String>> getColumnIndexPairs(Set<String> columns) {
|
||||
return externalTable.getColumnIndexPairs(columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> getChunkSizes() {
|
||||
return externalTable.getChunkSizes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput out) throws IOException {
|
||||
externalTable.write(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean autoAnalyzeEnabled() {
|
||||
return externalTable.autoAnalyzeEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
@ -33,6 +33,7 @@ import org.apache.doris.common.Config;
|
||||
import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.common.util.Util;
|
||||
import org.apache.doris.datasource.ExternalTable;
|
||||
import org.apache.doris.datasource.ExternalView;
|
||||
import org.apache.doris.datasource.hive.HMSExternalTable;
|
||||
import org.apache.doris.datasource.hive.HMSExternalTable.DLAType;
|
||||
import org.apache.doris.nereids.CTEContext;
|
||||
@ -464,7 +465,8 @@ public class BindRelation extends OneAnalysisRuleFactory {
|
||||
ctx.changeDefaultCatalog(hiveCatalog);
|
||||
ctx.setDatabase(hiveDb);
|
||||
try {
|
||||
return parseAndAnalyzeView(table, ddlSql, cascadesContext);
|
||||
return new LogicalView<>(new ExternalView(table, ddlSql),
|
||||
parseAndAnalyzeView(table, ddlSql, cascadesContext));
|
||||
} finally {
|
||||
// restore catalog and db in connect context
|
||||
ctx.changeDefaultCatalog(previousCatalog);
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.doris.nereids.trees.plans.logical;
|
||||
|
||||
import org.apache.doris.catalog.View;
|
||||
import org.apache.doris.catalog.ViewIf;
|
||||
import org.apache.doris.nereids.exceptions.AnalysisException;
|
||||
import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.properties.FdItem;
|
||||
@ -40,10 +40,10 @@ import java.util.Optional;
|
||||
|
||||
/** LogicalView */
|
||||
public class LogicalView<BODY extends Plan> extends LogicalUnary<BODY> {
|
||||
private final View view;
|
||||
private final ViewIf view;
|
||||
|
||||
/** LogicalView */
|
||||
public LogicalView(View view, BODY body) {
|
||||
public LogicalView(ViewIf view, BODY body) {
|
||||
super(PlanType.LOGICAL_VIEW, Optional.empty(), Optional.empty(), body);
|
||||
this.view = Objects.requireNonNull(view, "catalog can not be null");
|
||||
if (!(body instanceof LogicalPlan)) {
|
||||
@ -73,11 +73,7 @@ public class LogicalView<BODY extends Plan> extends LogicalUnary<BODY> {
|
||||
return view.getName();
|
||||
}
|
||||
|
||||
public String getViewString() {
|
||||
return view.getInlineViewDef();
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
public ViewIf getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
// 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_select_external_view_auth","p0,auth") {
|
||||
String enabled = context.config.otherConfigs.get("enableHiveTest")
|
||||
if (enabled == null || !enabled.equalsIgnoreCase("true")) {
|
||||
logger.info("diable Hive test.")
|
||||
return;
|
||||
}
|
||||
for (String hivePrefix : ["hive2", "hive3"]) {
|
||||
try {
|
||||
String hms_port = context.config.otherConfigs.get(hivePrefix + "HmsPort")
|
||||
String catalogName = "${hivePrefix}_test_mtmv"
|
||||
String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
|
||||
|
||||
sql """drop catalog if exists ${catalogName}"""
|
||||
sql """create catalog if not exists ${catalogName} properties (
|
||||
"type"="hms",
|
||||
'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}'
|
||||
);"""
|
||||
|
||||
String suiteName = "test_select_external_view_auth"
|
||||
String user = "${suiteName}_user"
|
||||
String pwd = 'C123_567p'
|
||||
String dbName = "`default`"
|
||||
String tableName = "sale_table"
|
||||
String viewName = "test_view1"
|
||||
|
||||
try_sql("drop user ${user}")
|
||||
sql """create user '${user}' IDENTIFIED by '${pwd}'"""
|
||||
sql """grant select_priv on regression_test to ${user}"""
|
||||
|
||||
//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 """grant select_priv on ${catalogName}.${dbName}.${tableName} to ${user}"""
|
||||
// table column
|
||||
connect(user, "${pwd}", context.config.jdbcUrl) {
|
||||
try {
|
||||
sql "select * from ${catalogName}.${dbName}.${viewName}"
|
||||
} catch (Exception e) {
|
||||
log.info(e.getMessage())
|
||||
assertTrue(e.getMessage().contains("denied"))
|
||||
}
|
||||
}
|
||||
sql """revoke select_priv on ${catalogName}.${dbName}.${tableName} from ${user}"""
|
||||
sql """grant select_priv on ${catalogName}.${dbName}.${viewName} to ${user}"""
|
||||
connect(user, "${pwd}", context.config.jdbcUrl) {
|
||||
sql "select * from ${catalogName}.${dbName}.${viewName}"
|
||||
}
|
||||
try_sql("drop user ${user}")
|
||||
sql """drop catalog if exists ${catalogName}"""
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user