You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by to...@apache.org on 2023/01/30 01:04:04 UTC
[shardingsphere] branch master updated: Add UnauthorizedOperationException to decouple audit exception and authority exception (#23814)
This is an automated email from the ASF dual-hosted git repository.
totalo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 025966c078c Add UnauthorizedOperationException to decouple audit exception and authority exception (#23814)
025966c078c is described below
commit 025966c078c0d4e231da4eb6cdba57e4d47786bb
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Mon Jan 30 09:03:57 2023 +0800
Add UnauthorizedOperationException to decouple audit exception and authority exception (#23814)
* Add UnauthorizedOperationException to decouple audit exception and authority exception
* Add UnauthorizedOperationException to decouple audit exception and authority exception
* Add UnauthorizedOperationException to decouple audit exception and authority exception
* Refactor AuthorityChecker
* Refactor AuthorityChecker
---
.../user-manual/error-code/sql-error-code.cn.md | 9 ++++-
.../user-manual/error-code/sql-error-code.en.md | 6 +++
.../hint/SQLHintDataSourceNotExistsException.java | 2 +-
.../authority/checker/AuthorityChecker.java | 46 +++++++++++-----------
.../exception/UnauthorizedOperationException.java | 12 +++---
.../authority/checker/AuthorityCheckerTest.java | 14 +++----
.../handler/ProxyBackendHandlerFactory.java | 2 +-
.../authentication/MySQLAuthenticationHandler.java | 2 +-
.../OpenGaussAuthenticationHandler.java | 2 +-
.../PostgreSQLAuthenticationHandler.java | 2 +-
.../DefaultPipelineDataSourceManagerTest.java | 2 -
11 files changed, 53 insertions(+), 46 deletions(-)
diff --git a/docs/document/content/user-manual/error-code/sql-error-code.cn.md b/docs/document/content/user-manual/error-code/sql-error-code.cn.md
index 626354b7f7e..cdb54cda0ce 100644
--- a/docs/document/content/user-manual/error-code/sql-error-code.cn.md
+++ b/docs/document/content/user-manual/error-code/sql-error-code.cn.md
@@ -82,7 +82,13 @@ SQL 错误码以标准的 SQL State,Vendor Code 和详细错误信息提供,
| SQL State | Vendor Code | 错误信息 |
| --------- | ----------- | ------ |
| 44000 | 16000 | SQL audit failed, error message: %s. |
-| 44000 | 16001 | Hint datasource: %s is not exist. |
+| 44000 | 16001 | Hint data source: %s is not exist. |
+
+### 权限
+
+| SQL State | Vendor Code | 错误信息 |
+| --------- | ----------- | ------ |
+| 44000 | 16500 | Access denied for operation `%s`. |
### 集群
@@ -229,7 +235,6 @@ SQL 错误码以标准的 SQL State,Vendor Code 和详细错误信息提供,
| 44000 | 20383 | Group name in MGR is not same with configured one \`%s\` in database \`%s\`. |
| 42S01 | 20390 | MySQL Duplicate primary data source in database \`%s\`. |
-
### SQL 方言转换
| SQL State | Vendor Code | 错误信息 |
diff --git a/docs/document/content/user-manual/error-code/sql-error-code.en.md b/docs/document/content/user-manual/error-code/sql-error-code.en.md
index 3c174ed241c..f8b13c497a1 100644
--- a/docs/document/content/user-manual/error-code/sql-error-code.en.md
+++ b/docs/document/content/user-manual/error-code/sql-error-code.en.md
@@ -84,6 +84,12 @@ SQL error codes provide by standard `SQL State`, `Vendor Code` and `Reason`, whi
| 44000 | 16000 | SQL audit failed, error message: %s. |
| 44000 | 16001 | Hint datasource: %s is not exist. |
+### Authority
+
+| SQL State | Vendor Code | Reason |
+| --------- | ----------- | ------ |
+| 44000 | 16500 | Access denied for operation `%s`. |
+
### Cluster
| SQL State | Vendor Code | Reason |
diff --git a/infra/common/src/main/java/org/apache/shardingsphere/infra/hint/SQLHintDataSourceNotExistsException.java b/infra/common/src/main/java/org/apache/shardingsphere/infra/hint/SQLHintDataSourceNotExistsException.java
index e463d6aa3ea..6a2f9b0f0c0 100644
--- a/infra/common/src/main/java/org/apache/shardingsphere/infra/hint/SQLHintDataSourceNotExistsException.java
+++ b/infra/common/src/main/java/org/apache/shardingsphere/infra/hint/SQLHintDataSourceNotExistsException.java
@@ -30,6 +30,6 @@ public final class SQLHintDataSourceNotExistsException extends KernelSQLExceptio
private static final int KERNEL_CODE = 6;
public SQLHintDataSourceNotExistsException(final String errorMessage) {
- super(XOpenSQLState.CHECK_OPTION_VIOLATION, KERNEL_CODE, 1, "Hint datasource: %s is not exist.", errorMessage);
+ super(XOpenSQLState.CHECK_OPTION_VIOLATION, KERNEL_CODE, 1, "Hint data source: %s is not exist.", errorMessage);
}
}
diff --git a/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/checker/AuthorityChecker.java b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/checker/AuthorityChecker.java
index c1ce6a4dc9e..81e743d5218 100644
--- a/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/checker/AuthorityChecker.java
+++ b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/checker/AuthorityChecker.java
@@ -18,12 +18,11 @@
package org.apache.shardingsphere.authority.checker;
import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.authority.exception.UnauthorizedOperationException;
import org.apache.shardingsphere.authority.model.PrivilegeType;
import org.apache.shardingsphere.authority.model.ShardingSpherePrivileges;
import org.apache.shardingsphere.authority.rule.AuthorityRule;
-import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
-import org.apache.shardingsphere.infra.executor.audit.exception.SQLAuditException;
-import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.dialect.exception.syntax.database.UnknownDatabaseException;
import org.apache.shardingsphere.infra.metadata.user.Grantee;
import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
@@ -58,43 +57,42 @@ public final class AuthorityChecker {
private final Grantee grantee;
/**
- * Check database authority.
- *
- * @param databaseName database name
- * @return authorized or not
+ * Check Authentication with cipher.
+ *
+ * @param validator validator
+ * @param cipher cipher
+ * @return authenticated or not
*/
- public boolean isAuthorized(final String databaseName) {
- return null == grantee || rule.findPrivileges(grantee).map(optional -> optional.hasPrivileges(databaseName)).orElse(false);
+ public boolean isAuthenticated(final BiPredicate<Object, Object> validator, final Object cipher) {
+ return rule.findUser(grantee).filter(optional -> validator.test(optional, cipher)).isPresent();
}
/**
- * Check authority with cipher.
+ * Check database authority.
*
- * @param validator validator
- * @param cipher cipher
+ * @param databaseName database name
* @return authorized or not
*/
- public boolean isAuthorized(final BiPredicate<Object, Object> validator, final Object cipher) {
- return rule.findUser(grantee).filter(optional -> validator.test(optional, cipher)).isPresent();
+ public boolean isAuthorized(final String databaseName) {
+ return null == grantee || rule.findPrivileges(grantee).map(optional -> optional.hasPrivileges(databaseName)).orElse(false);
}
/**
- * Check SQL authority.
+ * Check privileges.
*
- * @param sqlStatementContext SQL statement context
- * @param database current database
+ * @param databaseName database name
+ * @param sqlStatement SQL statement
*/
- public void isAuthorized(final SQLStatementContext<?> sqlStatementContext, final ShardingSphereDatabase database) {
+ public void checkPrivileges(final String databaseName, final SQLStatement sqlStatement) {
if (null == grantee) {
return;
}
Optional<ShardingSpherePrivileges> privileges = rule.findPrivileges(grantee);
- ShardingSpherePreconditions.checkState(privileges.isPresent(), () -> new SQLAuditException(String.format("Access denied for user '%s'@'%s'", grantee.getUsername(), grantee.getHostname())));
- ShardingSpherePreconditions.checkState(null == database || privileges.filter(optional -> optional.hasPrivileges(database.getName())).isPresent(),
- () -> new SQLAuditException(String.format("Unknown database '%s'", null == database ? null : database.getName())));
- PrivilegeType privilegeType = getPrivilege(sqlStatementContext.getSqlStatement());
- boolean hasPrivileges = privileges.get().hasPrivileges(Collections.singleton(privilegeType));
- ShardingSpherePreconditions.checkState(hasPrivileges, () -> new SQLAuditException(String.format("Access denied for operation %s", null == privilegeType ? "" : privilegeType.name())));
+ ShardingSpherePreconditions.checkState(null == databaseName || privileges.filter(optional -> optional.hasPrivileges(databaseName)).isPresent(),
+ () -> new UnknownDatabaseException(databaseName));
+ PrivilegeType privilegeType = getPrivilege(sqlStatement);
+ ShardingSpherePreconditions.checkState(privileges.isPresent() && privileges.get().hasPrivileges(Collections.singleton(privilegeType)),
+ () -> new UnauthorizedOperationException(null == privilegeType ? "" : privilegeType.name()));
}
private PrivilegeType getPrivilege(final SQLStatement sqlStatement) {
diff --git a/infra/common/src/main/java/org/apache/shardingsphere/infra/hint/SQLHintDataSourceNotExistsException.java b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/exception/UnauthorizedOperationException.java
similarity index 74%
copy from infra/common/src/main/java/org/apache/shardingsphere/infra/hint/SQLHintDataSourceNotExistsException.java
copy to kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/exception/UnauthorizedOperationException.java
index e463d6aa3ea..2d4ba47e8ee 100644
--- a/infra/common/src/main/java/org/apache/shardingsphere/infra/hint/SQLHintDataSourceNotExistsException.java
+++ b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/exception/UnauthorizedOperationException.java
@@ -15,21 +15,21 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.infra.hint;
+package org.apache.shardingsphere.authority.exception;
import org.apache.shardingsphere.infra.util.exception.external.sql.sqlstate.XOpenSQLState;
import org.apache.shardingsphere.infra.util.exception.external.sql.type.kernel.KernelSQLException;
/**
- * SQL Hint data source not exists exception.
+ * Unauthorized operation exception.
*/
-public final class SQLHintDataSourceNotExistsException extends KernelSQLException {
+public final class UnauthorizedOperationException extends KernelSQLException {
- private static final long serialVersionUID = -8222967059220727514L;
+ private static final long serialVersionUID = -182093939317068572L;
private static final int KERNEL_CODE = 6;
- public SQLHintDataSourceNotExistsException(final String errorMessage) {
- super(XOpenSQLState.CHECK_OPTION_VIOLATION, KERNEL_CODE, 1, "Hint datasource: %s is not exist.", errorMessage);
+ public UnauthorizedOperationException(final String operation) {
+ super(XOpenSQLState.CHECK_OPTION_VIOLATION, KERNEL_CODE, 500, "Access denied for operation `%s`.", operation);
}
}
diff --git a/kernel/authority/core/src/test/java/org/apache/shardingsphere/authority/checker/AuthorityCheckerTest.java b/kernel/authority/core/src/test/java/org/apache/shardingsphere/authority/checker/AuthorityCheckerTest.java
index f469f758ca0..30920cce4a1 100644
--- a/kernel/authority/core/src/test/java/org/apache/shardingsphere/authority/checker/AuthorityCheckerTest.java
+++ b/kernel/authority/core/src/test/java/org/apache/shardingsphere/authority/checker/AuthorityCheckerTest.java
@@ -19,12 +19,12 @@ package org.apache.shardingsphere.authority.checker;
import org.apache.shardingsphere.authority.config.AuthorityRuleConfiguration;
import org.apache.shardingsphere.authority.rule.AuthorityRule;
-import org.apache.shardingsphere.infra.binder.statement.ddl.CreateTableStatementContext;
-import org.apache.shardingsphere.infra.binder.statement.dml.InsertStatementContext;
-import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
import org.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration;
import org.apache.shardingsphere.infra.metadata.user.Grantee;
import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateTableStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
import org.junit.Test;
import java.util.Collection;
@@ -44,12 +44,12 @@ public final class AuthorityCheckerTest {
}
@Test
- public void assertCheck() {
+ public void assertCheckPrivileges() {
Collection<ShardingSphereUser> users = Collections.singleton(new ShardingSphereUser("root", "", "localhost"));
AuthorityRule rule = new AuthorityRule(new AuthorityRuleConfiguration(users, new AlgorithmConfiguration("ALL_PERMITTED", new Properties())), Collections.emptyMap());
AuthorityChecker authorityChecker = new AuthorityChecker(rule, new Grantee("root", "localhost"));
- authorityChecker.isAuthorized(mock(SelectStatementContext.class), null);
- authorityChecker.isAuthorized(mock(InsertStatementContext.class), null);
- authorityChecker.isAuthorized(mock(CreateTableStatementContext.class), null);
+ authorityChecker.checkPrivileges(null, mock(SelectStatement.class));
+ authorityChecker.checkPrivileges(null, mock(InsertStatement.class));
+ authorityChecker.checkPrivileges(null, mock(CreateTableStatement.class));
}
}
diff --git a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
index 6e233082981..50c00200b27 100644
--- a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
+++ b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
@@ -162,7 +162,7 @@ public final class ProxyBackendHandlerFactory {
: connectionSession.getDatabaseName();
AuthorityRule authorityRule = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
ShardingSphereDatabase database = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getDatabase(databaseName);
- new AuthorityChecker(authorityRule, connectionSession.getGrantee()).isAuthorized(sqlStatementContext, database);
+ new AuthorityChecker(authorityRule, connectionSession.getGrantee()).checkPrivileges(databaseName, sqlStatementContext.getSqlStatement());
SQLAuditEngine.audit(sqlStatementContext, queryContext.getParameters(),
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData(), database, connectionSession.getGrantee());
backendHandler = DatabaseAdminBackendHandlerFactory.newInstance(databaseType, sqlStatementContext, connectionSession);
diff --git a/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandler.java b/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandler.java
index 1de8b70caf0..f94554f8fa5 100644
--- a/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandler.java
+++ b/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandler.java
@@ -52,7 +52,7 @@ public final class MySQLAuthenticationHandler {
Grantee grantee = new Grantee(username, hostname);
AuthorityChecker authorityChecker = new AuthorityChecker(authorityRule, grantee);
MySQLAuthenticator authenticator = getAuthenticator(username, hostname);
- if (!authorityChecker.isAuthorized((a, b) -> authenticator.authenticate((ShardingSphereUser) a, (byte[]) b), authenticationResponse)) {
+ if (!authorityChecker.isAuthenticated((a, b) -> authenticator.authenticate((ShardingSphereUser) a, (byte[]) b), authenticationResponse)) {
return Optional.of(MySQLVendorError.ER_ACCESS_DENIED_ERROR);
}
return null == databaseName || authorityChecker.isAuthorized(databaseName) ? Optional.empty() : Optional.of(MySQLVendorError.ER_DBACCESS_DENIED_ERROR);
diff --git a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
index aab6c3e7c1d..13168188502 100644
--- a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
+++ b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
@@ -109,7 +109,7 @@ public final class OpenGaussAuthenticationHandler {
Grantee grantee = new Grantee(username, "%");
ShardingSpherePreconditions.checkState(authorityRule.findUser(grantee).isPresent(), () -> new UnknownUsernameException(username));
AuthorityChecker authorityChecker = new AuthorityChecker(authorityRule, grantee);
- if (!authorityChecker.isAuthorized((a, b) -> isPasswordRight((ShardingSphereUser) a, (Object[]) b), new Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration})) {
+ if (!authorityChecker.isAuthenticated((a, b) -> isPasswordRight((ShardingSphereUser) a, (Object[]) b), new Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration})) {
throw new InvalidPasswordException(username);
}
ShardingSpherePreconditions.checkState(null == databaseName || authorityChecker.isAuthorized(databaseName), () -> new PrivilegeNotGrantedException(username, databaseName));
diff --git a/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandler.java b/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandler.java
index 0ee28f33326..333ef2f02e2 100644
--- a/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandler.java
+++ b/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandler.java
@@ -52,7 +52,7 @@ public final class PostgreSQLAuthenticationHandler {
ShardingSpherePreconditions.checkState(authorityRule.findUser(grantee).isPresent(), () -> new UnknownUsernameException(username));
AuthorityChecker authorityChecker = new AuthorityChecker(authorityRule, grantee);
PostgreSQLAuthenticator authenticator = getAuthenticator(username, grantee.getHostname());
- if (!authorityChecker.isAuthorized((a, b) -> authenticator.authenticate((ShardingSphereUser) a, (Object[]) b), new Object[]{passwordMessagePacket.getDigest(), md5Salt})) {
+ if (!authorityChecker.isAuthenticated((a, b) -> authenticator.authenticate((ShardingSphereUser) a, (Object[]) b), new Object[]{passwordMessagePacket.getDigest(), md5Salt})) {
throw new InvalidPasswordException(username);
}
ShardingSpherePreconditions.checkState(null == databaseName || authorityChecker.isAuthorized(databaseName), () -> new PrivilegeNotGrantedException(username, databaseName));
diff --git a/test/it/pipeline/src/test/java/org/apache/shardingsphere/test/it/data/pipeline/core/datasource/DefaultPipelineDataSourceManagerTest.java b/test/it/pipeline/src/test/java/org/apache/shardingsphere/test/it/data/pipeline/core/datasource/DefaultPipelineDataSourceManagerTest.java
index 2a3393f6c28..e078e1ab3db 100644
--- a/test/it/pipeline/src/test/java/org/apache/shardingsphere/test/it/data/pipeline/core/datasource/DefaultPipelineDataSourceManagerTest.java
+++ b/test/it/pipeline/src/test/java/org/apache/shardingsphere/test/it/data/pipeline/core/datasource/DefaultPipelineDataSourceManagerTest.java
@@ -35,7 +35,6 @@ import java.util.Map;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public final class DefaultPipelineDataSourceManagerTest {
@@ -67,7 +66,6 @@ public final class DefaultPipelineDataSourceManagerTest {
dataSourceManager.getDataSource(PipelineDataSourceConfigurationFactory.newInstance(jobConfig.getSource().getType(), jobConfig.getSource().getParameter()));
dataSourceManager.getDataSource(PipelineDataSourceConfigurationFactory.newInstance(jobConfig.getTarget().getType(), jobConfig.getTarget().getParameter()));
Map<?, ?> cachedDataSources = (Map<?, ?>) Plugins.getMemberAccessor().get(DefaultPipelineDataSourceManager.class.getDeclaredField("cachedDataSources"), dataSourceManager);
- assertNotNull(cachedDataSources);
assertThat(cachedDataSources.size(), is(2));
dataSourceManager.close();
assertTrue(cachedDataSources.isEmpty());