From 8324e65d342a14e41a68d4bc2df587bc1ec275b0 Mon Sep 17 00:00:00 2001 From: Raigor Date: Fri, 1 Nov 2024 11:33:40 +0800 Subject: [PATCH] Fix privilege check in CreateDatabaseBackendHandler (#32) --- .../authority/obj/domain/RALACLObject.java | 26 ++++++++++ .../dal/dialect/MySQLACLObjectExtractor.java | 25 +++++++++- .../type/ddl/DDLACLObjectExtractor.java | 15 ++++++ .../CreateDatabaseACLObjectExtractor.java | 45 +++++++++++++++++ .../type/CreateIndexACLObjectExtractor.java | 50 +++++++++++++++++++ .../ddl/type/DropIndexACLObjectExtractor.java | 46 +++++++++++++++++ .../distsql/DistSQLACLObjectExtractor.java | 7 +++ .../operation/ACLOperationExtractor.java | 16 ++++-- .../cases/show-dist-users-current-config.yaml | 1 + .../test/resources/cases/show-dist-users.xml | 2 +- .../backend/connector/DatabaseConnector.java | 35 +++++++++++++ .../ProxyDatabaseConnectionManager.java | 22 ++++++++ .../CreateDatabaseBackendHandler.java | 7 ++- .../CreateDatabaseBackendHandlerTest.java | 16 ++++-- ...abaseOperateBackendHandlerFactoryTest.java | 1 + .../DropDatabaseBackendHandlerTest.java | 7 ++- .../executor/ShowTablesExecutorTest.java | 3 ++ 17 files changed, 311 insertions(+), 13 deletions(-) create mode 100644 kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/domain/RALACLObject.java create mode 100644 kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/CreateDatabaseACLObjectExtractor.java create mode 100644 kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/CreateIndexACLObjectExtractor.java create mode 100644 kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/DropIndexACLObjectExtractor.java diff --git a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/domain/RALACLObject.java b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/domain/RALACLObject.java new file mode 100644 index 00000000000000..3995a355339186 --- /dev/null +++ b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/domain/RALACLObject.java @@ -0,0 +1,26 @@ +/* + * 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 com.sphereex.dbplusengine.authority.obj.domain; + +import com.sphereex.dbplusengine.authority.model.obj.ACLObject; + +/** + * RAL ACL object. + */ +public final class RALACLObject implements ACLObject { +} diff --git a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/dal/dialect/MySQLACLObjectExtractor.java b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/dal/dialect/MySQLACLObjectExtractor.java index 5bf40fd7a7f7b9..17d45cae812d2e 100644 --- a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/dal/dialect/MySQLACLObjectExtractor.java +++ b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/dal/dialect/MySQLACLObjectExtractor.java @@ -18,9 +18,12 @@ package com.sphereex.dbplusengine.authority.obj.extractor.type.dal.dialect; import com.sphereex.dbplusengine.authority.model.obj.ACLObject; +import com.sphereex.dbplusengine.authority.obj.domain.TableACLObject; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.sql.parser.statement.mysql.MySQLStatement; +import org.apache.shardingsphere.sql.parser.statement.mysql.dal.MySQLShowCreateTableStatement; +import org.apache.shardingsphere.sql.parser.statement.mysql.ddl.MySQLDropIndexStatement; import java.util.Collection; import java.util.Collections; @@ -39,7 +42,27 @@ public final class MySQLACLObjectExtractor { * @return extracted ACL objects */ public static Collection extract(final String currentDatabase, final MySQLStatement sqlStatement) { - // TODO + if (sqlStatement instanceof MySQLShowCreateTableStatement) { + return extractSowCreateTableStatement(currentDatabase, (MySQLShowCreateTableStatement) sqlStatement); + } + if (sqlStatement instanceof MySQLDropIndexStatement) { + return extractDropIndexStatement(currentDatabase, (MySQLDropIndexStatement) sqlStatement); + } return Collections.emptyList(); } + + private static Collection extractSowCreateTableStatement(final String currentDatabase, final MySQLShowCreateTableStatement sqlStatement) { + String database = sqlStatement.getTable().getOwner().map(optional -> optional.getIdentifier().getValue()).orElse(currentDatabase); + String table = sqlStatement.getTable().getTableName().getIdentifier().getValue(); + return Collections.singleton(new TableACLObject(database, table)); + } + + private static Collection extractDropIndexStatement(final String currentDatabase, final MySQLDropIndexStatement sqlStatement) { + if (!sqlStatement.getSimpleTable().isPresent()) { + return Collections.emptyList(); + } + String database = sqlStatement.getSimpleTable().get().getOwner().map(optional -> optional.getIdentifier().getValue()).orElse(currentDatabase); + String table = sqlStatement.getSimpleTable().get().getTableName().getIdentifier().getValue(); + return Collections.singleton(new TableACLObject(database, table)); + } } diff --git a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/DDLACLObjectExtractor.java b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/DDLACLObjectExtractor.java index 4bd9d9e018590b..322425284ed467 100644 --- a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/DDLACLObjectExtractor.java +++ b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/DDLACLObjectExtractor.java @@ -19,16 +19,22 @@ import com.sphereex.dbplusengine.authority.model.obj.ACLObject; import com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type.AlterTableACLObjectExtractor; +import com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type.CreateDatabaseACLObjectExtractor; +import com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type.CreateIndexACLObjectExtractor; import com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type.CreateTableACLObjectExtractor; import com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type.DropDatabaseACLObjectExtractor; +import com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type.DropIndexACLObjectExtractor; import com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type.DropTableACLObjectExtractor; import com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type.TruncateTableACLObjectExtractor; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.AlterTableStatement; +import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateDatabaseStatement; +import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateIndexStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateTableStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DropDatabaseStatement; +import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DropIndexStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DropTableStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.TruncateStatement; @@ -58,9 +64,18 @@ public static Collection extract(final String currentDatabase, final if (sqlStatement instanceof DropTableStatement) { return DropTableACLObjectExtractor.extract(currentDatabase, (DropTableStatement) sqlStatement); } + if (sqlStatement instanceof CreateIndexStatement) { + return CreateIndexACLObjectExtractor.extract(currentDatabase, (CreateIndexStatement) sqlStatement); + } + if (sqlStatement instanceof DropIndexStatement) { + return DropIndexACLObjectExtractor.extract(currentDatabase, (DropIndexStatement) sqlStatement); + } if (sqlStatement instanceof TruncateStatement) { return TruncateTableACLObjectExtractor.extract(currentDatabase, (TruncateStatement) sqlStatement); } + if (sqlStatement instanceof CreateDatabaseStatement) { + return CreateDatabaseACLObjectExtractor.extract((CreateDatabaseStatement) sqlStatement); + } if (sqlStatement instanceof DropDatabaseStatement) { return DropDatabaseACLObjectExtractor.extract((DropDatabaseStatement) sqlStatement); } diff --git a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/CreateDatabaseACLObjectExtractor.java b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/CreateDatabaseACLObjectExtractor.java new file mode 100644 index 00000000000000..92f9097040b633 --- /dev/null +++ b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/CreateDatabaseACLObjectExtractor.java @@ -0,0 +1,45 @@ +/* + * 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 com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type; + +import com.sphereex.dbplusengine.authority.model.obj.ACLObject; +import com.sphereex.dbplusengine.authority.obj.domain.TableACLObject; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.shardingsphere.authority.constant.AuthorityConstants; +import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateDatabaseStatement; + +import java.util.Collection; +import java.util.Collections; + +/** + * Create database ACL object extractor. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class CreateDatabaseACLObjectExtractor { + + /** + * Extract ACL objects. + * + * @param sqlStatement create database statement + * @return extracted ACL objects + */ + public static Collection extract(final CreateDatabaseStatement sqlStatement) { + return Collections.singleton(new TableACLObject(sqlStatement.getDatabaseName(), AuthorityConstants.PRIVILEGE_WILDCARD)); + } +} diff --git a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/CreateIndexACLObjectExtractor.java b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/CreateIndexACLObjectExtractor.java new file mode 100644 index 00000000000000..8a1d8f7f2c990f --- /dev/null +++ b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/CreateIndexACLObjectExtractor.java @@ -0,0 +1,50 @@ +/* + * 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 com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type; + +import com.sphereex.dbplusengine.authority.model.obj.ACLObject; +import com.sphereex.dbplusengine.authority.obj.domain.TableACLObject; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateIndexStatement; + +import java.util.Collection; +import java.util.Collections; + +/** + * Create index ACL object extractor. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class CreateIndexACLObjectExtractor { + + /** + * Extract ACL objects. + * + * @param currentDatabase current database name + * @param sqlStatement create index statement + * @return extracted ACL objects + */ + public static Collection extract(final String currentDatabase, final CreateIndexStatement sqlStatement) { + if (null == sqlStatement.getTable()) { + return Collections.emptyList(); + } + String database = sqlStatement.getTable().getOwner().map(optional -> optional.getIdentifier().getValue()).orElse(currentDatabase); + String table = sqlStatement.getTable().getTableName().getIdentifier().getValue(); + return Collections.singleton(new TableACLObject(database, table)); + } +} diff --git a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/DropIndexACLObjectExtractor.java b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/DropIndexACLObjectExtractor.java new file mode 100644 index 00000000000000..d6e8fc1f93e344 --- /dev/null +++ b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/ddl/type/DropIndexACLObjectExtractor.java @@ -0,0 +1,46 @@ +/* + * 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 com.sphereex.dbplusengine.authority.obj.extractor.type.ddl.type; + +import com.sphereex.dbplusengine.authority.model.obj.ACLObject; +import com.sphereex.dbplusengine.authority.obj.extractor.type.dal.dialect.MySQLACLObjectExtractor; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DropIndexStatement; +import org.apache.shardingsphere.sql.parser.statement.mysql.MySQLStatement; + +import java.util.Collection; +import java.util.Collections; + +/** + * Drop index ACL object extractor. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class DropIndexACLObjectExtractor { + + /** + * Extract ACL objects. + * + * @param currentDatabase current database name + * @param sqlStatement drop index statement + * @return extracted ACL objects + */ + public static Collection extract(final String currentDatabase, final DropIndexStatement sqlStatement) { + return sqlStatement instanceof MySQLStatement ? MySQLACLObjectExtractor.extract(currentDatabase, (MySQLStatement) sqlStatement) : Collections.emptyList(); + } +} diff --git a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/distsql/DistSQLACLObjectExtractor.java b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/distsql/DistSQLACLObjectExtractor.java index 3f6b28b3ab9cfb..6211b9b3655568 100644 --- a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/distsql/DistSQLACLObjectExtractor.java +++ b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/obj/extractor/type/distsql/DistSQLACLObjectExtractor.java @@ -20,12 +20,16 @@ import com.sphereex.dbplusengine.authority.model.obj.ACLObject; import com.sphereex.dbplusengine.authority.obj.domain.DCLACLObject; import com.sphereex.dbplusengine.authority.obj.domain.DistSQLACLObject; +import com.sphereex.dbplusengine.authority.obj.domain.RALACLObject; import com.sphereex.dbplusengine.distsql.acl.DistSQLACLObjectUtils; import com.sphereex.dbplusengine.distsql.extractor.DistSQLResourceIdentifierExtractor; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.authority.constant.AuthorityConstants; import org.apache.shardingsphere.distsql.statement.DistSQLStatement; +import org.apache.shardingsphere.distsql.statement.ral.RALStatement; +import org.apache.shardingsphere.distsql.statement.rdl.rule.global.GlobalRuleDefinitionStatement; +import org.apache.shardingsphere.distsql.statement.rql.rule.global.ShowGlobalRulesStatement; import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader; import org.apache.shardingsphere.sql.parser.statement.core.statement.dcl.DCLStatement; @@ -51,6 +55,9 @@ public static Collection extract(final String currentDatabase, final if (sqlStatement instanceof DCLStatement) { return Collections.singleton(new DCLACLObject()); } + if (sqlStatement instanceof RALStatement || sqlStatement instanceof ShowGlobalRulesStatement || sqlStatement instanceof GlobalRuleDefinitionStatement) { + return Collections.singleton(new RALACLObject()); + } Collection aclObjectNames = TypedSPILoader.findService(DistSQLResourceIdentifierExtractor.class, sqlStatement.getClass()) .map(optional -> optional.extract(sqlStatement)).orElse(Collections.emptyList()); String aclObjectTypeName = DistSQLACLObjectUtils.getACLObject(sqlStatement.getClass()); diff --git a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/operation/ACLOperationExtractor.java b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/operation/ACLOperationExtractor.java index d71aad4d7e3e43..b7474f492e0638 100644 --- a/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/operation/ACLOperationExtractor.java +++ b/kernel/authority/core/src/main/java/com/sphereex/dbplusengine/authority/operation/ACLOperationExtractor.java @@ -22,25 +22,31 @@ import lombok.NoArgsConstructor; import org.apache.shardingsphere.distsql.statement.DistSQLStatement; import org.apache.shardingsphere.distsql.statement.ral.RALStatement; +import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type.AlterStorageUnitStatement; import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type.RegisterStorageUnitStatement; import org.apache.shardingsphere.distsql.statement.rdl.resource.unit.type.UnregisterStorageUnitStatement; import org.apache.shardingsphere.distsql.statement.rdl.rule.database.type.AlterRuleStatement; import org.apache.shardingsphere.distsql.statement.rdl.rule.database.type.CreateRuleStatement; import org.apache.shardingsphere.distsql.statement.rdl.rule.database.type.DropRuleStatement; +import org.apache.shardingsphere.distsql.statement.rdl.rule.global.GlobalRuleDefinitionStatement; import org.apache.shardingsphere.distsql.statement.rql.resource.ShowStorageUnitsStatement; import org.apache.shardingsphere.distsql.statement.rql.rule.database.ShowDatabaseRulesStatement; +import org.apache.shardingsphere.distsql.statement.rql.rule.global.ShowGlobalRulesStatement; import org.apache.shardingsphere.distsql.statement.rul.sql.FormatStatement; import org.apache.shardingsphere.distsql.statement.rul.sql.ParseStatement; import org.apache.shardingsphere.distsql.statement.rul.sql.PreviewStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.dcl.DCLStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.AlterDatabaseStatement; +import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.AlterIndexStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.AlterTableStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateDatabaseStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateFunctionStatement; +import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateIndexStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.CreateTableStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DDLStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DropDatabaseStatement; +import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DropIndexStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.DropTableStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.ddl.TruncateStatement; import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.DMLStatement; @@ -102,7 +108,7 @@ private static ACLOperation extractDDL(final DDLStatement sqlStatement) { if (sqlStatement instanceof AlterDatabaseStatement) { return ACLOperation.ALTER_ANY_DATABASE; } - if (sqlStatement instanceof AlterTableStatement) { + if (sqlStatement instanceof AlterTableStatement || isIndexDDLStatement(sqlStatement)) { return ACLOperation.ALTER; } if (sqlStatement instanceof CreateFunctionStatement) { @@ -114,6 +120,10 @@ private static ACLOperation extractDDL(final DDLStatement sqlStatement) { return ACLOperation.UNKNOWN; } + private static boolean isIndexDDLStatement(final SQLStatement sqlStatement) { + return sqlStatement instanceof CreateIndexStatement || sqlStatement instanceof AlterIndexStatement || sqlStatement instanceof DropIndexStatement; + } + private static ACLOperation extractDistSQL(final DistSQLStatement sqlStatement) { if (sqlStatement instanceof CreateRuleStatement) { return ACLOperation.CREATE_RULE; @@ -127,7 +137,7 @@ private static ACLOperation extractDistSQL(final DistSQLStatement sqlStatement) if (sqlStatement instanceof ShowDatabaseRulesStatement || sqlStatement instanceof ShowStorageUnitsStatement) { return ACLOperation.SHOW_RULES; } - if (sqlStatement instanceof RegisterStorageUnitStatement) { + if (sqlStatement instanceof RegisterStorageUnitStatement || sqlStatement instanceof AlterStorageUnitStatement) { return ACLOperation.REGISTER; } if (sqlStatement instanceof UnregisterStorageUnitStatement) { @@ -145,7 +155,7 @@ private static ACLOperation extractDistSQL(final DistSQLStatement sqlStatement) if (sqlStatement instanceof ParseStatement) { return ACLOperation.PARSE; } - if (sqlStatement instanceof RALStatement) { + if (sqlStatement instanceof RALStatement || sqlStatement instanceof ShowGlobalRulesStatement || sqlStatement instanceof GlobalRuleDefinitionStatement) { return ACLOperation.RAL_OPERATE; } return ACLOperation.UNKNOWN; diff --git a/kernel/authority/distsql/handler/src/test/resources/cases/show-dist-users-current-config.yaml b/kernel/authority/distsql/handler/src/test/resources/cases/show-dist-users-current-config.yaml index aaf25b0fb62f9e..7cafac73832e81 100644 --- a/kernel/authority/distsql/handler/src/test/resources/cases/show-dist-users-current-config.yaml +++ b/kernel/authority/distsql/handler/src/test/resources/cases/show-dist-users-current-config.yaml @@ -21,4 +21,5 @@ rules: users: - user: root@% password: 123456 + admin: true #SPEX ADDED: END diff --git a/kernel/authority/distsql/handler/src/test/resources/cases/show-dist-users.xml b/kernel/authority/distsql/handler/src/test/resources/cases/show-dist-users.xml index 29266eece3709e..31f2fd34f2a4e5 100644 --- a/kernel/authority/distsql/handler/src/test/resources/cases/show-dist-users.xml +++ b/kernel/authority/distsql/handler/src/test/resources/cases/show-dist-users.xml @@ -19,7 +19,7 @@ - %|root + %|root|Y diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java index b0dafc5784930f..10c02521cea9fe 100644 --- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java +++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java @@ -17,6 +17,7 @@ package org.apache.shardingsphere.proxy.backend.connector; +import com.sphereex.dbplusengine.SphereEx; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.shardingsphere.infra.binder.context.aware.CursorAware; @@ -398,6 +399,12 @@ private Collection closeResultSets() { try { each.close(); } catch (final SQLException ex) { + // SPEX ADDED: BEGIN + if (isClosed(each)) { + log.info("ResultSet is already closed", ex); + continue; + } + // SPEX ADDED: END result.add(ex); } } @@ -412,6 +419,12 @@ private Collection closeStatements() { each.cancel(); each.close(); } catch (final SQLException ex) { + // SPEX ADDED: BEGIN + if (isClosed(each)) { + log.info("Statement is already closed", ex); + continue; + } + // SPEX ADDED: END result.add(ex); } } @@ -419,6 +432,28 @@ private Collection closeStatements() { return result; } + @SphereEx + private boolean isClosed(final ResultSet resultSet) { + try { + if (resultSet.isClosed()) { + return true; + } + } catch (final SQLException ignored) { + } + return false; + } + + @SphereEx + private boolean isClosed(final Statement statement) { + try { + if (statement.isClosed()) { + return true; + } + } catch (final SQLException ignored) { + } + return false; + } + private Optional closeSQLFederationEngine() { if (null != proxySQLExecutor.getSqlFederationEngine()) { try { diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/ProxyDatabaseConnectionManager.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/ProxyDatabaseConnectionManager.java index 9ff69eb0ccd186..bbda0bd73288f2 100644 --- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/ProxyDatabaseConnectionManager.java +++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/ProxyDatabaseConnectionManager.java @@ -20,8 +20,10 @@ import com.google.common.base.Preconditions; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; +import com.sphereex.dbplusengine.SphereEx; import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.apache.shardingsphere.infra.database.core.type.DatabaseType; import org.apache.shardingsphere.infra.executor.sql.execute.engine.ConnectionMode; import org.apache.shardingsphere.infra.executor.sql.prepare.driver.DatabaseConnectionManager; @@ -53,6 +55,9 @@ /** * Database connection manager of ShardingSphere-Proxy. */ +// SPEX ADDED: BEGIN +@Slf4j +// SPEX ADDED: END @RequiredArgsConstructor @Getter public final class ProxyDatabaseConnectionManager implements DatabaseConnectionManager { @@ -328,6 +333,12 @@ public Collection closeConnections(final boolean forceRollback) { } each.close(); } catch (final SQLException ex) { + // SPEX ADDED: BEGIN + if (isClosed(each)) { + log.info("Connection is already closed", ex); + continue; + } + // SPEX ADDED: END result.add(ex); } } @@ -339,6 +350,17 @@ public Collection closeConnections(final boolean forceRollback) { return result; } + @SphereEx + private boolean isClosed(final Connection connection) { + try { + if (connection.isClosed()) { + return true; + } + } catch (final SQLException ignored) { + } + return false; + } + private void resetSessionVariablesIfNecessary(final Collection values, final Collection exceptions) { if (connectionSession.getRequiredSessionVariableRecorder().isEmpty() || values.isEmpty()) { return; diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandler.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandler.java index 2b7e15cf9007ab..1b5e0cf6033778 100644 --- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandler.java +++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandler.java @@ -18,11 +18,9 @@ package org.apache.shardingsphere.proxy.backend.handler.database; import com.sphereex.dbplusengine.SphereEx; -import com.sphereex.dbplusengine.authority.exception.access.UnauthorizedDatabaseException; import lombok.RequiredArgsConstructor; import org.apache.shardingsphere.authority.checker.AuthorityChecker; import org.apache.shardingsphere.authority.rule.AuthorityRule; -import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions; import org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.DatabaseCreateExistsException; import org.apache.shardingsphere.proxy.backend.context.ProxyContext; import org.apache.shardingsphere.proxy.backend.handler.ProxyBackendHandler; @@ -49,8 +47,9 @@ public ResponseHeader execute() throws SQLException { check(sqlStatement); // SPEX ADDED: BEGIN AuthorityRule authorityRule = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class); - ShardingSpherePreconditions.checkState(new AuthorityChecker(authorityRule, connectionSession.getConnectionContext().getGrantee()).isAuthorized(sqlStatement.getDatabaseName()), - () -> new UnauthorizedDatabaseException(connectionSession.getConnectionContext().getGrantee(), sqlStatement.getDatabaseName())); + AuthorityChecker authorityChecker = new AuthorityChecker(authorityRule, connectionSession.getConnectionContext().getGrantee()); + authorityChecker.checkPrivileges(null, sqlStatement); + // SPEX ADDED: END ProxyContext.getInstance().getContextManager().getPersistServiceFacade().getMetaDataManagerPersistService().createDatabase(sqlStatement.getDatabaseName()); return new UpdateResponseHeader(sqlStatement); } diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandlerTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandlerTest.java index 5aa1945aad79ce..82d780d9ead369 100644 --- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandlerTest.java +++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/CreateDatabaseBackendHandlerTest.java @@ -19,13 +19,15 @@ import com.sphereex.dbplusengine.SphereEx; import com.sphereex.dbplusengine.SphereEx.Type; -import com.sphereex.dbplusengine.authority.exception.access.UnauthorizedDatabaseException; +import com.sphereex.dbplusengine.authority.exception.access.UnauthorizedOperationException; +import com.sphereex.dbplusengine.authority.provider.enterprise.privilege.EnterprisePermittedPrivileges; import org.apache.shardingsphere.authority.rule.AuthorityRule; import org.apache.shardingsphere.infra.config.props.temporary.TemporaryConfigurationProperties; import org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.DatabaseCreateExistsException; import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; import org.apache.shardingsphere.infra.metadata.user.Grantee; +import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser; import org.apache.shardingsphere.mode.manager.ContextManager; import org.apache.shardingsphere.mode.metadata.MetaDataContexts; import org.apache.shardingsphere.proxy.backend.context.ProxyContext; @@ -42,6 +44,7 @@ import java.sql.SQLException; import java.util.Collections; +import java.util.Optional; import java.util.Properties; import static org.hamcrest.CoreMatchers.instanceOf; @@ -100,11 +103,18 @@ void assertExecuteCreateExistDatabaseWithIfNotExists() throws SQLException { @SphereEx @Test void assertExecuteCreateNotAuthorizedDatabase() { - when(connectionSession.getConnectionContext().getGrantee()).thenReturn(new Grantee("foo", "")); + Grantee grantee = new Grantee("foo", ""); + when(connectionSession.getConnectionContext().getGrantee()).thenReturn(grantee); when(statement.getDatabaseName()).thenReturn("foo_db"); ContextManager contextManager = mockContextManager(); when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager); - assertThrows(UnauthorizedDatabaseException.class, () -> handler.execute()); + AuthorityRule authorityRule = mock(AuthorityRule.class, RETURNS_DEEP_STUBS); + RuleMetaData globalRuleMetaData = new RuleMetaData(Collections.singleton(authorityRule)); + when(contextManager.getMetaDataContexts().getMetaData().getGlobalRuleMetaData()).thenReturn(globalRuleMetaData); + ShardingSphereUser user = mock(ShardingSphereUser.class); + when(authorityRule.findUser(grantee)).thenReturn(Optional.of(user)); + when(authorityRule.findPrivileges(grantee)).thenReturn(Optional.of(mock(EnterprisePermittedPrivileges.class))); + assertThrows(UnauthorizedOperationException.class, () -> handler.execute()); } private ContextManager mockContextManager() { diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactoryTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactoryTest.java index c237b69a5c4d61..2e3bb9f2628211 100644 --- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactoryTest.java +++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactoryTest.java @@ -86,6 +86,7 @@ void setUp() { when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager); when(ProxyContext.getInstance().databaseExists("foo_db")).thenReturn(true); // SPEX ADDED: BEGIN + when(connectionSession.getConnectionContext().getGrantee()).thenReturn(null); when(contextManager.isMetaDataConsistent()).thenReturn(true); // SPEX ADDED: END } diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandlerTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandlerTest.java index ff24b8c44e2f21..f140cd0f98baa7 100644 --- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandlerTest.java +++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandlerTest.java @@ -18,8 +18,9 @@ package org.apache.shardingsphere.proxy.backend.handler.database; import org.apache.shardingsphere.authority.rule.AuthorityRule; -import org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.DatabaseDropNotExistsException; +import org.apache.shardingsphere.infra.config.props.temporary.TemporaryConfigurationProperties; import org.apache.shardingsphere.infra.database.core.type.DatabaseType; +import org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.DatabaseDropNotExistsException; import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase; import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData; import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader; @@ -44,6 +45,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; @@ -88,6 +90,9 @@ private ContextManager mockContextManager() { when(metaDataContexts.getMetaData().getDatabase("foo_db")).thenReturn(database); when(metaDataContexts.getMetaData().getDatabase("bar_db")).thenReturn(database); when(metaDataContexts.getMetaData().getDatabase("test_not_exist_db")).thenReturn(database); + // SPEX ADDED: BEGIN + when(metaDataContexts.getMetaData().getTemporaryProps()).thenReturn(new TemporaryConfigurationProperties(new Properties())); + // SPEX ADDED: END when(metaDataContexts.getMetaData().getGlobalRuleMetaData()).thenReturn(new RuleMetaData(Collections.singleton(mock(AuthorityRule.class)))); ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS); when(result.getMetaDataContexts()).thenReturn(metaDataContexts); diff --git a/proxy/backend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/ShowTablesExecutorTest.java b/proxy/backend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/ShowTablesExecutorTest.java index d6b0330bda60f2..1b1aecf39030b9 100644 --- a/proxy/backend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/ShowTablesExecutorTest.java +++ b/proxy/backend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/ShowTablesExecutorTest.java @@ -224,6 +224,9 @@ private Map getDatabases() { private ConnectionSession mockConnectionSession() { ConnectionSession result = mock(ConnectionSession.class, RETURNS_DEEP_STUBS); when(result.getUsedDatabaseName()).thenReturn(String.format(DATABASE_PATTERN, 0)); + // SPEX ADDED: BEGIN + when(result.getConnectionContext().getGrantee()).thenReturn(null); + // SPEX ADDED: END return result; } }