This is an automated email from the ASF dual-hosted git repository.
terrymanu 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 05c87d6bbf7 Fix stale encryptors leaking when altering an encrypt rule
(#39209)
05c87d6bbf7 is described below
commit 05c87d6bbf708f92438ee7d0a9333698e314a86c
Author: Eunbin Son <[email protected]>
AuthorDate: Tue Sep 8 19:16:06 2026 +0900
Fix stale encryptors leaking when altering an encrypt rule (#39209)
* Fix stale encryptors leaking when altering an encrypt rule
* Match altered encrypt table names case-insensitively when building
dropped rules
EncryptRule keys its tables through CaseInsensitiveMap and ALTER validation
uses that key set, but buildToBeDroppedRuleConfiguration excluded replaced
tables with a case-sensitive list. Altering T_ENCRYPT for a persisted
t_encrypt therefore kept the old definition alongside the new one, so
UnusedAlgorithmFinder still saw the assisted and like encryptors as
referenced and dropped none of them.
---
RELEASE-NOTES.md | 1 +
.../handler/update/AlterEncryptRuleExecutor.java | 8 ++-
.../update/AlterEncryptRuleExecutorTest.java | 65 ++++++++++++++++++++++
3 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 9d27775493f..7b429a9443d 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -83,6 +83,7 @@
1. Readwrite-splitting: Evaluate inline expressions in data source names of
rule configuration checker -
[#39374](https://github.com/apache/shardingsphere/pull/39374)
1. SQL Federation: Fix SQL Federation pagination binding for long LIMIT
parameters - [#39237](https://github.com/apache/shardingsphere/pull/39237)
1. Broadcast: Fix case-sensitive table name lookup in broadcast data node rule
attribute - [#39153](https://github.com/apache/shardingsphere/pull/39153)
+1. Encrypt: Fix stale encryptors leaking when altering an encrypt rule -
[#39209](https://github.com/apache/shardingsphere/pull/39209)
### Enhancements
diff --git
a/features/encrypt/distsql/handler/src/main/java/org/apache/shardingsphere/encrypt/distsql/handler/update/AlterEncryptRuleExecutor.java
b/features/encrypt/distsql/handler/src/main/java/org/apache/shardingsphere/encrypt/distsql/handler/update/AlterEncryptRuleExecutor.java
index 6d51c66181c..affd48c5199 100644
---
a/features/encrypt/distsql/handler/src/main/java/org/apache/shardingsphere/encrypt/distsql/handler/update/AlterEncryptRuleExecutor.java
+++
b/features/encrypt/distsql/handler/src/main/java/org/apache/shardingsphere/encrypt/distsql/handler/update/AlterEncryptRuleExecutor.java
@@ -17,11 +17,13 @@
package org.apache.shardingsphere.encrypt.distsql.handler.update;
+import com.cedarsoftware.util.CaseInsensitiveSet;
import lombok.Setter;
import
org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.database.type.DatabaseRuleAlterExecutor;
import
org.apache.shardingsphere.distsql.handler.required.DistSQLExecutorCurrentRuleRequired;
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
import org.apache.shardingsphere.encrypt.config.EncryptRuleConfiguration;
+import
org.apache.shardingsphere.encrypt.config.rule.EncryptTableRuleConfiguration;
import
org.apache.shardingsphere.encrypt.distsql.handler.converter.EncryptRuleStatementConverter;
import org.apache.shardingsphere.encrypt.distsql.segment.EncryptRuleSegment;
import
org.apache.shardingsphere.encrypt.distsql.statement.AlterEncryptRuleStatement;
@@ -102,7 +104,11 @@ public final class AlterEncryptRuleExecutor implements
DatabaseRuleAlterExecutor
@Override
public EncryptRuleConfiguration buildToBeDroppedRuleConfiguration(final
EncryptRuleConfiguration toBeAlteredRuleConfig) {
- Collection<String> unusedEncryptor =
UnusedAlgorithmFinder.findUnusedEncryptor(rule.getConfiguration());
+ Collection<String> toBeAlteredTableNames = new
CaseInsensitiveSet<>(toBeAlteredRuleConfig.getTables().stream().map(EncryptTableRuleConfiguration::getName).collect(Collectors.toList()));
+ Collection<EncryptTableRuleConfiguration> tables =
rule.getConfiguration().getTables().stream().filter(each ->
!toBeAlteredTableNames.contains(each.getName())).collect(Collectors.toList());
+ tables.addAll(toBeAlteredRuleConfig.getTables());
+ EncryptRuleConfiguration toBeCheckedRuleConfig = new
EncryptRuleConfiguration(tables, rule.getConfiguration().getEncryptors());
+ Collection<String> unusedEncryptor =
UnusedAlgorithmFinder.findUnusedEncryptor(toBeCheckedRuleConfig);
Map<String, AlgorithmConfiguration> toBeDroppedEncryptors = new
HashMap<>(unusedEncryptor.size(), 1F);
unusedEncryptor.forEach(each -> toBeDroppedEncryptors.put(each,
rule.getConfiguration().getEncryptors().get(each)));
return new EncryptRuleConfiguration(Collections.emptyList(),
toBeDroppedEncryptors);
diff --git
a/features/encrypt/distsql/handler/src/test/java/org/apache/shardingsphere/encrypt/distsql/handler/update/AlterEncryptRuleExecutorTest.java
b/features/encrypt/distsql/handler/src/test/java/org/apache/shardingsphere/encrypt/distsql/handler/update/AlterEncryptRuleExecutorTest.java
index a6ac6fb2068..893f5a5c4a4 100644
---
a/features/encrypt/distsql/handler/src/test/java/org/apache/shardingsphere/encrypt/distsql/handler/update/AlterEncryptRuleExecutorTest.java
+++
b/features/encrypt/distsql/handler/src/test/java/org/apache/shardingsphere/encrypt/distsql/handler/update/AlterEncryptRuleExecutorTest.java
@@ -21,12 +21,15 @@ import
org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecuteEngine;
import org.apache.shardingsphere.distsql.segment.AlgorithmSegment;
import org.apache.shardingsphere.encrypt.config.EncryptRuleConfiguration;
+import
org.apache.shardingsphere.encrypt.config.rule.EncryptColumnItemRuleConfiguration;
+import
org.apache.shardingsphere.encrypt.config.rule.EncryptColumnRuleConfiguration;
import
org.apache.shardingsphere.encrypt.config.rule.EncryptTableRuleConfiguration;
import
org.apache.shardingsphere.encrypt.distsql.segment.EncryptColumnItemSegment;
import org.apache.shardingsphere.encrypt.distsql.segment.EncryptColumnSegment;
import org.apache.shardingsphere.encrypt.distsql.segment.EncryptRuleSegment;
import
org.apache.shardingsphere.encrypt.distsql.statement.AlterEncryptRuleStatement;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
+import
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
import
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.InvalidRuleConfigurationException;
import
org.apache.shardingsphere.infra.exception.kernel.metadata.rule.MissingRequiredRuleException;
@@ -39,7 +42,9 @@ import org.junit.jupiter.api.Test;
import java.sql.SQLException;
import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedList;
+import java.util.Map;
import java.util.Properties;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -111,6 +116,54 @@ class AlterEncryptRuleExecutorTest {
assertDoesNotThrow(() ->
metaDataManagerPersistService.alterRuleConfiguration(any(),
argThat(this::assertToBeAlteredRuleConfiguration)));
}
+ @Test
+ void
assertBuildToBeDroppedRuleConfigurationWhenAssistedAndLikeQueriesRemoved() {
+ EncryptRule rule = mock(EncryptRule.class);
+
when(rule.getConfiguration()).thenReturn(createCurrentRuleConfigurationWithGeneratedEncryptors());
+ AlterEncryptRuleExecutor executor = new AlterEncryptRuleExecutor();
+ executor.setRule(rule);
+ EncryptColumnRuleConfiguration alteredColumn = new
EncryptColumnRuleConfiguration("user_id", new
EncryptColumnItemRuleConfiguration("user_cipher", "foo_cipher"));
+ EncryptRuleConfiguration toBeAlteredRuleConfig = new
EncryptRuleConfiguration(
+ Collections.singleton(new
EncryptTableRuleConfiguration("t_encrypt",
Collections.singleton(alteredColumn))), Collections.emptyMap());
+ EncryptRuleConfiguration actual =
executor.buildToBeDroppedRuleConfiguration(toBeAlteredRuleConfig);
+ assertTrue(actual.getTables().isEmpty());
+ assertThat(actual.getEncryptors().size(), is(2));
+ assertTrue(actual.getEncryptors().containsKey("foo_assisted"));
+ assertTrue(actual.getEncryptors().containsKey("foo_like"));
+ }
+
+ @Test
+ void
assertBuildToBeDroppedRuleConfigurationWhenAlteredTableNameCaseDiffers() {
+ EncryptRule rule = mock(EncryptRule.class);
+
when(rule.getConfiguration()).thenReturn(createCurrentRuleConfigurationWithGeneratedEncryptors());
+ AlterEncryptRuleExecutor executor = new AlterEncryptRuleExecutor();
+ executor.setRule(rule);
+ EncryptColumnRuleConfiguration alteredColumn = new
EncryptColumnRuleConfiguration("user_id", new
EncryptColumnItemRuleConfiguration("user_cipher", "foo_cipher"));
+ EncryptRuleConfiguration toBeAlteredRuleConfig = new
EncryptRuleConfiguration(
+ Collections.singleton(new
EncryptTableRuleConfiguration("T_ENCRYPT",
Collections.singleton(alteredColumn))), Collections.emptyMap());
+ EncryptRuleConfiguration actual =
executor.buildToBeDroppedRuleConfiguration(toBeAlteredRuleConfig);
+ assertTrue(actual.getTables().isEmpty());
+ assertThat(actual.getEncryptors().size(), is(2));
+ assertTrue(actual.getEncryptors().containsKey("foo_assisted"));
+ assertTrue(actual.getEncryptors().containsKey("foo_like"));
+ }
+
+ @Test
+ void
assertBuildToBeDroppedRuleConfigurationWhenColumnDefinitionUnchanged() {
+ EncryptRule rule = mock(EncryptRule.class);
+
when(rule.getConfiguration()).thenReturn(createCurrentRuleConfigurationWithGeneratedEncryptors());
+ AlterEncryptRuleExecutor executor = new AlterEncryptRuleExecutor();
+ executor.setRule(rule);
+ EncryptColumnRuleConfiguration alteredColumn = new
EncryptColumnRuleConfiguration("user_id", new
EncryptColumnItemRuleConfiguration("user_cipher", "foo_cipher"));
+ alteredColumn.setAssistedQuery(new
EncryptColumnItemRuleConfiguration("user_assisted", "foo_assisted"));
+ alteredColumn.setLikeQuery(new
EncryptColumnItemRuleConfiguration("user_like", "foo_like"));
+ EncryptRuleConfiguration toBeAlteredRuleConfig = new
EncryptRuleConfiguration(
+ Collections.singleton(new
EncryptTableRuleConfiguration("t_encrypt",
Collections.singleton(alteredColumn))), Collections.emptyMap());
+ EncryptRuleConfiguration actual =
executor.buildToBeDroppedRuleConfiguration(toBeAlteredRuleConfig);
+ assertTrue(actual.getTables().isEmpty());
+ assertTrue(actual.getEncryptors().isEmpty());
+ }
+
private ContextManager mockContextManager(final EncryptRule rule) {
DatabaseType databaseType = mock(DatabaseType.class);
ResourceMetaData resourceMetaData = mock(ResourceMetaData.class);
@@ -142,6 +195,18 @@ class AlterEncryptRuleExecutorTest {
return new EncryptRuleConfiguration(new
LinkedList<>(Collections.singleton(tableRuleConfig)), Collections.emptyMap());
}
+ private EncryptRuleConfiguration
createCurrentRuleConfigurationWithGeneratedEncryptors() {
+ EncryptColumnRuleConfiguration columnRuleConfig = new
EncryptColumnRuleConfiguration("user_id", new
EncryptColumnItemRuleConfiguration("user_cipher", "foo_cipher"));
+ columnRuleConfig.setAssistedQuery(new
EncryptColumnItemRuleConfiguration("user_assisted", "foo_assisted"));
+ columnRuleConfig.setLikeQuery(new
EncryptColumnItemRuleConfiguration("user_like", "foo_like"));
+ Map<String, AlgorithmConfiguration> encryptors = new HashMap<>(3, 1F);
+ encryptors.put("foo_cipher", new AlgorithmConfiguration("MD5", new
Properties()));
+ encryptors.put("foo_assisted", new AlgorithmConfiguration("MD5", new
Properties()));
+ encryptors.put("foo_like", new AlgorithmConfiguration("MD5", new
Properties()));
+ EncryptTableRuleConfiguration tableRuleConfig = new
EncryptTableRuleConfiguration("t_encrypt",
Collections.singleton(columnRuleConfig));
+ return new EncryptRuleConfiguration(new
LinkedList<>(Collections.singleton(tableRuleConfig)), encryptors);
+ }
+
private boolean assertToBeDroppedRuleConfiguration(final
EncryptRuleConfiguration actual) {
assertTrue(actual.getTables().isEmpty());
assertTrue(actual.getEncryptors().isEmpty());