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 <[email protected]>
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());