diff --git a/sermant-agentcore/sermant-agentcore-config/config/plugins.yaml b/sermant-agentcore/sermant-agentcore-config/config/plugins.yaml index 640303395f..ba875a7803 100644 --- a/sermant-agentcore/sermant-agentcore-config/config/plugins.yaml +++ b/sermant-agentcore/sermant-agentcore-config/config/plugins.yaml @@ -17,6 +17,7 @@ plugins: - service-removal - service-visibility - tag-transmission + - database-write-prohibition # dynamicPlugins用于配置支持动态安装的插件, agentmain启动时生效, 允许卸载: # 1. active类型插件将会主动启用 # 2. passive类型插件需通过指令或接口调用启用 diff --git a/sermant-plugins/pom.xml b/sermant-plugins/pom.xml index b74cfcbef1..7491370331 100644 --- a/sermant-plugins/pom.xml +++ b/sermant-plugins/pom.xml @@ -42,6 +42,7 @@ sermant-service-removal sermant-spring-beans-deal sermant-tag-transmission + sermant-database-write-prohibition @@ -74,6 +75,7 @@ sermant-service-removal sermant-spring-beans-deal sermant-tag-transmission + sermant-database-write-prohibition @@ -106,6 +108,7 @@ sermant-service-removal sermant-spring-beans-deal sermant-tag-transmission + sermant-database-write-prohibition diff --git a/sermant-plugins/sermant-database-write-prohibition/database-controller/pom.xml b/sermant-plugins/sermant-database-write-prohibition/database-controller/pom.xml new file mode 100644 index 0000000000..56b9432de9 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/pom.xml @@ -0,0 +1,27 @@ + + + + sermant-database-write-prohibition + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + database-controller + + + 8 + 8 + + + + + com.huaweicloud.sermant + sermant-agentcore-core + provided + + + + \ No newline at end of file diff --git a/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/config/DatabaseWriteProhibitionConfig.java b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/config/DatabaseWriteProhibitionConfig.java new file mode 100644 index 0000000000..c59d7d4cda --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/config/DatabaseWriteProhibitionConfig.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.database.config; + +import java.util.HashSet; +import java.util.Set; + +/** + * 数据库禁写插件配置类 + * + * @author daizhenyu + * @since 2024-01-15 + **/ +public class DatabaseWriteProhibitionConfig { + /** + * 是否开启禁写 + */ + private boolean enableDatabaseWriteProhibition = false; + + /** + * 需要禁写的数据库 + */ + private Set databases = new HashSet<>(); + + public boolean isEnableDatabaseWriteProhibition() { + return enableDatabaseWriteProhibition; + } + + public void setEnableDatabaseWriteProhibition(boolean enableDatabaseWriteProhibition) { + this.enableDatabaseWriteProhibition = enableDatabaseWriteProhibition; + } + + /** + * 获取禁消费的数据库列表 + * + * @return 数据库列表 + */ + public Set getDatabases() { + return databases; + } + + public void setDatabases(Set databases) { + this.databases = databases; + } + + @Override + public String toString() { + return "enableDatabaseWriteProhibition=" + enableDatabaseWriteProhibition + ", databases=" + databases; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/config/DatabaseWriteProhibitionManager.java b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/config/DatabaseWriteProhibitionManager.java new file mode 100644 index 0000000000..8ab9f9963a --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/config/DatabaseWriteProhibitionManager.java @@ -0,0 +1,105 @@ +/* + * 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.config; + +import java.util.Collections; +import java.util.Set; + +/** + * 数据库禁写配置管理类 + * + * @author daizhenyu + * @since 2024-01-22 + */ +public class DatabaseWriteProhibitionManager { + private static DatabaseWriteProhibitionConfig globalConfig = new DatabaseWriteProhibitionConfig(); + + private static DatabaseWriteProhibitionConfig localConfig = new DatabaseWriteProhibitionConfig(); + + private DatabaseWriteProhibitionManager() { + } + + /** + * 获取要禁止消费的数据库集合 + * + * @return 禁止消费的数据库集合 + */ + public static Set getProhibitionDatabases() { + if (globalConfig.isEnableDatabaseWriteProhibition()) { + return globalConfig.getDatabases(); + } + if (localConfig.isEnableDatabaseWriteProhibition()) { + return localConfig.getDatabases(); + } + return Collections.EMPTY_SET; + } + + /** + * 获取全局配置 + * + * @return 全局配置 + */ + public static DatabaseWriteProhibitionConfig getGlobalConfig() { + return globalConfig; + } + + /** + * 获取局部配置 + * + * @return 局部配置 + */ + public static DatabaseWriteProhibitionConfig getLocalConfig() { + return localConfig; + } + + /** + * 更新全局配置 + * + * @param config 禁止消费配置 + */ + public static void updateGlobalConfig(DatabaseWriteProhibitionConfig config) { + if (config == null) { + globalConfig = new DatabaseWriteProhibitionConfig(); + return; + } + globalConfig = config; + } + + /** + * 更新局部配置 + * + * @param config 禁止消费配置 + */ + public static void updateLocalConfig(DatabaseWriteProhibitionConfig config) { + if (config == null) { + localConfig = new DatabaseWriteProhibitionConfig(); + return; + } + localConfig = config; + } + + /** + * 打印配置信息 + * + * @return 配置信息 + */ + public static String printConfig() { + return "Global WriteProhibitionConfig: " + globalConfig.toString() + "; Local WriteProhibitionConfig: " + + localConfig.toString(); + } +} 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 new file mode 100644 index 0000000000..bfa0fd5abd --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/controller/DatabaseController.java @@ -0,0 +1,46 @@ +/* + * 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.controller; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; + +import java.sql.SQLException; + +/** + * 数据库控制器 + * + * @author daizhenyu + * @since 2024-01-15 + **/ +public class DatabaseController { + private static Object result = new Object(); + + private DatabaseController() { + } + + /** + * 获取需要禁写的数据库清单 + * + * @param database 数据库名称 + * @param context 拦截点上下文对象 + * @return + */ + public static void disableDatabaseWriteOperation(String database, ExecuteContext context) { + context.setThrowableOut(new SQLException("Database prohibit to write, database: " + database)); + context.skip(result); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/handler/DatabaseHandler.java b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/handler/DatabaseHandler.java new file mode 100644 index 0000000000..72546ea269 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/handler/DatabaseHandler.java @@ -0,0 +1,48 @@ +/* + * 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.handler; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; + +/** + * 数据库禁写处理接口 + * + * @author daizhenyu + * @since 2024-01-15 + **/ +public interface DatabaseHandler { + /** + * 拦截点前置处理 + * + * @param context 上下文信息 + */ + void doBefore(ExecuteContext context); + + /** + * 拦截点后置处理 + * + * @param context 上下文信息 + */ + void doAfter(ExecuteContext context); + + /** + * 拦截点异常处理 + * + * @param context 上下文信息 + */ + void doOnThrow(ExecuteContext context); +} 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 new file mode 100644 index 0000000000..dc03e3ca41 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/database-controller/src/main/java/com/huaweicloud/sermant/database/interceptor/AbstractDatabaseInterceptor.java @@ -0,0 +1,66 @@ +/* + * 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.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor; +import com.huaweicloud.sermant.database.handler.DatabaseHandler; + +/** + * mongodb抽象interceptor + * + * @author daizhenyu + * @since 2024-01-22 + **/ +public abstract class AbstractDatabaseInterceptor extends AbstractInterceptor { + protected DatabaseHandler handler; + + @Override + public ExecuteContext before(ExecuteContext context) throws Exception { + if (handler != null) { + handler.doBefore(context); + return context; + } + return doBefore(context); + } + + @Override + public ExecuteContext after(ExecuteContext context) throws Exception { + if (handler != null) { + handler.doAfter(context); + return context; + } + return context; + } + + @Override + public ExecuteContext onThrow(ExecuteContext context) throws Exception { + if (handler != null) { + handler.doOnThrow(context); + return context; + } + return context; + } + + /** + * 方法执行前 + * + * @param context 上下文 + * @return ExecuteContext 上下文 + */ + protected abstract ExecuteContext doBefore(ExecuteContext context); +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/pom.xml b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/pom.xml new file mode 100644 index 0000000000..ecaedd445f --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/pom.xml @@ -0,0 +1,59 @@ + + + + + sermant-database-write-prohibition + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + mongodb-3.x-4.x-plugin + + + 8 + 8 + false + plugin + 4.3.4 + + + + + com.huaweicloud.sermant + sermant-agentcore-core + provided + + + org.mongodb + mongodb-driver-sync + ${mongodb.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/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/declarers/CommandOperationHelperDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/declarers/CommandOperationHelperDeclarer.java new file mode 100644 index 0000000000..8701d8f9f1 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/declarers/CommandOperationHelperDeclarer.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.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.mongodb.utils.MongoDbEnhancementHelper; + +/** + * mongodb写操作增强声明器 + * + * @author daizhenyu + * @since 2024-01-16 + **/ +public class CommandOperationHelperDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return MongoDbEnhancementHelper.getCommandOperationHelperClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return MongoDbEnhancementHelper.getCommandOperationHelperInterceptDeclarers(); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/declarers/MixedBulkWriteOperationDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/declarers/MixedBulkWriteOperationDeclarer.java new file mode 100644 index 0000000000..1fdb92f596 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/declarers/MixedBulkWriteOperationDeclarer.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.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.mongodb.utils.MongoDbEnhancementHelper; + +/** + * MixedBulkWriteOperation类增强声明器 + * + * @author daizhenyu + * @since 2024-01-16 + **/ +public class MixedBulkWriteOperationDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return MongoDbEnhancementHelper.getMixedBulkWriteOperationClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return MongoDbEnhancementHelper.getMixedBulkWriteOperationInterceptDeclarers(); + } +} 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 new file mode 100644 index 0000000000..28028e5a5c --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteCommandInterceptor.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.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.handler.DatabaseHandler; +import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor; + +/** + * 执行同步和异步write操作的拦截器 + * + * @author daizhenyu + * @since 2024-01-18 + **/ +public class ExecuteCommandInterceptor extends AbstractDatabaseInterceptor { + /** + * 无参构造方法 + */ + public ExecuteCommandInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public ExecuteCommandInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + public ExecuteContext doBefore(ExecuteContext context) { + String database = (String) context.getArguments()[0]; + if (DatabaseWriteProhibitionManager.getProhibitionDatabases().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/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 new file mode 100644 index 0000000000..12179ffc32 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/ExecuteRetryableCommandInterceptor.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.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.handler.DatabaseHandler; +import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor; + +/** + * 执行重试write操作的拦截器 + * + * @author daizhenyu + * @since 2024-01-18 + **/ +public class ExecuteRetryableCommandInterceptor extends AbstractDatabaseInterceptor { + /** + * 无参构造方法 + */ + public ExecuteRetryableCommandInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public ExecuteRetryableCommandInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + public ExecuteContext doBefore(ExecuteContext context) { + String database = (String) context.getArguments()[1]; + if (DatabaseWriteProhibitionManager.getProhibitionDatabases().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/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 new file mode 100644 index 0000000000..711cf40f1c --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/interceptors/MixedBulkWriteOperationInterceptor.java @@ -0,0 +1,57 @@ +/* + * 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.handler.DatabaseHandler; +import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor; + +import com.mongodb.internal.operation.MixedBulkWriteOperation; + +/** + * MixedBulkWriteOperation类拦截声明器 + * + * @author daizhenyu + * @since 2024-01-16 + **/ +public class MixedBulkWriteOperationInterceptor extends AbstractDatabaseInterceptor { + /** + * 无参构造方法 + */ + public MixedBulkWriteOperationInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public MixedBulkWriteOperationInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + public ExecuteContext doBefore(ExecuteContext context) { + String database = ((MixedBulkWriteOperation) context.getObject()).getNamespace().getDatabaseName(); + if (DatabaseWriteProhibitionManager.getProhibitionDatabases().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/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 new file mode 100644 index 0000000000..fc14be7a63 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/java/com/huaweicloud/sermant/mongodb/utils/MongoDbEnhancementHelper.java @@ -0,0 +1,295 @@ +/* + * 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.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.mongodb.interceptors.ExecuteCommandInterceptor; +import com.huaweicloud.sermant.mongodb.interceptors.ExecuteRetryableCommandInterceptor; +import com.huaweicloud.sermant.mongodb.interceptors.MixedBulkWriteOperationInterceptor; + +import com.mongodb.ReadPreference; +import com.mongodb.internal.binding.ConnectionSource; +import com.mongodb.internal.connection.Connection; + +import org.bson.BsonDocument; +import org.bson.FieldNameValidator; +import org.bson.codecs.Decoder; + +/** + * mongo拦截点辅助类 + * + * @author daizhenyu + * @since 2024-01-16 + **/ +public class MongoDbEnhancementHelper { + private static final String MIXED_BULK_WRITE_CLASS = "com.mongodb.internal.operation.MixedBulkWriteOperation"; + + private static final String COMMAND_OPERATION_CLASS = "com.mongodb.internal.operation.CommandOperationHelper"; + + 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"; + + private static final String EXECUTE_RETRYABLE_COMMAND_METHOD_NAME = "executeRetryableCommand"; + + private static final int METHOD_PARAM_COUNT = 9; + + private static final Class[] EXECUTE_COMMAND_PARAMS_TYPE = { + String.class, + BsonDocument.class, + FieldNameValidator.class, + Decoder.class, + ConnectionSource.class, + Connection.class, + ReadPreference.class + }; + + private static final String[] EXECUTE_RETRY_COMMAND_PARAMS_TYPE = { + "com.mongodb.internal.binding.WriteBinding", + "java.lang.String", + "com.mongodb.ReadPreference", + "org.bson.FieldNameValidator", + "org.bson.codecs.Decoder", + "com.mongodb.internal.operation.CommandOperationHelper.CommandCreator", + "com.mongodb.internal.operation.CommandOperationHelper.CommandWriteTransformer", + "com.mongodb.Function" + }; + + private static final String[] EXECUTE_RETRY_COMMAND_ASYNC_PARAMS_TYPE = { + "com.mongodb.internal.binding.AsyncWriteBinding", + "java.lang.String", + "com.mongodb.ReadPreference", + "org.bson.FieldNameValidator", + "org.bson.codecs.Decoder", + "com.mongodb.internal.operation.CommandOperationHelper.CommandCreator", + "com.mongodb.internal.operation.CommandOperationHelper.CommandWriteTransformerAsync", + "com.mongodb.Function", + "com.mongodb.internal.async.SingleResultCallback" + }; + + private MongoDbEnhancementHelper() { + } + + /** + * 获取CommandOperationHelper类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getCommandOperationHelperClassMatcher() { + return ClassMatcher.nameEquals(COMMAND_OPERATION_CLASS); + } + + /** + * 获取MixedBulkWriteOperation类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getMixedBulkWriteOperationClassMatcher() { + return ClassMatcher.nameEquals(MIXED_BULK_WRITE_CLASS); + } + + /** + * 获取MixedBulkWriteOperation写操作无参拦截器数组 + * + * @return InterceptDeclarer[] MixedBulkWriteOperation写操作无参拦截器数组 + */ + public static InterceptDeclarer[] getMixedBulkWriteOperationInterceptDeclarers() { + MixedBulkWriteOperationInterceptor mixedBulkWriteOperationInterceptor = + new MixedBulkWriteOperationInterceptor(); + return new InterceptDeclarer[]{ + InterceptDeclarer.build(getExecuteMethodMatcher(), mixedBulkWriteOperationInterceptor), + InterceptDeclarer.build(getExecuteAsyncMethodMatcher(), mixedBulkWriteOperationInterceptor) + }; + } + + /** + * 获取MixedBulkWriteOperation execute方法无参拦截器 + * + * @return InterceptDeclarer MixedBulkWriteOperation execute方法无参拦截器 + */ + public static InterceptDeclarer getExecuteInterceptDeclarer() { + return InterceptDeclarer.build(getExecuteMethodMatcher(), + new MixedBulkWriteOperationInterceptor()); + } + + /** + * 获取MixedBulkWriteOperation execute方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer MixedBulkWriteOperation execute方法有参拦截器 + */ + public static InterceptDeclarer getExecuteInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getExecuteMethodMatcher(), + new MixedBulkWriteOperationInterceptor(handler)); + } + + /** + * 获取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写操作无参拦截器 + * + * @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(getExecuteRetryableCommandMethodMatcher(), + new ExecuteRetryableCommandInterceptor()) + }; + } + + /** + * 获取CommandOperationHelper executeCommand方法无参拦截器 + * + * @return InterceptDeclarer CommandOperationHelper executeCommand方法无参拦截器 + */ + public static InterceptDeclarer getExecuteCommandInterceptDeclarer() { + return InterceptDeclarer.build(getExecuteCommandMethodMatcher(), new ExecuteCommandInterceptor()); + } + + /** + * 获取CommandOperationHelper executeCommand方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer CommandOperationHelper executeCommand方法有参拦截器 + */ + public static InterceptDeclarer getExecuteCommandInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getExecuteCommandMethodMatcher(), new ExecuteCommandInterceptor(handler)); + } + + /** + * 获取CommandOperationHelper executeWriteCommand方法无参拦截器 + * + * @return InterceptDeclarer CommandOperationHelper executeWriteCommand方法无参拦截器 + */ + public static InterceptDeclarer getExecuteWriteCommandInterceptDeclarer() { + return InterceptDeclarer.build(getExecuteWriteCommandMethodMatcher(), new ExecuteCommandInterceptor()); + } + + /** + * 获取CommandOperationHelper executeWriteCommand方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer CommandOperationHelper executeWriteCommand方法有参拦截器 + */ + 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)); + } + + /** + * 获取CommandOperationHelper executeRetryableCommand方法无参拦截器 + * + * @return InterceptDeclarer CommandOperationHelper executeRetryableCommand方法无参拦截器 + */ + public static InterceptDeclarer getExecuteRetryableCommandInterceptDeclarer() { + return InterceptDeclarer + .build(getExecuteRetryableCommandMethodMatcher(), new ExecuteRetryableCommandInterceptor()); + } + + /** + * 获取CommandOperationHelper executeRetryableCommand方法有参拦截器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer CommandOperationHelper executeRetryableCommand方法有参拦截器 + */ + public static InterceptDeclarer getExecuteRetryableCommandInterceptDeclarer( + DatabaseHandler handler) { + return InterceptDeclarer + .build(getExecuteRetryableCommandMethodMatcher(), new ExecuteRetryableCommandInterceptor(handler)); + } + + 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)); + } + + private static MethodMatcher getExecuteWriteCommandMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_WRITE_COMMAND_METHOD_NAME) + .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))); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer new file mode 100644 index 0000000000..4dd727257e --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/mongodb-3.x-4.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.mongodb.declarers.MixedBulkWriteOperationDeclarer +com.huaweicloud.sermant.mongodb.declarers.CommandOperationHelperDeclarer \ 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 new file mode 100644 index 0000000000..053aca2eeb --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/pom.xml @@ -0,0 +1,49 @@ + + + + sermant-plugins + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + sermant-database-write-prohibition + pom + + + 8 + 8 + ${pom.basedir}/../../.. + database-write-prohibition + + + + + agent + + true + + + database-controller + mongodb-3.x-4.x-plugin + + + + test + + database-controller + mongodb-3.x-4.x-plugin + + + + release + + database-controller + mongodb-3.x-4.x-plugin + + + + + \ No newline at end of file