Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@

import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
import org.apache.doris.catalog.ScalarType;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
import org.apache.doris.common.proc.BackendsProcDir;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.ShowResultSetMetaData;
Expand All @@ -37,10 +39,10 @@ public ShowBackendsStmt() {
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);

if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)
&& !Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(),
PrivPredicate.OPERATOR)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN/OPERATOR");
if (!Env.getCurrentEnv().getAccessManager().checkDbPriv(ConnectContext.get(),
InternalCatalog.INTERNAL_CATALOG_NAME, InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DB_ACCESS_DENIED_ERROR,
PrivPredicate.SELECT.getPrivs().toString(), InfoSchemaDb.DATABASE_NAME);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@

import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
import org.apache.doris.catalog.ScalarType;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.proc.FrontendsProcNode;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.ShowResultSetMetaData;
Expand All @@ -46,10 +48,10 @@ public String getDetailType() {

@Override
public void analyze(Analyzer analyzer) throws AnalysisException {
if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)
&& !Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(),
PrivPredicate.OPERATOR)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN/OPERATOR");
if (!Env.getCurrentEnv().getAccessManager().checkDbPriv(ConnectContext.get(),
InternalCatalog.INTERNAL_CATALOG_NAME, InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DB_ACCESS_DENIED_ERROR,
PrivPredicate.SELECT.getPrivs().toString(), InfoSchemaDb.DATABASE_NAME);
}

if (detail != null && !detail.equalsIgnoreCase("disks")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
package org.apache.doris.httpv2.rest;

import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
import org.apache.doris.httpv2.entity.ResponseEntityBuilder;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.system.Backend;

import com.fasterxml.jackson.annotation.JsonProperty;
Expand Down Expand Up @@ -66,12 +69,8 @@ public class BackendsAction extends RestBaseController {

@RequestMapping(path = "/api/backends", method = {RequestMethod.GET})
public Object getBackends(HttpServletRequest request, HttpServletResponse response) {
/**
* As required, the interface should require user have GlobalAuth-PrivPredicate.ADMIN permission.
* However, a user who uses spark-doris-connector/flink-doris-connector does not have corresponding permission.
* To ensure that the connector works properly, we do not verify the permission of the interface.
*/
executeCheckPassword(request, response);
checkDbAuth(ConnectContext.get().getCurrentUserIdentity(), InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT);

boolean needAlive = false;
String isAlive = request.getParameter(IS_ALIVE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.doris.httpv2.rest.manager;

import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
import org.apache.doris.common.Config;
import org.apache.doris.common.ConfigBase;
import org.apache.doris.common.MarkedCountDownLatch;
Expand Down Expand Up @@ -108,7 +109,7 @@ public class NodeAction extends RestBaseController {
@RequestMapping(path = "/frontends", method = RequestMethod.GET)
public Object frontends_info(HttpServletRequest request, HttpServletResponse response) throws Exception {
executeCheckPassword(request, response);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(), PrivPredicate.ADMIN);
checkDbAuth(ConnectContext.get().getCurrentUserIdentity(), InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT);

return fetchNodeInfo(request, response, "/frontends");
}
Expand All @@ -117,7 +118,7 @@ public Object frontends_info(HttpServletRequest request, HttpServletResponse res
@RequestMapping(path = "/backends", method = RequestMethod.GET)
public Object backends_info(HttpServletRequest request, HttpServletResponse response) throws Exception {
executeCheckPassword(request, response);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(), PrivPredicate.ADMIN);
checkDbAuth(ConnectContext.get().getCurrentUserIdentity(), InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT);

return fetchNodeInfo(request, response, "/backends");
}
Expand All @@ -126,7 +127,7 @@ public Object backends_info(HttpServletRequest request, HttpServletResponse resp
@RequestMapping(path = "/brokers", method = RequestMethod.GET)
public Object brokers_info(HttpServletRequest request, HttpServletResponse response) throws Exception {
executeCheckPassword(request, response);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(), PrivPredicate.ADMIN);
checkDbAuth(ConnectContext.get().getCurrentUserIdentity(), InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT);

return fetchNodeInfo(request, response, "/brokers");
}
Expand Down Expand Up @@ -181,7 +182,7 @@ public NodeInfo(List<String> columnNames, List<List<String>> rows) {
@RequestMapping(path = "/configuration_name", method = RequestMethod.GET)
public Object configurationName(HttpServletRequest request, HttpServletResponse response) {
executeCheckPassword(request, response);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(), PrivPredicate.ADMIN);
checkDbAuth(ConnectContext.get().getCurrentUserIdentity(), InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT);

Map<String, List<String>> result = Maps.newHashMap();
try {
Expand Down Expand Up @@ -220,7 +221,7 @@ public Object configurationName(HttpServletRequest request, HttpServletResponse
@RequestMapping(path = "/node_list", method = RequestMethod.GET)
public Object nodeList(HttpServletRequest request, HttpServletResponse response) {
executeCheckPassword(request, response);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(), PrivPredicate.ADMIN);
checkDbAuth(ConnectContext.get().getCurrentUserIdentity(), InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT);

Map<String, List<String>> result = Maps.newHashMap();
result.put("frontend", getFeList());
Expand All @@ -247,7 +248,7 @@ private static List<String> getBeList() {
@RequestMapping(path = "/config", method = RequestMethod.GET)
public Object config(HttpServletRequest request, HttpServletResponse response) {
executeCheckPassword(request, response);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(), PrivPredicate.ADMIN);
checkDbAuth(ConnectContext.get().getCurrentUserIdentity(), InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT);

List<List<String>> configs = ConfigBase.getConfigInfo(null);
// Sort all configs by config key.
Expand Down Expand Up @@ -308,7 +309,7 @@ public Object configurationInfo(HttpServletRequest request, HttpServletResponse
@RequestParam(value = "type") String type,
@RequestBody(required = false) ConfigInfoRequestBody requestBody) {
executeCheckPassword(request, response);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(), PrivPredicate.ADMIN);
checkGlobalAuth(ConnectContext.get().getCurrentUserIdentity(), PrivPredicate.ADMIN_OR_NODE);

initHttpExecutor();

Expand Down
14 changes: 12 additions & 2 deletions fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2262,8 +2262,13 @@ private void handleShowExport() throws AnalysisException {
resultSet = new ShowResultSet(showExportStmt.getMetaData(), infos);
}

private void handleShowBackends() {
private void handleShowBackends() throws AnalysisException {
final ShowBackendsStmt showStmt = (ShowBackendsStmt) stmt;
try {
showStmt.analyze(null);
} catch (Exception e) {
throw (AnalysisException) e;
}
List<List<String>> backendInfos = BackendsProcDir.getBackendInfos();

backendInfos.sort(new Comparator<List<String>>() {
Expand All @@ -2276,8 +2281,13 @@ public int compare(List<String> o1, List<String> o2) {
resultSet = new ShowResultSet(showStmt.getMetaData(), backendInfos);
}

private void handleShowFrontends() {
private void handleShowFrontends() throws AnalysisException {
final ShowFrontendsStmt showStmt = (ShowFrontendsStmt) stmt;
try {
showStmt.analyze(null);
} catch (Exception e) {
throw (AnalysisException) e;
}

List<List<String>> infos = Lists.newArrayList();
FrontendsProcNode.getFrontendsInfo(Env.getCurrentEnv(), showStmt.getDetailType(), infos);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@
package org.apache.doris.tablefunction;

import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.catalog.ScalarType;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.thrift.TBackendsMetadataParams;
import org.apache.doris.thrift.TMetaScanRange;
import org.apache.doris.thrift.TMetadataType;
Expand Down Expand Up @@ -83,6 +89,12 @@ public BackendsTableValuedFunction(Map<String, String> params) throws AnalysisEx
if (params.size() != 0) {
throw new AnalysisException("backends table-valued-function does not support any params");
}
if (!Env.getCurrentEnv().getAccessManager().checkDbPriv(ConnectContext.get(),
InternalCatalog.INTERNAL_CATALOG_NAME, InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT)) {
String message = ErrorCode.ERR_DB_ACCESS_DENIED_ERROR.formatErrorMsg(
PrivPredicate.SELECT.getPrivs().toString(), InfoSchemaDb.DATABASE_NAME);
throw new AnalysisException(message);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@
package org.apache.doris.tablefunction;

import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
import org.apache.doris.catalog.ScalarType;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.thrift.TFrontendsMetadataParams;
import org.apache.doris.thrift.TMetaScanRange;
import org.apache.doris.thrift.TMetadataType;
Expand Down Expand Up @@ -67,6 +73,12 @@ public FrontendsDisksTableValuedFunction(Map<String, String> params) throws Anal
if (params.size() != 0) {
throw new AnalysisException("frontends_disks table-valued-function does not support any params");
}
if (!Env.getCurrentEnv().getAccessManager().checkDbPriv(ConnectContext.get(),
InternalCatalog.INTERNAL_CATALOG_NAME, InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT)) {
String message = ErrorCode.ERR_DB_ACCESS_DENIED_ERROR.formatErrorMsg(
PrivPredicate.SELECT.getPrivs().toString(), InfoSchemaDb.DATABASE_NAME);
throw new AnalysisException(message);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@
package org.apache.doris.tablefunction;

import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
import org.apache.doris.catalog.ScalarType;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.thrift.TFrontendsMetadataParams;
import org.apache.doris.thrift.TMetaScanRange;
import org.apache.doris.thrift.TMetadataType;
Expand Down Expand Up @@ -76,6 +82,12 @@ public FrontendsTableValuedFunction(Map<String, String> params) throws AnalysisE
if (params.size() != 0) {
throw new AnalysisException("frontends table-valued-function does not support any params");
}
if (!Env.getCurrentEnv().getAccessManager().checkDbPriv(ConnectContext.get(),
InternalCatalog.INTERNAL_CATALOG_NAME, InfoSchemaDb.DATABASE_NAME, PrivPredicate.SELECT)) {
String message = ErrorCode.ERR_DB_ACCESS_DENIED_ERROR.formatErrorMsg(
PrivPredicate.SELECT.getPrivs().toString(), InfoSchemaDb.DATABASE_NAME);
throw new AnalysisException(message);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void testAnalyze() throws Exception {
AtomicBoolean privilege = new AtomicBoolean(false);
new MockUp<AccessControllerManager>() {
@Mock
public boolean checkGlobalPriv(ConnectContext ctx, PrivPredicate wanted) {
public boolean checkDbPriv(UserIdentity currentUser, String ctl, String db, PrivPredicate wanted) {
return privilege.get();
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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.analysis;

import org.apache.doris.common.AnalysisException;
import org.apache.doris.mysql.privilege.AccessControllerManager;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.SessionVariable;

import mockit.Mock;
import mockit.MockUp;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;

import java.util.concurrent.atomic.AtomicBoolean;

public class ShowFrontendsStmtTest {
private Analyzer analyzer;
private ConnectContext ctx = new ConnectContext();

@Before
public void setUp() {
analyzer = AccessTestUtil.fetchAdminAnalyzer(true);
ctx.setSessionVariable(new SessionVariable());
ctx.setThreadLocalInfo();
}

@After
public void tearDown() {
ConnectContext.remove();
}

@Test
public void testAnalyze() throws Exception {
AtomicBoolean privilege = new AtomicBoolean(false);
new MockUp<AccessControllerManager>() {
@Mock
public boolean checkDbPriv(UserIdentity currentUser, String ctl, String db, PrivPredicate wanted) {
return privilege.get();
}
};

ShowFrontendsStmt stmt = new ShowFrontendsStmt();
Assertions.assertThrows(AnalysisException.class, () -> stmt.analyze(analyzer));

privilege.set(true);
stmt.analyze(analyzer);
}

}
14 changes: 13 additions & 1 deletion regression-test/suites/auth_call/test_show_backend_auth.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,26 @@ suite("test_show_backend_auth","p0,auth_call") {
try_sql("DROP USER ${user}")
sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'"""
sql """grant select_priv on regression_test to ${user}"""
sql """grant select_priv on internal.information_schema.* to ${user}"""
def show_grants_result = sql """show grants for ${user}"""
logger.info("show grants result: " + show_grants_result)
sql """revoke select_priv on internal.information_schema.* from ${user}"""

connect(user, "${pwd}", context.config.jdbcUrl) {

try {
def show_result = sql """SHOW BACKENDS"""
logger.info("show_result: " + show_result)
} catch (Exception e) {
logger.info("show_result: " + e)
e.printStackTrace()
}
test {
sql """SHOW BACKENDS"""
exception "denied"
}
}
sql """grant node_priv on *.*.* to ${user}"""
sql """grant select_priv on internal.information_schema.* to ${user}"""
connect(user, "${pwd}", context.config.jdbcUrl) {
def res = sql """SHOW BACKENDS"""
assertTrue(res.size() > 0)
Expand Down
Loading