diff --git a/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/controller/DatabaseController.java b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/controller/DatabaseController.java index bfa0fd5abd..4cca690d37 100644 --- a/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/controller/DatabaseController.java +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/controller/DatabaseController.java @@ -16,9 +16,12 @@ package com.huaweicloud.sermant.database.controller; +import com.huaweicloud.sermant.core.common.LoggerFactory; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import java.sql.SQLException; +import java.util.logging.Level; +import java.util.logging.Logger; /** * 数据库控制器 @@ -27,6 +30,8 @@ * @since 2024-01-15 **/ public class DatabaseController { + private static final Logger LOGGER = LoggerFactory.getLogger(); + private static Object result = new Object(); private DatabaseController() { @@ -42,5 +47,6 @@ private DatabaseController() { public static void disableDatabaseWriteOperation(String database, ExecuteContext context) { context.setThrowableOut(new SQLException("Database prohibit to write, database: " + database)); context.skip(result); + LOGGER.log(Level.FINE, "Database prohibit to write, database: {0}", database); } } diff --git a/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/entity/DatabaseInfo.java b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/entity/DatabaseInfo.java new file mode 100644 index 0000000000..5162a8533e --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/entity/DatabaseInfo.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.database.entity; + +/** + * 数据库示例信息 + * + * @author daizhenyu + * @since 2024-02-01 + **/ +public class DatabaseInfo { + private String databaseName; + + private String hostAddress; + + private int port; + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getDatabaseName() { + return databaseName; + } + + public void setDatabaseName(String databaseName) { + this.databaseName = databaseName; + } + + public String getHostAddress() { + return hostAddress; + } + + public void setHostAddress(String hostAddress) { + this.hostAddress = hostAddress; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/interceptor/AbstractDatabaseInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/interceptor/AbstractDatabaseInterceptor.java index dc03e3ca41..35d05fa649 100644 --- a/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/interceptor/AbstractDatabaseInterceptor.java +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/interceptor/AbstractDatabaseInterceptor.java @@ -21,16 +21,25 @@ import com.huaweicloud.sermant.database.handler.DatabaseHandler; /** - * mongodb抽象interceptor + * 数据库抽象interceptor * * @author daizhenyu * @since 2024-01-22 **/ public abstract class AbstractDatabaseInterceptor extends AbstractInterceptor { + /** + * 数据库信息存储的key + */ + protected static final String DATABASE_INFO = "databaseInfo"; + + /** + * 自定义数据库处理handle + */ protected DatabaseHandler handler; @Override public ExecuteContext before(ExecuteContext context) throws Exception { + createAndCacheDatabaseInfo(context); if (handler != null) { handler.doBefore(context); return context; @@ -63,4 +72,11 @@ public ExecuteContext onThrow(ExecuteContext context) throws Exception { * @return ExecuteContext 上下文 */ protected abstract ExecuteContext doBefore(ExecuteContext context); + + /** + * 创建数据库实例对象并缓存在上下文的本地局部属性集中 + * + * @param context 上下文 + */ + protected abstract void createAndCacheDatabaseInfo(ExecuteContext context); } diff --git a/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/utils/SqlParserUtils.java b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/utils/SqlParserUtils.java new file mode 100644 index 0000000000..6c99a5bf66 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/utils/SqlParserUtils.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.database.utils; + +import com.huaweicloud.sermant.core.utils.StringUtils; + +import java.util.regex.Pattern; + +/** + * sql解析工具类 + * + * @author daizhenyu + * @since 2024-01-25 + **/ +public class SqlParserUtils { + private static Pattern writePattern = + Pattern.compile("INSERT\\b|UPDATE\\b|DELETE\\b|CREATE\\b|ALTER\\b|DROP\\b|TRUNCATE\\b", + Pattern.CASE_INSENSITIVE); + + private SqlParserUtils() { + } + + /** + * 解析sql并判断是否为写操作 + * + * @param sql sql语句 + * @return 是否为写操作 + */ + public static boolean isWriteOperation(String sql) { + if (StringUtils.isEmpty(sql)) { + return false; + } + return writePattern.matcher(sql).find(); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/AbstractMongoDbInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/AbstractMongoDbInterceptor.java new file mode 100644 index 0000000000..c1b268b6c8 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/AbstractMongoDbInterceptor.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mongodb.interceptors; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; +import com.huaweicloud.sermant.database.controller.DatabaseController; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; +import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor; + +/** + * mongodb抽象interceptor + * + * @author daizhenyu + * @since 2024-02-02 + **/ +public abstract class AbstractMongoDbInterceptor extends AbstractDatabaseInterceptor { + @Override + public ExecuteContext doBefore(ExecuteContext context) { + String database = ((DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO)).getDatabaseName(); + if (DatabaseWriteProhibitionManager.getMongoDbProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + } + return context; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteCommandInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteCommandInterceptor.java index ad098161bc..ac5076553a 100644 --- a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteCommandInterceptor.java +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteCommandInterceptor.java @@ -17,18 +17,22 @@ package com.huaweicloud.sermant.mongodb.interceptors; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; -import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; -import com.huaweicloud.sermant.database.controller.DatabaseController; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; import com.huaweicloud.sermant.database.handler.DatabaseHandler; -import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor; + +import com.mongodb.ServerAddress; +import com.mongodb.connection.ConnectionDescription; +import com.mongodb.internal.connection.Connection; /** - * 执行同步和异步write操作的拦截器 + * 执行executeCommand方法的拦截器 * * @author daizhenyu * @since 2024-01-18 **/ -public class ExecuteCommandInterceptor extends AbstractDatabaseInterceptor { +public class ExecuteCommandInterceptor extends AbstractMongoDbInterceptor { + private static final int PARAM_INDEX = 5; + /** * 无参构造方法 */ @@ -45,11 +49,16 @@ public ExecuteCommandInterceptor(DatabaseHandler handler) { } @Override - public ExecuteContext doBefore(ExecuteContext context) { - String database = (String) context.getArguments()[0]; - if (DatabaseWriteProhibitionManager.getMongoDbProhibitionDatabases().contains(database)) { - DatabaseController.disableDatabaseWriteOperation(database, context); + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + DatabaseInfo info = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, info); + info.setDatabaseName((String) context.getArguments()[0]); + Connection connection = (Connection) context.getArguments()[PARAM_INDEX]; + ConnectionDescription description = connection.getDescription(); + if (description != null) { + ServerAddress serverAddress = description.getServerAddress(); + info.setHostAddress(serverAddress.getHost()); + info.setPort(serverAddress.getPort()); } - return context; } } diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteRetryableCommandInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteRetryableCommandInterceptor.java index 79db0cdfe3..61b0969998 100644 --- a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteRetryableCommandInterceptor.java +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteRetryableCommandInterceptor.java @@ -17,10 +17,11 @@ package com.huaweicloud.sermant.mongodb.interceptors; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; -import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; -import com.huaweicloud.sermant.database.controller.DatabaseController; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; import com.huaweicloud.sermant.database.handler.DatabaseHandler; -import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor; + +import com.mongodb.ServerAddress; +import com.mongodb.internal.binding.WriteBinding; /** * 执行重试write操作的拦截器 @@ -28,7 +29,7 @@ * @author daizhenyu * @since 2024-01-18 **/ -public class ExecuteRetryableCommandInterceptor extends AbstractDatabaseInterceptor { +public class ExecuteRetryableCommandInterceptor extends AbstractMongoDbInterceptor { /** * 无参构造方法 */ @@ -45,11 +46,15 @@ public ExecuteRetryableCommandInterceptor(DatabaseHandler handler) { } @Override - public ExecuteContext doBefore(ExecuteContext context) { - String database = (String) context.getArguments()[1]; - if (DatabaseWriteProhibitionManager.getMongoDbProhibitionDatabases().contains(database)) { - DatabaseController.disableDatabaseWriteOperation(database, context); - } - return context; + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + DatabaseInfo info = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, info); + ServerAddress serverAddress = ((WriteBinding) context.getArguments()[0]) + .getWriteConnectionSource() + .getServerDescription() + .getAddress(); + info.setDatabaseName((String) context.getArguments()[1]); + info.setHostAddress(serverAddress.getHost()); + info.setPort(serverAddress.getPort()); } } diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteWriteCommandInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteWriteCommandInterceptor.java new file mode 100644 index 0000000000..f42c049df9 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteWriteCommandInterceptor.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mongodb.interceptors; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; +import com.huaweicloud.sermant.database.handler.DatabaseHandler; + +import com.mongodb.ServerAddress; +import com.mongodb.connection.ConnectionDescription; +import com.mongodb.internal.connection.Connection; + +/** + * 执行executeWriteCommand方法的拦截器 + * + * @author daizhenyu + * @since 2024-01-18 + **/ +public class ExecuteWriteCommandInterceptor extends AbstractMongoDbInterceptor { + private static final int PARAM_INDEX = 4; + + /** + * 无参构造方法 + */ + public ExecuteWriteCommandInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public ExecuteWriteCommandInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + DatabaseInfo info = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, info); + info.setDatabaseName((String) context.getArguments()[0]); + Connection connection = (Connection) context.getArguments()[PARAM_INDEX]; + ConnectionDescription description = connection.getDescription(); + if (description != null) { + ServerAddress serverAddress = description.getServerAddress(); + info.setHostAddress(serverAddress.getHost()); + info.setPort(serverAddress.getPort()); + } + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/MixedBulkWriteOperationInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/MixedBulkWriteOperationInterceptor.java index 4fb0dc3fb8..da17c929b1 100644 --- a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/MixedBulkWriteOperationInterceptor.java +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/MixedBulkWriteOperationInterceptor.java @@ -17,11 +17,11 @@ package com.huaweicloud.sermant.mongodb.interceptors; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; -import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; -import com.huaweicloud.sermant.database.controller.DatabaseController; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; import com.huaweicloud.sermant.database.handler.DatabaseHandler; -import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor; +import com.mongodb.ServerAddress; +import com.mongodb.internal.binding.WriteBinding; import com.mongodb.internal.operation.MixedBulkWriteOperation; /** @@ -30,7 +30,7 @@ * @author daizhenyu * @since 2024-01-16 **/ -public class MixedBulkWriteOperationInterceptor extends AbstractDatabaseInterceptor { +public class MixedBulkWriteOperationInterceptor extends AbstractMongoDbInterceptor { /** * 无参构造方法 */ @@ -47,11 +47,15 @@ public MixedBulkWriteOperationInterceptor(DatabaseHandler handler) { } @Override - public ExecuteContext doBefore(ExecuteContext context) { - String database = ((MixedBulkWriteOperation) context.getObject()).getNamespace().getDatabaseName(); - if (DatabaseWriteProhibitionManager.getMongoDbProhibitionDatabases().contains(database)) { - DatabaseController.disableDatabaseWriteOperation(database, context); - } - return context; + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + DatabaseInfo info = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, info); + ServerAddress serverAddress = ((WriteBinding) context.getArguments()[0]) + .getWriteConnectionSource() + .getServerDescription() + .getAddress(); + info.setDatabaseName(((MixedBulkWriteOperation) context.getObject()).getNamespace().getDatabaseName()); + info.setHostAddress(serverAddress.getHost()); + info.setPort(serverAddress.getPort()); } } diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/utils/MongoDbEnhancementHelper.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/utils/MongoDbEnhancementHelper.java index 3566b4a7c2..3ed8c05f46 100644 --- a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/utils/MongoDbEnhancementHelper.java +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/utils/MongoDbEnhancementHelper.java @@ -23,6 +23,7 @@ import com.huaweicloud.sermant.mongodb.constant.MethodParamTypeName; import com.huaweicloud.sermant.mongodb.interceptors.ExecuteCommandInterceptor; import com.huaweicloud.sermant.mongodb.interceptors.ExecuteRetryableCommandInterceptor; +import com.huaweicloud.sermant.mongodb.interceptors.ExecuteWriteCommandInterceptor; import com.huaweicloud.sermant.mongodb.interceptors.MixedBulkWriteOperationInterceptor; /** @@ -38,10 +39,6 @@ public class MongoDbEnhancementHelper { private static final String EXECUTE_METHOD_NAME = "execute"; - private static final String EXECUTE_ASYNC_METHOD_NAME = "executeAsync"; - - private static final String EXECUTE_COMMAND_ASYNC_METHOD_NAME = "executeCommandAsync"; - private static final String EXECUTE_COMMAND_METHOD_NAME = "executeCommand"; private static final String EXECUTE_WRITE_COMMAND_METHOD_NAME = "executeWriteCommand"; @@ -71,18 +68,6 @@ public class MongoDbEnhancementHelper { MethodParamTypeName.FUNCTION_CLASS_NAME }; - private static final String[] EXECUTE_RETRY_COMMAND_ASYNC_PARAMS_TYPE = { - MethodParamTypeName.ASYNC_WRITE_BINDING_CLASS_NAME, - MethodParamTypeName.STRING_CLASS_NAME, - MethodParamTypeName.READ_PREFERENCE_CLASS_NAME, - MethodParamTypeName.FIELD_NAME_VALIDATOR_CLASS_NAME, - MethodParamTypeName.DECODER_CLASS_NAME, - MethodParamTypeName.COMMAND_CREATOR_CLASS_NAME, - MethodParamTypeName.COMMAND_WRITE_TRANSFORMER_ASYNC_CLASS_NAME, - MethodParamTypeName.FUNCTION_CLASS_NAME, - MethodParamTypeName.SINGLE_RESULT_CALLBACK_CLASS_NAME - }; - private MongoDbEnhancementHelper() { } @@ -114,7 +99,6 @@ public static InterceptDeclarer[] getMixedBulkWriteOperationInterceptDeclarers() new MixedBulkWriteOperationInterceptor(); return new InterceptDeclarer[]{ InterceptDeclarer.build(getExecuteMethodMatcher(), mixedBulkWriteOperationInterceptor), - InterceptDeclarer.build(getExecuteAsyncMethodMatcher(), mixedBulkWriteOperationInterceptor) }; } @@ -140,37 +124,14 @@ public static InterceptDeclarer getExecuteInterceptDeclarer(DatabaseHandler hand } /** - * 获取MixedBulkWriteOperation executeAsync方法无参拦截器 - * - * @return InterceptDeclarer MixedBulkWriteOperation executeAsync方法无参拦截器 - */ - public static InterceptDeclarer getExecuteAsyncInterceptDeclarer() { - return InterceptDeclarer.build(getExecuteAsyncMethodMatcher(), - new MixedBulkWriteOperationInterceptor()); - } - - /** - * 获取MixedBulkWriteOperation executeAsync方法有参拦截器 - * - * @param handler 数据库自定义处理器 - * @return InterceptDeclarer MixedBulkWriteOperation executeAsync方法有参拦截器 - */ - public static InterceptDeclarer getExecuteAsyncInterceptDeclarer(DatabaseHandler handler) { - return InterceptDeclarer.build(getExecuteAsyncMethodMatcher(), - new MixedBulkWriteOperationInterceptor(handler)); - } - - /** - * 获取CommandOperationHelper写操作无参拦截器 + * 获取CommandOperationHelper写操作无参拦截器数组 * - * @return InterceptDeclarer[] CommandOperationHelper写操作无参拦截器 + * @return InterceptDeclarer[] CommandOperationHelper写操作无参拦截器数组 */ public static InterceptDeclarer[] getCommandOperationHelperInterceptDeclarers() { - ExecuteCommandInterceptor commandInterceptor = new ExecuteCommandInterceptor(); return new InterceptDeclarer[]{ - InterceptDeclarer.build(getExecuteCommandMethodMatcher(), commandInterceptor), - InterceptDeclarer.build(getExecuteCommandAsyncMethodMatcher(), commandInterceptor), - InterceptDeclarer.build(getExecuteWriteCommandMethodMatcher(), commandInterceptor), + InterceptDeclarer.build(getExecuteCommandMethodMatcher(), new ExecuteCommandInterceptor()), + InterceptDeclarer.build(getExecuteWriteCommandMethodMatcher(), new ExecuteWriteCommandInterceptor()), InterceptDeclarer.build(getExecuteRetryableCommandMethodMatcher(), new ExecuteRetryableCommandInterceptor()) }; @@ -201,7 +162,7 @@ public static InterceptDeclarer getExecuteCommandInterceptDeclarer(DatabaseHandl * @return InterceptDeclarer CommandOperationHelper executeWriteCommand方法无参拦截器 */ public static InterceptDeclarer getExecuteWriteCommandInterceptDeclarer() { - return InterceptDeclarer.build(getExecuteWriteCommandMethodMatcher(), new ExecuteCommandInterceptor()); + return InterceptDeclarer.build(getExecuteWriteCommandMethodMatcher(), new ExecuteWriteCommandInterceptor()); } /** @@ -212,27 +173,8 @@ public static InterceptDeclarer getExecuteWriteCommandInterceptDeclarer() { */ public static InterceptDeclarer getExecuteWriteCommandInterceptDeclarer( DatabaseHandler handler) { - return InterceptDeclarer.build(getExecuteWriteCommandMethodMatcher(), new ExecuteCommandInterceptor(handler)); - } - - /** - * 获取CommandOperationHelper executeCommandAsync方法无参拦截器 - * - * @return InterceptDeclarer CommandOperationHelper executeCommandAsync方法无参拦截器 - */ - public static InterceptDeclarer getExecuteCommandAsyncInterceptDeclarer() { - return InterceptDeclarer.build(getExecuteCommandAsyncMethodMatcher(), new ExecuteCommandInterceptor()); - } - - /** - * 获取CommandOperationHelper executeCommandAsync方法有参拦截器 - * - * @param handler 数据库自定义处理器 - * @return InterceptDeclarer CommandOperationHelper executeCommandAsync方法有参拦截器 - */ - public static InterceptDeclarer getExecuteCommandAsyncInterceptDeclarer( - DatabaseHandler handler) { - return InterceptDeclarer.build(getExecuteCommandAsyncMethodMatcher(), new ExecuteCommandInterceptor(handler)); + return InterceptDeclarer + .build(getExecuteWriteCommandMethodMatcher(), new ExecuteWriteCommandInterceptor(handler)); } /** @@ -261,10 +203,6 @@ private static MethodMatcher getExecuteMethodMatcher() { return MethodMatcher.nameEquals(EXECUTE_METHOD_NAME); } - private static MethodMatcher getExecuteAsyncMethodMatcher() { - return MethodMatcher.nameEquals(EXECUTE_ASYNC_METHOD_NAME); - } - private static MethodMatcher getExecuteCommandMethodMatcher() { return MethodMatcher.nameEquals(EXECUTE_COMMAND_METHOD_NAME) .and(MethodMatcher.paramTypesEqual(EXECUTE_COMMAND_PARAMS_TYPE)); @@ -275,14 +213,8 @@ private static MethodMatcher getExecuteWriteCommandMethodMatcher() { .and(MethodMatcher.paramCountEquals(METHOD_PARAM_COUNT)); } - private static MethodMatcher getExecuteCommandAsyncMethodMatcher() { - return MethodMatcher.nameEquals(EXECUTE_COMMAND_ASYNC_METHOD_NAME) - .and(MethodMatcher.paramCountEquals(METHOD_PARAM_COUNT)); - } - private static MethodMatcher getExecuteRetryableCommandMethodMatcher() { return MethodMatcher.nameEquals(EXECUTE_RETRYABLE_COMMAND_METHOD_NAME) - .and(MethodMatcher.paramTypesEqual(EXECUTE_RETRY_COMMAND_ASYNC_PARAMS_TYPE) - .or(MethodMatcher.paramTypesEqual(EXECUTE_RETRY_COMMAND_PARAMS_TYPE))); + .and(MethodMatcher.paramTypesEqual(EXECUTE_RETRY_COMMAND_PARAMS_TYPE)); } } diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ConnectionSourceImpl.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ConnectionSourceImpl.java new file mode 100644 index 0000000000..e5f26ae6c6 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ConnectionSourceImpl.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mongodb.interceptors; + +import com.mongodb.ServerApi; +import com.mongodb.connection.ServerDescription; +import com.mongodb.internal.binding.ConnectionSource; +import com.mongodb.internal.connection.Connection; +import com.mongodb.internal.session.SessionContext; + +/** + * ConnectionSource接口的实现类 + * + * @author daizhenyu + * @since 2024-02-05 + **/ +public class ConnectionSourceImpl implements ConnectionSource { + private ServerDescription description; + + /** + * 构造方法 + * + * @param description 服务端信息 + */ + public ConnectionSourceImpl(ServerDescription description) { + this.description = description; + } + @Override + public ServerDescription getServerDescription() { + return description; + } + + @Override + public SessionContext getSessionContext() { + return null; + } + + @Override + public ServerApi getServerApi() { + return null; + } + + @Override + public Connection getConnection() { + return null; + } + + @Override + public int getCount() { + return 0; + } + + @Override + public ConnectionSource retain() { + return null; + } + + @Override + public void release() { + + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteCommandInterceptorTest.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteCommandInterceptorTest.java index 97fd8133cb..a02e9d5a48 100644 --- a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteCommandInterceptorTest.java +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteCommandInterceptorTest.java @@ -21,6 +21,10 @@ import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; import com.mongodb.MongoNamespace; +import com.mongodb.ServerAddress; +import com.mongodb.connection.ConnectionDescription; +import com.mongodb.internal.connection.Connection; +import com.mongodb.internal.connection.DefaultServerConnection; import com.mongodb.internal.operation.MixedBulkWriteOperation; import org.junit.AfterClass; @@ -61,7 +65,12 @@ public static void setUp() { operationMock = Mockito.mock(MixedBulkWriteOperation.class); methodMock = Mockito.mock(Method.class); Mockito.when(operationMock.getNamespace()).thenReturn(namespace); - argument = new Object[]{"database-test"}; + Connection connection = Mockito.mock(DefaultServerConnection.class); + ConnectionDescription description = Mockito.mock(ConnectionDescription.class); + ServerAddress serverAddress = new ServerAddress("127.0.0.1", 8080); + Mockito.when(connection.getDescription()).thenReturn(description); + Mockito.when(description.getServerAddress()).thenReturn(serverAddress); + argument = new Object[]{"database-test", null, null, null, null, connection}; } @AfterClass @@ -70,29 +79,30 @@ public static void tearDown() { } @Test - public void testDoBefore() { + public void testDoBefore() throws Exception { // 数据库禁写开关关闭 globalConfig.setEnableMongoDbWriteProhibition(false); context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); - interceptor.doBefore(context); + interceptor.before(context); Assert.assertNull(context.getThrowableOut()); // 数据库禁写开关关闭,禁写数据库set包含被拦截的数据库 Set databases = new HashSet<>(); databases.add("database-test"); globalConfig.setMongoDbDatabases(databases); + interceptor.before(context); Assert.assertNull(context.getThrowableOut()); //数据库禁写开关打开,禁写数据库集合包含被拦截的数据库 globalConfig.setEnableMongoDbWriteProhibition(true); context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); - interceptor.doBefore(context); + interceptor.before(context); Assert.assertEquals("Database prohibit to write, database: database-test", context.getThrowableOut().getMessage()); //数据库禁写开关打开,禁写数据库集合不包含被拦截的数据库 globalConfig.setMongoDbDatabases(new HashSet<>()); - interceptor.doBefore(context); + interceptor.before(context); context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); Assert.assertNull(context.getThrowableOut()); } diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteRetryableCommandInterceptorTest.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteRetryableCommandInterceptorTest.java index aed7687745..2afe38ad57 100644 --- a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteRetryableCommandInterceptorTest.java +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteRetryableCommandInterceptorTest.java @@ -21,7 +21,15 @@ import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; import com.mongodb.MongoNamespace; +import com.mongodb.ServerAddress; +import com.mongodb.ServerApi; +import com.mongodb.connection.ServerDescription; +import com.mongodb.internal.binding.ConnectionSource; +import com.mongodb.internal.binding.SingleServerBinding; +import com.mongodb.internal.binding.WriteBinding; +import com.mongodb.internal.connection.Connection; import com.mongodb.internal.operation.MixedBulkWriteOperation; +import com.mongodb.internal.session.SessionContext; import org.junit.AfterClass; import org.junit.Assert; @@ -61,7 +69,12 @@ public static void setUp() { operationMock = Mockito.mock(MixedBulkWriteOperation.class); methodMock = Mockito.mock(Method.class); Mockito.when(operationMock.getNamespace()).thenReturn(namespace); - argument = new Object[] {"first-param", "database-test"}; + WriteBinding binding = Mockito.mock(SingleServerBinding.class); + ServerDescription description = Mockito.mock(ServerDescription.class); + ServerAddress serverAddress = new ServerAddress("127.0.0.1", 8080); + Mockito.when(binding.getWriteConnectionSource()).thenReturn(new ConnectionSourceImpl(description)); + Mockito.when(description.getAddress()).thenReturn(serverAddress); + argument = new Object[] {binding, "database-test"}; } @AfterClass @@ -70,23 +83,24 @@ public static void tearDown() { } @Test - public void testDoBefore() { + public void testDoBefore() throws Exception { // 数据库禁写开关关闭 globalConfig.setEnableMongoDbWriteProhibition(false); context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); - interceptor.doBefore(context); + interceptor.before(context); Assert.assertNull(context.getThrowableOut()); // 数据库禁写开关关闭,禁写数据库set包含被拦截的数据库 Set databases = new HashSet<>(); databases.add("database-test"); globalConfig.setMongoDbDatabases(databases); + interceptor.before(context); Assert.assertNull(context.getThrowableOut()); //数据库禁写开关打开,禁写数据库集合包含被拦截的数据库 globalConfig.setEnableMongoDbWriteProhibition(true); context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); - interceptor.doBefore(context); + interceptor.before(context); Assert.assertEquals("Database prohibit to write, database: database-test", context.getThrowableOut().getMessage()); diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteWriteCommandInterceptorTest.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteWriteCommandInterceptorTest.java new file mode 100644 index 0000000000..63c9145dd5 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteWriteCommandInterceptorTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mongodb.interceptors; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionConfig; +import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; + +import com.mongodb.MongoNamespace; +import com.mongodb.ServerAddress; +import com.mongodb.connection.ConnectionDescription; +import com.mongodb.internal.connection.Connection; +import com.mongodb.internal.connection.DefaultServerConnection; +import com.mongodb.internal.operation.MixedBulkWriteOperation; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; + +/** + * ExecuteCommand方法拦截器单元测试 + * + * @author daizhenyu + * @since 2024-01-23 + **/ +public class ExecuteWriteCommandInterceptorTest { + private static DatabaseWriteProhibitionConfig globalConfig = new DatabaseWriteProhibitionConfig(); + + private static MongoNamespace namespace = new MongoNamespace("database-test", + "collection-test"); + + private static MixedBulkWriteOperation operationMock; + + private static ExecuteContext context; + + private static Method methodMock; + + private static Object[] argument; + + private ExecuteWriteCommandInterceptor interceptor = new ExecuteWriteCommandInterceptor(); + + @BeforeClass + public static void setUp() { + DatabaseWriteProhibitionManager.updateGlobalConfig(globalConfig); + operationMock = Mockito.mock(MixedBulkWriteOperation.class); + methodMock = Mockito.mock(Method.class); + Mockito.when(operationMock.getNamespace()).thenReturn(namespace); + Connection connection = Mockito.mock(DefaultServerConnection.class); + ConnectionDescription description = Mockito.mock(ConnectionDescription.class); + ServerAddress serverAddress = new ServerAddress("127.0.0.1", 8080); + Mockito.when(connection.getDescription()).thenReturn(description); + Mockito.when(description.getServerAddress()).thenReturn(serverAddress); + argument = new Object[]{"database-test", null, null, null, connection}; + } + + @AfterClass + public static void tearDown() { + Mockito.clearAllCaches(); + } + + @Test + public void testDoBefore() throws Exception { + // 数据库禁写开关关闭 + globalConfig.setEnableMongoDbWriteProhibition(false); + context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); + interceptor.before(context); + Assert.assertNull(context.getThrowableOut()); + + // 数据库禁写开关关闭,禁写数据库set包含被拦截的数据库 + Set databases = new HashSet<>(); + databases.add("database-test"); + globalConfig.setMongoDbDatabases(databases); + interceptor.before(context); + Assert.assertNull(context.getThrowableOut()); + + //数据库禁写开关打开,禁写数据库集合包含被拦截的数据库 + globalConfig.setEnableMongoDbWriteProhibition(true); + context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); + interceptor.before(context); + Assert.assertEquals("Database prohibit to write, database: database-test", + context.getThrowableOut().getMessage()); + + //数据库禁写开关打开,禁写数据库集合不包含被拦截的数据库 + globalConfig.setMongoDbDatabases(new HashSet<>()); + interceptor.before(context); + context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); + Assert.assertNull(context.getThrowableOut()); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/MixedBulkWriteOperationInterceptorTest.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/MixedBulkWriteOperationInterceptorTest.java index 0552ac010f..396932ca0c 100644 --- a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/MixedBulkWriteOperationInterceptorTest.java +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/test/java/com/huaweicloud/sermant/mongodb/interceptors/MixedBulkWriteOperationInterceptorTest.java @@ -21,7 +21,15 @@ import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; import com.mongodb.MongoNamespace; +import com.mongodb.ServerAddress; +import com.mongodb.ServerApi; +import com.mongodb.connection.ServerDescription; +import com.mongodb.internal.binding.ConnectionSource; +import com.mongodb.internal.binding.SingleServerBinding; +import com.mongodb.internal.binding.WriteBinding; +import com.mongodb.internal.connection.Connection; import com.mongodb.internal.operation.MixedBulkWriteOperation; +import com.mongodb.internal.session.SessionContext; import org.junit.AfterClass; import org.junit.Assert; @@ -51,6 +59,8 @@ public class MixedBulkWriteOperationInterceptorTest { private static Method methodMock; + private static Object[] argument; + private MixedBulkWriteOperationInterceptor interceptor = new MixedBulkWriteOperationInterceptor(); @BeforeClass @@ -59,6 +69,12 @@ public static void setUp() { operationMock = Mockito.mock(MixedBulkWriteOperation.class); methodMock = Mockito.mock(Method.class); Mockito.when(operationMock.getNamespace()).thenReturn(namespace); + WriteBinding binding = Mockito.mock(SingleServerBinding.class); + ServerDescription description = Mockito.mock(ServerDescription.class); + ServerAddress serverAddress = new ServerAddress("127.0.0.1", 8080); + Mockito.when(binding.getWriteConnectionSource()).thenReturn(new ConnectionSourceImpl(description)); + Mockito.when(description.getAddress()).thenReturn(serverAddress); + argument = new Object[]{binding}; } @AfterClass @@ -67,30 +83,31 @@ public static void tearDown() { } @Test - public void testDoBefore() { + public void testDoBefore() throws Exception { // 数据库禁写开关关闭 globalConfig.setEnableMongoDbWriteProhibition(false); - context = ExecuteContext.forMemberMethod(operationMock, methodMock, null, null, null); - interceptor.doBefore(context); + context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); + interceptor.before(context); Assert.assertNull(context.getThrowableOut()); // 数据库禁写开关关闭,禁写数据库set包含被拦截的数据库 Set databases = new HashSet<>(); databases.add("database-test"); globalConfig.setMongoDbDatabases(databases); + interceptor.before(context); Assert.assertNull(context.getThrowableOut()); //数据库禁写开关打开,禁写数据库集合包含被拦截的数据库 globalConfig.setEnableMongoDbWriteProhibition(true); - context = ExecuteContext.forMemberMethod(operationMock, methodMock, null, null, null); - interceptor.doBefore(context); + context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); + interceptor.before(context); Assert.assertEquals("Database prohibit to write, database: database-test", context.getThrowableOut().getMessage()); //数据库禁写开关打开,禁写数据库集合不包含被拦截的数据库 globalConfig.setMongoDbDatabases(new HashSet<>()); - interceptor.doBefore(context); - context = ExecuteContext.forMemberMethod(operationMock, methodMock, null, null, null); + interceptor.before(context); + context = ExecuteContext.forMemberMethod(operationMock, methodMock, argument, null, null); Assert.assertNull(context.getThrowableOut()); } } diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/pom.xml b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/pom.xml new file mode 100644 index 0000000000..acb5e64ea0 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/pom.xml @@ -0,0 +1,58 @@ + + + + sermant-database-write-prohibition + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + mysql-mariadb-2.x-plugin + + + 8 + 8 + false + plugin + 2.6.0 + + + + + com.huaweicloud.sermant + sermant-agentcore-core + provided + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb.version} + provided + + + com.huaweicloud.sermant + database-controller + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + org.apache.maven.plugins + maven-shade-plugin + + + + + \ No newline at end of file diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/declarers/QueryProtocolDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/declarers/QueryProtocolDeclarer.java new file mode 100644 index 0000000000..47a3667499 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/declarers/QueryProtocolDeclarer.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv2.declarers; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.mariadbv2.utils.MariadbV2EnhancementHelper; + +/** + * AbstractQueryProtocol类增强声明器 + * + * @author daizhenyu + * @since 2024-01-26 + **/ +public class QueryProtocolDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return MariadbV2EnhancementHelper.getQueryProtocolClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return MariadbV2EnhancementHelper.getQueryProtocolInterceptDeclarers(); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/AbstractMariadbV2Interceptor.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/AbstractMariadbV2Interceptor.java new file mode 100644 index 0000000000..547c968e37 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/AbstractMariadbV2Interceptor.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv2.interceptors; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; +import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor; + +import org.mariadb.jdbc.HostAddress; +import org.mariadb.jdbc.internal.protocol.Protocol; + +/** + * mariadb2.x抽象interceptor + * + * @author daizhenyu + * @since 2024-02-02 + **/ +public abstract class AbstractMariadbV2Interceptor extends AbstractDatabaseInterceptor { + @Override + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + DatabaseInfo info = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, info); + Protocol protocol = (Protocol) context.getObject(); + info.setDatabaseName(protocol.getDatabase()); + HostAddress hostAddress = protocol.getHostAddress(); + if (hostAddress != null) { + info.setHostAddress(hostAddress.host); + info.setPort(hostAddress.port); + } + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/ExecuteBatchStmtInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/ExecuteBatchStmtInterceptor.java new file mode 100644 index 0000000000..460a1a2bf1 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/ExecuteBatchStmtInterceptor.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv2.interceptors; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; +import com.huaweicloud.sermant.database.controller.DatabaseController; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; +import com.huaweicloud.sermant.database.handler.DatabaseHandler; +import com.huaweicloud.sermant.database.utils.SqlParserUtils; + +import java.util.List; + +/** + * executeBatchStmt方法拦截器 + * + * @author daizhenyu + * @since 2024-01-26 + **/ +public class ExecuteBatchStmtInterceptor extends AbstractMariadbV2Interceptor { + private static final int PARAM_INDEX = 2; + + /** + * 无参构造方法 + */ + public ExecuteBatchStmtInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public ExecuteBatchStmtInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + protected ExecuteContext doBefore(ExecuteContext context) { + String database = ((DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO)).getDatabaseName(); + List sqlList = (List) context.getArguments()[PARAM_INDEX]; + for (String sql : sqlList) { + if (SqlParserUtils.isWriteOperation(sql) + && DatabaseWriteProhibitionManager.getMysqlProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + return context; + } + } + return context; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/ExecuteInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/ExecuteInterceptor.java new file mode 100644 index 0000000000..ac081ce81d --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/ExecuteInterceptor.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv2.interceptors; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; +import com.huaweicloud.sermant.database.controller.DatabaseController; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; +import com.huaweicloud.sermant.database.handler.DatabaseHandler; +import com.huaweicloud.sermant.database.utils.SqlParserUtils; + +import org.mariadb.jdbc.internal.util.dao.ClientPrepareResult; + +/** + * executeQuery、executeBatchClient方法拦截器 + * + * @author daizhenyu + * @since 2024-01-26 + **/ +public class ExecuteInterceptor extends AbstractMariadbV2Interceptor { + private static final int PARAM_INDEX = 2; + + /** + * 无参构造方法 + */ + public ExecuteInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public ExecuteInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + protected ExecuteContext doBefore(ExecuteContext context) { + String database = ((DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO)).getDatabaseName(); + Object argument = context.getArguments()[PARAM_INDEX]; + String sql = null; + if (argument instanceof ClientPrepareResult) { + sql = ((ClientPrepareResult) argument).getSql(); + } else { + sql = (String) argument; + } + if (SqlParserUtils.isWriteOperation(sql) + && DatabaseWriteProhibitionManager.getMysqlProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + } + return context; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/ExecuteServerInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/ExecuteServerInterceptor.java new file mode 100644 index 0000000000..6a9568c1af --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/ExecuteServerInterceptor.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv2.interceptors; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; +import com.huaweicloud.sermant.database.controller.DatabaseController; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; +import com.huaweicloud.sermant.database.handler.DatabaseHandler; +import com.huaweicloud.sermant.database.utils.SqlParserUtils; + +import org.mariadb.jdbc.internal.util.dao.ServerPrepareResult; + +/** + * executePreparedQuery、executeBatchServer方法拦截器 + * + * @author daizhenyu + * @since 2024-01-26 + **/ +public class ExecuteServerInterceptor extends AbstractMariadbV2Interceptor { + /** + * 无参构造方法 + */ + public ExecuteServerInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public ExecuteServerInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + protected ExecuteContext doBefore(ExecuteContext context) { + String database = ((DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO)).getDatabaseName(); + String sql = ((ServerPrepareResult) context.getArguments()[1]).getSql(); + if (SqlParserUtils.isWriteOperation(sql) + && DatabaseWriteProhibitionManager.getMysqlProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + } + return context; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/PrepareInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/PrepareInterceptor.java new file mode 100644 index 0000000000..4d2a7bd7d9 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/interceptors/PrepareInterceptor.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv2.interceptors; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; +import com.huaweicloud.sermant.database.controller.DatabaseController; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; +import com.huaweicloud.sermant.database.handler.DatabaseHandler; +import com.huaweicloud.sermant.database.utils.SqlParserUtils; + +/** + * prepare方法拦截器 + * + * @author daizhenyu + * @since 2024-01-27 + **/ +public class PrepareInterceptor extends AbstractMariadbV2Interceptor { + /** + * 无参构造方法 + */ + public PrepareInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public PrepareInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + protected ExecuteContext doBefore(ExecuteContext context) { + String database = ((DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO)).getDatabaseName(); + String sql = (String) context.getArguments()[0]; + if (SqlParserUtils.isWriteOperation(sql) + && DatabaseWriteProhibitionManager.getMysqlProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + } + return context; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/utils/MariadbV2EnhancementHelper.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/utils/MariadbV2EnhancementHelper.java new file mode 100644 index 0000000000..d3027c23a6 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv2/utils/MariadbV2EnhancementHelper.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv2.utils; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; +import com.huaweicloud.sermant.database.handler.DatabaseHandler; +import com.huaweicloud.sermant.mariadbv2.interceptors.ExecuteBatchStmtInterceptor; +import com.huaweicloud.sermant.mariadbv2.interceptors.ExecuteInterceptor; +import com.huaweicloud.sermant.mariadbv2.interceptors.ExecuteServerInterceptor; +import com.huaweicloud.sermant.mariadbv2.interceptors.PrepareInterceptor; + +/** + * mariadb2.x拦截点辅助类 + * + * @author daizhenyu + * @since 2024-01-26 + **/ +public class MariadbV2EnhancementHelper { + private static final String QUERY_PROTOCOL_CLASS = "org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol"; + + private static final String EXECUTE_QUERY_METHOD_NAME = "executeQuery"; + + private static final String EXECUTE_BATCH_CLIENT_METHOD_NAME = "executeBatchClient"; + + private static final String EXECUTE_BATCH_SERVER_METHOD_NAME = "executeBatchServer"; + + private static final String EXECUTE_BATCH_STMT_METHOD_NAME = "executeBatchStmt"; + + private static final String EXECUTE_PREPARED_QUERY_METHOD_NAME = "executePreparedQuery"; + + private static final String PREPARE_METHOD_NAME = "prepare"; + + private static final int FIRST_OVER_LOAD_METHOD_PARAM_COUNT = 3; + + private static final int SECOND_OVER_LOAD_METHOD_PARAM_COUNT = 4; + + private static final int THIRD_OVER_LOAD_METHOD_PARAM_COUNT = 5; + + private MariadbV2EnhancementHelper() { + } + + /** + * 获取AbstractQueryProtocol类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getQueryProtocolClassMatcher() { + return ClassMatcher.nameEquals(QUERY_PROTOCOL_CLASS); + } + + /** + * 获取AbstractQueryProtocol类sql执行无参拦截器数组 + * + * @return InterceptDeclarer[] AbstractQueryProtocol类sql执行无参拦截器数组 + */ + public static InterceptDeclarer[] getQueryProtocolInterceptDeclarers() { + ExecuteInterceptor executeInterceptor = new ExecuteInterceptor(); + ExecuteServerInterceptor executeServerInterceptor = new ExecuteServerInterceptor(); + return new InterceptDeclarer[]{ + InterceptDeclarer.build(getExecuteQueryMethodMatcher(), executeInterceptor), + InterceptDeclarer.build(getExecuteBatchClientMethodMatcher(), executeInterceptor), + InterceptDeclarer.build(getExecuteBatchStmtMethodMatcher(), new ExecuteBatchStmtInterceptor()), + InterceptDeclarer.build(getExecutePreparedQueryMethodMatcher(), executeServerInterceptor), + InterceptDeclarer.build(getExecuteBatchServerMethodMatcher(), executeServerInterceptor), + InterceptDeclarer.build(getPrepareMethodMatcher(), new PrepareInterceptor()) + }; + } + + /** + * 获取AbstractQueryProtocol类executeQuery方法无参拦截器 + * + * @return InterceptDeclarer AbstractQueryProtocol类executeQuery方法无参拦截器 + */ + public static InterceptDeclarer getExecuteQueryInterceptDeclarer() { + return InterceptDeclarer.build(getExecuteQueryMethodMatcher(), + new ExecuteInterceptor()); + } + + /** + * 获取AbstractQueryProtocol类executeQuery方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer AbstractQueryProtocol类execute方法有参拦截器 + */ + public static InterceptDeclarer getExecuteQueryInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getExecuteQueryMethodMatcher(), + new ExecuteInterceptor(handler)); + } + + /** + * 获取AbstractQueryProtocol类executeBatchClient方法无参拦截器 + * + * @return InterceptDeclarer AbstractQueryProtocol类executeBatchClient方法无参拦截器 + */ + public static InterceptDeclarer getExecuteBatchClientInterceptDeclarer() { + return InterceptDeclarer.build(getExecuteBatchClientMethodMatcher(), + new ExecuteInterceptor()); + } + + /** + * 获取AbstractQueryProtocol类executeBatchClient方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer AbstractQueryProtocol类executeBatchClient方法有参拦截器 + */ + public static InterceptDeclarer getExecuteBatchClientInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getExecuteBatchClientMethodMatcher(), + new ExecuteInterceptor(handler)); + } + + /** + * 获取AbstractQueryProtocol类executeBatchStmt方法无参拦截器 + * + * @return InterceptDeclarer AbstractQueryProtocol类executeBatchStmt方法无参拦截器 + */ + public static InterceptDeclarer getExecuteBatchStmtInterceptDeclarer() { + return InterceptDeclarer.build(getExecuteBatchStmtMethodMatcher(), + new ExecuteBatchStmtInterceptor()); + } + + /** + * 获取AbstractQueryProtocol类executeBatchStmt方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer AbstractQueryProtocol类executeBatchStmt方法有参拦截器 + */ + public static InterceptDeclarer getExecuteBatchStmtInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getExecuteBatchStmtMethodMatcher(), + new ExecuteBatchStmtInterceptor(handler)); + } + + /** + * 获取AbstractQueryProtocol类executePreparedQuery方法无参拦截器 + * + * @return InterceptDeclarer AbstractQueryProtocol类executePreparedQuery方法无参拦截器 + */ + public static InterceptDeclarer getExecutePreparedQueryInterceptDeclarer() { + return InterceptDeclarer.build(getExecutePreparedQueryMethodMatcher(), + new ExecuteServerInterceptor()); + } + + /** + * 获取AbstractQueryProtocol类executePreparedQuery方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer AbstractQueryProtocol类executePreparedQuery方法有参拦截器 + */ + public static InterceptDeclarer getExecutePreparedQueryInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getExecutePreparedQueryMethodMatcher(), + new ExecuteServerInterceptor(handler)); + } + + /** + * 获取AbstractQueryProtocol类executeBatchServer方法无参拦截器 + * + * @return InterceptDeclarer AbstractQueryProtocol类executeBatchServer方法无参拦截器 + */ + public static InterceptDeclarer getExecuteBatchServerInterceptDeclarer() { + return InterceptDeclarer.build(getExecuteBatchServerMethodMatcher(), + new ExecuteServerInterceptor()); + } + + /** + * 获取AbstractQueryProtocol类executeBatchServer方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer AbstractQueryProtocol类executeBatchServer方法有参拦截器 + */ + public static InterceptDeclarer getExecuteBatchServerInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getExecuteBatchServerMethodMatcher(), + new ExecuteServerInterceptor(handler)); + } + + /** + * 获取AbstractQueryProtocol类prepare方法无参拦截器 + * + * @return InterceptDeclarer AbstractQueryProtocol类prepare方法无参拦截器 + */ + public static InterceptDeclarer getPrepareInterceptDeclarer() { + return InterceptDeclarer.build(getPrepareMethodMatcher(), + new PrepareInterceptor()); + } + + /** + * 获取AbstractQueryProtocol类prepare方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer AbstractQueryProtocol类prepare方法有参拦截器 + */ + public static InterceptDeclarer getPrepareInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getPrepareMethodMatcher(), + new PrepareInterceptor(handler)); + } + + private static MethodMatcher getExecuteQueryMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_QUERY_METHOD_NAME) + .and(MethodMatcher.paramCountEquals(FIRST_OVER_LOAD_METHOD_PARAM_COUNT) + .or(MethodMatcher.paramCountEquals(SECOND_OVER_LOAD_METHOD_PARAM_COUNT)) + .or(MethodMatcher.paramCountEquals(THIRD_OVER_LOAD_METHOD_PARAM_COUNT))); + } + + private static MethodMatcher getExecuteBatchStmtMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_BATCH_STMT_METHOD_NAME); + } + + private static MethodMatcher getExecuteBatchClientMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_BATCH_CLIENT_METHOD_NAME); + } + + private static MethodMatcher getExecutePreparedQueryMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_PREPARED_QUERY_METHOD_NAME); + } + + private static MethodMatcher getExecuteBatchServerMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_BATCH_SERVER_METHOD_NAME); + } + + private static MethodMatcher getPrepareMethodMatcher() { + return MethodMatcher.nameEquals(PREPARE_METHOD_NAME); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer new file mode 100644 index 0000000000..6e8007ba58 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-2.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer @@ -0,0 +1,16 @@ +# +# Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. +# +# Licensed 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. +# +com.huaweicloud.sermant.mariadbv2.declarers.QueryProtocolDeclarer \ No newline at end of file diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/pom.xml b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/pom.xml new file mode 100644 index 0000000000..0dae417a02 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/pom.xml @@ -0,0 +1,58 @@ + + + + sermant-database-write-prohibition + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + mysql-mariadb-3.x-plugin + + + 8 + 8 + false + plugin + 3.0.11 + + + + + com.huaweicloud.sermant + sermant-agentcore-core + provided + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb.version} + provided + + + com.huaweicloud.sermant + database-controller + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + org.apache.maven.plugins + maven-shade-plugin + + + + + \ No newline at end of file diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/declarers/ReplayClientDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/declarers/ReplayClientDeclarer.java new file mode 100644 index 0000000000..6e393a17e1 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/declarers/ReplayClientDeclarer.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv3.declarers; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.mariadbv3.utils.MariadbV3EnhancementHelper; + +/** + * ReplayClient类增强声明器 + * + * @author daizhenyu + * @since 2024-01-30 + **/ +public class ReplayClientDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return MariadbV3EnhancementHelper.getReplayClientClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[] { + MariadbV3EnhancementHelper.getSendQueryInterceptDeclarer() + }; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/declarers/StandardClientDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/declarers/StandardClientDeclarer.java new file mode 100644 index 0000000000..f2effba439 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/declarers/StandardClientDeclarer.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv3.declarers; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.mariadbv3.utils.MariadbV3EnhancementHelper; + +/** + * StandardClient类增强声明器 + * + * @author daizhenyu + * @since 2024-01-30 + **/ +public class StandardClientDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return MariadbV3EnhancementHelper.getStandardClientClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[] { + MariadbV3EnhancementHelper.getSendQueryInterceptDeclarer() + }; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/interceptors/SendQueryInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/interceptors/SendQueryInterceptor.java new file mode 100644 index 0000000000..ea86fd6641 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/interceptors/SendQueryInterceptor.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv3.interceptors; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager; +import com.huaweicloud.sermant.database.controller.DatabaseController; +import com.huaweicloud.sermant.database.entity.DatabaseInfo; +import com.huaweicloud.sermant.database.handler.DatabaseHandler; +import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor; +import com.huaweicloud.sermant.database.utils.SqlParserUtils; + +import org.mariadb.jdbc.HostAddress; +import org.mariadb.jdbc.client.impl.StandardClient; +import org.mariadb.jdbc.message.ClientMessage; + +/** + * sendQuery方法拦截器 + * + * @author daizhenyu + * @since 2024-01-30 + **/ +public class SendQueryInterceptor extends AbstractDatabaseInterceptor { + /** + * 无参构造方法 + */ + public SendQueryInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public SendQueryInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + protected ExecuteContext doBefore(ExecuteContext context) { + ClientMessage clientMessage = (ClientMessage) context.getArguments()[0]; + String database = ((DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO)).getDatabaseName(); + if (SqlParserUtils.isWriteOperation(clientMessage.description()) + && DatabaseWriteProhibitionManager.getMysqlProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + } + return context; + } + + @Override + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + DatabaseInfo info = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, info); + StandardClient client = (StandardClient) context.getObject(); + if (client.getContext() != null) { + info.setDatabaseName(client.getContext().getDatabase()); + } + HostAddress hostAddress = client.getHostAddress(); + info.setHostAddress(hostAddress.host); + info.setPort(hostAddress.port); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/utils/MariadbV3EnhancementHelper.java b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/utils/MariadbV3EnhancementHelper.java new file mode 100644 index 0000000000..31cbd64c62 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/java/com/huaweicloud/sermant/mariadbv3/utils/MariadbV3EnhancementHelper.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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.huaweicloud.sermant.mariadbv3.utils; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; +import com.huaweicloud.sermant.database.handler.DatabaseHandler; +import com.huaweicloud.sermant.mariadbv3.interceptors.SendQueryInterceptor; + +/** + * mariadb3.x拦截点辅助类 + * + * @author daizhenyu + * @since 2024-01-30 + **/ +public class MariadbV3EnhancementHelper { + private static final String REPLAY_CLIENT_CLASS = "org.mariadb.jdbc.client.impl.ReplayClient"; + + private static final String STANDARD_CLIENT_CLASS = "org.mariadb.jdbc.client.impl.StandardClient"; + + private static final String SEND_QUERY_METHOD_NAME = "sendQuery"; + + private MariadbV3EnhancementHelper() { + } + + /** + * 获取ReplayClient类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getReplayClientClassMatcher() { + return ClassMatcher.nameEquals(REPLAY_CLIENT_CLASS); + } + + /** + * 获取StandardClient类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getStandardClientClassMatcher() { + return ClassMatcher.nameEquals(STANDARD_CLIENT_CLASS); + } + + /** + * 获取sendQuery方法无参拦截器 + * + * @return InterceptDeclarer sendQuery方法无参拦截器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer() { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), + new SendQueryInterceptor()); + } + + /** + * 获取sendQuery方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer sendQuery方法有参拦截器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), + new SendQueryInterceptor(handler)); + } + + private static MethodMatcher getSendQueryMethodMatcher() { + return MethodMatcher.nameEquals(SEND_QUERY_METHOD_NAME); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer new file mode 100644 index 0000000000..26fa6d9261 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mysql-mariadb-3.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer @@ -0,0 +1,17 @@ +# +# Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. +# +# Licensed 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. +# +com.huaweicloud.sermant.mariadbv3.declarers.ReplayClientDeclarer +com.huaweicloud.sermant.mariadbv3.declarers.StandardClientDeclarer \ No newline at end of file diff --git a/sermant-plugins/sermant-database-write-prohibition/pom.xml b/sermant-plugins/sermant-database-write-prohibition/pom.xml index 524194daa6..72fcce2b65 100644 --- a/sermant-plugins/sermant-database-write-prohibition/pom.xml +++ b/sermant-plugins/sermant-database-write-prohibition/pom.xml @@ -29,6 +29,8 @@ database-controller database-config-service mongodb-3.x-4.x-plugin + mysql-mariadb-2.x-plugin + mysql-mariadb-3.x-plugin @@ -37,6 +39,8 @@ database-controller database-config-service mongodb-3.x-4.x-plugin + mysql-mariadb-2.x-plugin + mysql-mariadb-3.x-plugin @@ -45,6 +49,8 @@ database-controller database-config-service mongodb-3.x-4.x-plugin + mysql-mariadb-2.x-plugin + mysql-mariadb-3.x-plugin