Skip to content

Commit

Permalink
Add privilege check for ShowTablesExecutor
Browse files Browse the repository at this point in the history
  • Loading branch information
RaigorJiang committed Oct 31, 2024
1 parent 522d795 commit 3b90c59
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.sphereex.dbplusengine.authority.distsql.statement.user.ShowDistUsersStatement;
import lombok.Setter;
import org.apache.shardingsphere.authority.config.UserConfiguration;
import org.apache.shardingsphere.authority.rule.AuthorityRule;
import org.apache.shardingsphere.distsql.handler.aware.DistSQLExecutorRuleAware;
import org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor;
Expand All @@ -39,12 +40,16 @@ public final class ShowDistUsersExecutor implements DistSQLQueryExecutor<ShowDis

@Override
public Collection<String> getColumnNames(final ShowDistUsersStatement sqlStatement) {
return Arrays.asList("host", "user");
return Arrays.asList("host", "user", "is_admin");
}

@Override
public Collection<LocalDataQueryResultRow> getRows(final ShowDistUsersStatement sqlStatement, final ContextManager contextManager) {
return rule.getGrantees().stream().map(each -> new LocalDataQueryResultRow(each.getHostname(), each.getUsername())).collect(Collectors.toList());
return rule.getConfiguration().getUsers().stream().map(this::getRow).collect(Collectors.toList());
}

private LocalDataQueryResultRow getRow(final UserConfiguration user) {
return new LocalDataQueryResultRow(user.getHostname(), user.getUsername(), user.isAdmin() ? "Y" : "N");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@

package org.apache.shardingsphere.proxy.backend.mysql.handler.admin.executor;

import com.sphereex.dbplusengine.SphereEx;
import com.sphereex.dbplusengine.SphereEx.Type;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.authority.checker.AuthorityChecker;
import org.apache.shardingsphere.authority.rule.AuthorityRule;
import org.apache.shardingsphere.infra.database.core.metadata.database.system.SystemDatabase;
import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
Expand All @@ -30,6 +34,7 @@
import org.apache.shardingsphere.infra.merge.result.MergedResult;
import org.apache.shardingsphere.infra.merge.result.impl.transparent.TransparentMergedResult;
import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
import org.apache.shardingsphere.infra.metadata.user.Grantee;
import org.apache.shardingsphere.infra.util.regex.RegexUtils;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
import org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAdminQueryExecutor;
Expand Down Expand Up @@ -67,7 +72,9 @@ public final class ShowTablesExecutor implements DatabaseAdminQueryExecutor {
public void execute(final ConnectionSession connectionSession) {
String databaseName = sqlStatement.getFromDatabase().map(schema -> schema.getDatabase().getIdentifier().getValue()).orElseGet(connectionSession::getUsedDatabaseName);
queryResultMetaData = createQueryResultMetaData(databaseName);
mergedResult = new TransparentMergedResult(getQueryResult(databaseName));
// SPEX CHANGED: BEGIN
mergedResult = new TransparentMergedResult(getQueryResult(databaseName, connectionSession.getConnectionContext().getGrantee()));
// SPEX CHANGED: END
}

private QueryResultMetaData createQueryResultMetaData(final String databaseName) {
Expand All @@ -80,12 +87,14 @@ private QueryResultMetaData createQueryResultMetaData(final String databaseName)
return new RawQueryResultMetaData(columnNames);
}

private QueryResult getQueryResult(final String databaseName) {
private QueryResult getQueryResult(final String databaseName, @SphereEx final Grantee grantee) {
SystemDatabase systemDatabase = new SystemDatabase(databaseType);
if (!systemDatabase.getSystemSchemas().contains(databaseName) && !ProxyContext.getInstance().getContextManager().getDatabase(databaseName).isComplete()) {
return new RawMemoryQueryResult(queryResultMetaData, Collections.emptyList());
}
List<MemoryQueryResultDataRow> rows = getTables(databaseName).stream().map(this::getRow).collect(Collectors.toList());
// SPEX CHANGED: BEGIN
List<MemoryQueryResultDataRow> rows = getTables(databaseName, grantee).stream().map(this::getRow).collect(Collectors.toList());
// SPEX CHANGED: END
return new RawMemoryQueryResult(queryResultMetaData, rows);
}

Expand All @@ -95,9 +104,13 @@ private MemoryQueryResultDataRow getRow(final ShardingSphereTable table) {
: new MemoryQueryResultDataRow(Collections.singletonList(table.getName()));
}

private Collection<ShardingSphereTable> getTables(final String databaseName) {
private Collection<ShardingSphereTable> getTables(final String databaseName, @SphereEx final Grantee grantee) {
@SphereEx(Type.MODIFY)
Collection<ShardingSphereTable> tables = ProxyContext.getInstance().getContextManager().getDatabase(databaseName).getSchema(databaseName).getTables().values();
Collection<ShardingSphereTable> filteredTables = filterByLike(tables);
// SPEX ADDED: BEGIN
filteredTables = filterByPrivilege(databaseName, grantee, filteredTables);
// SPEX ADDED: END
return filteredTables.stream().sorted(Comparator.comparing(ShardingSphereTable::getName)).collect(Collectors.toList());
}

Expand All @@ -106,6 +119,13 @@ private Collection<ShardingSphereTable> filterByLike(final Collection<ShardingSp
return likePattern.isPresent() ? tables.stream().filter(each -> likePattern.get().matcher(each.getName()).matches()).collect(Collectors.toList()) : tables;
}

@SphereEx
private Collection<ShardingSphereTable> filterByPrivilege(final String databaseName, final Grantee grantee, final Collection<ShardingSphereTable> tables) {
AuthorityRule authorityRule = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
AuthorityChecker authorityChecker = new AuthorityChecker(authorityRule, grantee);
return tables.stream().filter(each -> authorityChecker.isAuthorized(databaseName, each.getName())).collect(Collectors.toList());
}

private Optional<Pattern> getLikePattern() {
if (!sqlStatement.getFilter().isPresent()) {
return Optional.empty();
Expand Down

0 comments on commit 3b90c59

Please sign in to comment.