From 61851f50b22d7d19dfbc6af7811836c249174a64 Mon Sep 17 00:00:00 2001 From: RaigorJiang Date: Fri, 13 Dec 2024 10:44:44 +0800 Subject: [PATCH 1/2] Support ALL PRIVILEGES ON `DB`.* in MySQLDatabasePrivilegeChecker --- .../MySQLDatabasePrivilegeChecker.java | 3 +- .../MySQLDatabasePrivilegeCheckerTest.java | 56 +++++++++++++++++-- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabasePrivilegeChecker.java b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabasePrivilegeChecker.java index 61a2614637a00..2fdfe09656d01 100644 --- a/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabasePrivilegeChecker.java +++ b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabasePrivilegeChecker.java @@ -98,7 +98,8 @@ private String[][] getRequiredPrivileges(final Connection connection, final Priv } private String[][] getSelectRequiredPrivilege(final Connection connection) throws SQLException { - return new String[][]{{"ALL PRIVILEGES", "ON *.*"}, {"SELECT", "ON *.*"}, {"SELECT", String.format("ON `%s`.*", connection.getCatalog()).toUpperCase()}}; + String onCatalog = String.format("ON `%s`.*", connection.getCatalog().toUpperCase()); + return new String[][]{{"ALL PRIVILEGES", "ON *.*"}, {"SELECT", "ON *.*"}, {"ALL PRIVILEGES", onCatalog}, {"SELECT", onCatalog}}; } private boolean matchPrivileges(final String grantedPrivileges, final String[][] requiredPrivileges) { diff --git a/infra/database/type/mysql/src/test/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabasePrivilegeCheckerTest.java b/infra/database/type/mysql/src/test/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabasePrivilegeCheckerTest.java index 160223f5e5734..4da2b2dce5fab 100644 --- a/infra/database/type/mysql/src/test/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabasePrivilegeCheckerTest.java +++ b/infra/database/type/mysql/src/test/java/org/apache/shardingsphere/infra/database/mysql/checker/MySQLDatabasePrivilegeCheckerTest.java @@ -56,7 +56,7 @@ void setUp() throws SQLException { } @Test - void assertCheckPrivilegeWithParticularSuccess() throws SQLException { + void assertCheckPipelinePrivilegeWithParticularSuccess() throws SQLException { when(preparedStatement.executeQuery()).thenReturn(resultSet); when(resultSet.next()).thenReturn(true); when(resultSet.getString(1)).thenReturn("GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO '%'@'%'"); @@ -65,22 +65,22 @@ void assertCheckPrivilegeWithParticularSuccess() throws SQLException { } @Test - void assertCheckPrivilegeWithAllSuccess() throws SQLException { + void assertCheckPipelinePrivilegeWithAllSuccess() throws SQLException { when(preparedStatement.executeQuery()).thenReturn(resultSet); when(resultSet.next()).thenReturn(true); - when(resultSet.getString(1)).thenReturn("GRANT ALL PRIVILEGES CLIENT ON *.* TO '%'@'%'"); + when(resultSet.getString(1)).thenReturn("GRANT ALL PRIVILEGES ON *.* TO '%'@'%'"); new MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.PIPELINE); verify(preparedStatement).executeQuery(); } @Test - void assertCheckPrivilegeLackPrivileges() throws SQLException { + void assertCheckPipelinePrivilegeWithLackPrivileges() throws SQLException { when(preparedStatement.executeQuery()).thenReturn(resultSet); assertThrows(MissingRequiredPrivilegeException.class, () -> new MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.PIPELINE)); } @Test - void assertCheckPrivilegeFailure() throws SQLException { + void assertCheckPipelinePrivilegeFailure() throws SQLException { when(preparedStatement.executeQuery()).thenReturn(resultSet); when(resultSet.next()).thenThrow(new SQLException("")); assertThrows(CheckDatabaseEnvironmentFailedException.class, () -> new MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.PIPELINE)); @@ -127,4 +127,50 @@ void assertCheckXAPrivilegeFailureInMySQL8() throws SQLException { when(resultSet.next()).thenThrow(new SQLException("")); assertThrows(CheckDatabaseEnvironmentFailedException.class, () -> new MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.XA)); } + + @Test + void assertCheckSelectWithSelectPrivileges() throws SQLException { + when(dataSource.getConnection().getCatalog()).thenReturn("foo_db"); + when(preparedStatement.executeQuery()).thenReturn(resultSet); + when(resultSet.next()).thenReturn(true); + when(resultSet.getString(1)).thenReturn("GRANT SELECT ON *.* TO '%'@'%'"); + new MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.SELECT); + verify(preparedStatement).executeQuery(); + } + + @Test + void assertCheckSelectWithSelectOnDatabasePrivileges() throws SQLException { + when(dataSource.getConnection().getCatalog()).thenReturn("foo_db"); + when(preparedStatement.executeQuery()).thenReturn(resultSet); + when(resultSet.next()).thenReturn(true); + when(resultSet.getString(1)).thenReturn("GRANT SELECT ON `FOO_DB`.* TO '%'@'%'"); + new MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.SELECT); + verify(preparedStatement).executeQuery(); + } + + @Test + void assertCheckSelectWithAllPrivileges() throws SQLException { + when(dataSource.getConnection().getCatalog()).thenReturn("foo_db"); + when(preparedStatement.executeQuery()).thenReturn(resultSet); + when(resultSet.next()).thenReturn(true); + when(resultSet.getString(1)).thenReturn("GRANT ALL PRIVILEGES ON *.* TO '%'@'%'"); + new MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.SELECT); + verify(preparedStatement).executeQuery(); + } + + @Test + void assertCheckSelectWithAllPrivilegesOnDatabase() throws SQLException { + when(dataSource.getConnection().getCatalog()).thenReturn("foo_db"); + when(preparedStatement.executeQuery()).thenReturn(resultSet); + when(resultSet.next()).thenReturn(true); + when(resultSet.getString(1)).thenReturn("GRANT ALL PRIVILEGES ON `FOO_DB`.* TO '%'@'%'"); + new MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.SELECT); + verify(preparedStatement).executeQuery(); + } + + @Test + void assertCheckSelectWithLackPrivileges() throws SQLException { + when(preparedStatement.executeQuery()).thenReturn(resultSet); + assertThrows(MissingRequiredPrivilegeException.class, () -> new MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.SELECT)); + } } From 30c6652cae17adf3202bc8625462ce5dde969271 Mon Sep 17 00:00:00 2001 From: RaigorJiang Date: Fri, 13 Dec 2024 11:10:46 +0800 Subject: [PATCH 2/2] Update RELEASE-NOTES.md --- RELEASE-NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 6416bae3536d0..dcc167c950336 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -54,6 +54,7 @@ 1. Sharding: Fixes avg, sum, min, max function return empty data when no query result return - [#33449](https://github.com/apache/shardingsphere/pull/33449) 1. Encrypt: Fixes merge exception without encrypt rule in database - [#33708](https://github.com/apache/shardingsphere/pull/33708) 1. SQL Binder: Fixes the expression segment cannot find the outer table when binding - [#34015](https://github.com/apache/shardingsphere/pull/34015) +1. Proxy: Fixes "ALL PRIVILEGES ON `DB`.*" is not recognized during SELECT privilege verification for MySQL - [#34037](https://github.com/apache/shardingsphere/pull/34037) ### Change Logs