diff --git a/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/pom.xml b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/pom.xml new file mode 100644 index 0000000000..5c82b6c391 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/pom.xml @@ -0,0 +1,69 @@ + + + + + sermant-database-write-prohibition + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + opengauss-3.0.x-plugin + + + 8 + 8 + false + plugin + 3.0.0 + + + + + com.huaweicloud.sermant + sermant-agentcore-core + provided + + + org.opengauss + opengauss-jdbc + ${opengauss.version} + provided + + + com.huaweicloud.sermant + database-controller + ${project.version} + + + junit + junit + test + + + org.mockito + mockito-inline + test + + + + + + + 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/opengauss-3.0.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv30/declarers/QueryExecutorImplDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv30/declarers/QueryExecutorImplDeclarer.java new file mode 100644 index 0000000000..9fab9b462e --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv30/declarers/QueryExecutorImplDeclarer.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.opengaussv30.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.opengaussv30.utils.QueryExecutorImplEnhancementHelper; + +/** + * SQL执行器增强声明器 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return QueryExecutorImplEnhancementHelper.getQueryExecutorImplClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return QueryExecutorImplEnhancementHelper.getQueryExecutorImplInterceptDeclarer(); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv30/interceptors/QueryExecutorImplInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv30/interceptors/QueryExecutorImplInterceptor.java new file mode 100644 index 0000000000..cd7e474004 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv30/interceptors/QueryExecutorImplInterceptor.java @@ -0,0 +1,79 @@ +/* + * 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.opengaussv30.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.opengauss.core.Query; +import org.opengauss.core.v3.QueryExecutorImpl; +import org.opengauss.util.HostSpec; + +/** + * 执行SQL操作的拦截器 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplInterceptor extends AbstractDatabaseInterceptor { + /** + * 无参构造方法 + */ + public QueryExecutorImplInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public QueryExecutorImplInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + public ExecuteContext doBefore(ExecuteContext context) { + DatabaseInfo databaseInfo = (DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO); + String database = databaseInfo.getDatabaseName(); + Query query = (Query) context.getArguments()[0]; + String sql = query.getNativeSql(); + if (SqlParserUtils.isWriteOperation(sql) + && DatabaseWriteProhibitionManager.getOpenGaussProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + } + return context; + } + + @Override + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + QueryExecutorImpl queryExecutor = (QueryExecutorImpl) context.getObject(); + DatabaseInfo databaseInfo = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, databaseInfo); + databaseInfo.setDatabaseName(queryExecutor.getDatabase()); + HostSpec hostSpec = queryExecutor.getHostSpec(); + if (hostSpec == null) { + return; + } + databaseInfo.setPort(hostSpec.getPort()); + databaseInfo.setHostAddress(hostSpec.getHost()); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv30/utils/QueryExecutorImplEnhancementHelper.java b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv30/utils/QueryExecutorImplEnhancementHelper.java new file mode 100644 index 0000000000..1b6101554b --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv30/utils/QueryExecutorImplEnhancementHelper.java @@ -0,0 +1,113 @@ +/* + * 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.opengaussv30.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.opengaussv30.interceptors.QueryExecutorImplInterceptor; + +/** + * postgresql拦截点辅助类 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplEnhancementHelper { + private static final String EXECUTE_METHOD_NAME = "sendQuery"; + + private static final String ENHANCE_CLASS_NAME = "org.opengauss.core.v3.QueryExecutorImpl"; + + private static final String INT_CLASS_NAME = "int"; + + private static final String QUERY_CLASS_NAME = "org.opengauss.core.Query"; + + private static final String V3_PARAMETER_LIST_CLASS_NAME = "org.opengauss.core.v3.V3ParameterList"; + + private static final String RESULT_HANDLER_CLASS_NAME = "org.opengauss.core.ResultHandler"; + + private static final String BATCH_RESULT_HANDLER_CLASS_NAME = "org.opengauss.jdbc.BatchResultHandler"; + + private static final String[] EXECUTE_INTERNAL_METHOD_PARAMS_TYPE = { + QUERY_CLASS_NAME, + V3_PARAMETER_LIST_CLASS_NAME, + INT_CLASS_NAME, + INT_CLASS_NAME, + INT_CLASS_NAME, + RESULT_HANDLER_CLASS_NAME, + BATCH_RESULT_HANDLER_CLASS_NAME + }; + + private QueryExecutorImplEnhancementHelper() { + } + + private static MethodMatcher getSendQueryMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_METHOD_NAME) + .and(MethodMatcher.paramTypesEqual(EXECUTE_INTERNAL_METHOD_PARAMS_TYPE)); + } + + /** + * 获取QueryExecutorImpl sendQuery方法有参拦截声明器数组 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer[] QueryExecutorImpl sendQuery方法有参拦截声明器数组 + */ + public static InterceptDeclarer[] getQueryExecutorImplInterceptDeclarer( + DatabaseHandler handler) { + return new InterceptDeclarer[]{InterceptDeclarer.build(getSendQueryMethodMatcher(), + new QueryExecutorImplInterceptor(handler))}; + } + + /** + * 获取QueryExecutorImpl sendQuery方法无参拦截声明器数组 + * + * @return InterceptDeclarer[] QueryExecutorImpl sendQuery方法无参拦截声明器数组 + */ + public static InterceptDeclarer[] getQueryExecutorImplInterceptDeclarer() { + return new InterceptDeclarer[]{InterceptDeclarer.build(getSendQueryMethodMatcher(), + new QueryExecutorImplInterceptor())}; + } + + /** + * 获取QueryExecutorImpl sendQuery方法有参拦截声明器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer QueryExecutorImpl sendQuery方法有参拦截声明器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor(handler)); + } + + /** + * 获取QueryExecutorImpl sendQuery方法无参拦截声明器 + * + * @return InterceptDeclarer QueryExecutorImpl sendQuery方法无参拦截声明器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer() { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor()); + } + + /** + * 获取QueryExecutorImpl类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getQueryExecutorImplClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS_NAME); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer new file mode 100644 index 0000000000..feeedd021f --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.0.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.opengaussv30.declarers.QueryExecutorImplDeclarer \ No newline at end of file diff --git a/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/pom.xml b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/pom.xml new file mode 100644 index 0000000000..722dd8aa1a --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/pom.xml @@ -0,0 +1,69 @@ + + + + + sermant-database-write-prohibition + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + opengauss-3.1.x-plugin + + + 8 + 8 + false + plugin + 3.1.0 + + + + + com.huaweicloud.sermant + sermant-agentcore-core + provided + + + org.opengauss + opengauss-jdbc + ${opengauss.version} + provided + + + com.huaweicloud.sermant + database-controller + ${project.version} + + + junit + junit + test + + + org.mockito + mockito-inline + test + + + + + + + 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/opengauss-3.1.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv31/declarers/QueryExecutorImplDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv31/declarers/QueryExecutorImplDeclarer.java new file mode 100644 index 0000000000..539e9feddb --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv31/declarers/QueryExecutorImplDeclarer.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.opengaussv31.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.opengaussv31.utils.QueryExecutorImplEnhancementHelper; + +/** + * SQL执行器增强声明器 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return QueryExecutorImplEnhancementHelper.getQueryExecutorImplClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return QueryExecutorImplEnhancementHelper.getQueryExecutorImplInterceptDeclarer(); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv31/interceptors/QueryExecutorImplInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv31/interceptors/QueryExecutorImplInterceptor.java new file mode 100644 index 0000000000..b36c491adb --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv31/interceptors/QueryExecutorImplInterceptor.java @@ -0,0 +1,79 @@ +/* + * 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.opengaussv31.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.postgresql.core.Query; +import org.postgresql.core.v3.QueryExecutorImpl; +import org.postgresql.util.HostSpec; + +/** + * 执行SQL操作的拦截器 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplInterceptor extends AbstractDatabaseInterceptor { + /** + * 无参构造方法 + */ + public QueryExecutorImplInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public QueryExecutorImplInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + public ExecuteContext doBefore(ExecuteContext context) { + DatabaseInfo databaseInfo = (DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO); + String database = databaseInfo.getDatabaseName(); + Query query = (Query) context.getArguments()[0]; + String sql = query.getNativeSql(); + if (SqlParserUtils.isWriteOperation(sql) + && DatabaseWriteProhibitionManager.getOpenGaussProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + } + return context; + } + + @Override + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + QueryExecutorImpl queryExecutor = (QueryExecutorImpl) context.getObject(); + DatabaseInfo databaseInfo = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, databaseInfo); + databaseInfo.setDatabaseName(queryExecutor.getDatabase()); + HostSpec hostSpec = queryExecutor.getHostSpec(); + if (hostSpec == null) { + return; + } + databaseInfo.setPort(hostSpec.getPort()); + databaseInfo.setHostAddress(hostSpec.getHost()); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv31/utils/QueryExecutorImplEnhancementHelper.java b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv31/utils/QueryExecutorImplEnhancementHelper.java new file mode 100644 index 0000000000..67e3eb5d54 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/java/com/huaweicloud/sermant/opengaussv31/utils/QueryExecutorImplEnhancementHelper.java @@ -0,0 +1,113 @@ +/* + * 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.opengaussv31.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.opengaussv31.interceptors.QueryExecutorImplInterceptor; + +/** + * openGauss3.1.x拦截点辅助类 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplEnhancementHelper { + private static final String EXECUTE_METHOD_NAME = "sendQuery"; + + private static final String ENHANCE_CLASS_NAME = "org.postgresql.core.v3.QueryExecutorImpl"; + + private static final String INT_CLASS_NAME = "int"; + + private static final String QUERY_CLASS_NAME = "org.postgresql.core.Query"; + + private static final String V3_PARAMETER_LIST_CLASS_NAME = "org.postgresql.core.v3.V3ParameterList"; + + private static final String RESULT_HANDLER_CLASS_NAME = "org.postgresql.core.ResultHandler"; + + private static final String BATCH_RESULT_HANDLER_CLASS_NAME = "org.postgresql.jdbc.BatchResultHandler"; + + private static final String[] EXECUTE_INTERNAL_METHOD_PARAMS_TYPE = { + QUERY_CLASS_NAME, + V3_PARAMETER_LIST_CLASS_NAME, + INT_CLASS_NAME, + INT_CLASS_NAME, + INT_CLASS_NAME, + RESULT_HANDLER_CLASS_NAME, + BATCH_RESULT_HANDLER_CLASS_NAME + }; + + private QueryExecutorImplEnhancementHelper() { + } + + private static MethodMatcher getSendQueryMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_METHOD_NAME) + .and(MethodMatcher.paramTypesEqual(EXECUTE_INTERNAL_METHOD_PARAMS_TYPE)); + } + + /** + * 获取QueryExecutorImpl sendQuery方法有参拦截声明器数组 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer[] QueryExecutorImpl sendQuery方法有参拦截声明器数组 + */ + public static InterceptDeclarer[] getQueryExecutorImplInterceptDeclarer( + DatabaseHandler handler) { + return new InterceptDeclarer[]{InterceptDeclarer.build(getSendQueryMethodMatcher(), + new QueryExecutorImplInterceptor(handler))}; + } + + /** + * 获取QueryExecutorImpl sendQuery方法无参拦截声明器数组 + * + * @return InterceptDeclarer[] QueryExecutorImpl sendQuery方法无参拦截声明器数组 + */ + public static InterceptDeclarer[] getQueryExecutorImplInterceptDeclarer() { + return new InterceptDeclarer[]{InterceptDeclarer.build(getSendQueryMethodMatcher(), + new QueryExecutorImplInterceptor())}; + } + + /** + * 获取QueryExecutorImpl sendQuery方法有参拦截声明器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer QueryExecutorImpl sendQuery方法有参拦截声明器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor(handler)); + } + + /** + * 获取QueryExecutorImpl sendQuery方法无参拦截声明器 + * + * @return InterceptDeclarer QueryExecutorImpl sendQuery方法无参拦截声明器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer() { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor()); + } + + /** + * 获取QueryExecutorImpl类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getQueryExecutorImplClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS_NAME); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer new file mode 100644 index 0000000000..dc00a74fe5 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/opengauss-3.1.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.opengaussv31.declarers.QueryExecutorImplDeclarer \ 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 72fcce2b65..b235ba4363 100644 --- a/sermant-plugins/sermant-database-write-prohibition/pom.xml +++ b/sermant-plugins/sermant-database-write-prohibition/pom.xml @@ -31,6 +31,10 @@ mongodb-3.x-4.x-plugin mysql-mariadb-2.x-plugin mysql-mariadb-3.x-plugin + opengauss-3.0.x-plugin + opengauss-3.1.x-plugin + postgresql-9.4.x-plugin + postgresql-42.x-plugin @@ -41,6 +45,10 @@ mongodb-3.x-4.x-plugin mysql-mariadb-2.x-plugin mysql-mariadb-3.x-plugin + opengauss-3.0.x-plugin + opengauss-3.1.x-plugin + postgresql-9.4.x-plugin + postgresql-42.x-plugin @@ -51,6 +59,10 @@ mongodb-3.x-4.x-plugin mysql-mariadb-2.x-plugin mysql-mariadb-3.x-plugin + opengauss-3.0.x-plugin + opengauss-3.1.x-plugin + postgresql-9.4.x-plugin + postgresql-42.x-plugin diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/pom.xml b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/pom.xml new file mode 100644 index 0000000000..11c6ba7c17 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/pom.xml @@ -0,0 +1,69 @@ + + + + + sermant-database-write-prohibition + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + postgresql-42.x-plugin + + + 8 + 8 + false + plugin + 42.0.0 + + + + + com.huaweicloud.sermant + sermant-agentcore-core + provided + + + org.postgresql + postgresql + ${postgresql.version} + provided + + + com.huaweicloud.sermant + database-controller + ${project.version} + + + junit + junit + test + + + org.mockito + mockito-inline + test + + + + + + + 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/postgresql-42.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv42/declarers/QueryExecutorImplDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv42/declarers/QueryExecutorImplDeclarer.java new file mode 100644 index 0000000000..1cccb860e8 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv42/declarers/QueryExecutorImplDeclarer.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.postgresqlv42.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.postgresqlv42.utils.QueryExecutorImplEnhancementHelper; + +/** + * SQL执行器增强声明器 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return QueryExecutorImplEnhancementHelper.getQueryExecutorImplClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return QueryExecutorImplEnhancementHelper.getQueryExecutorImplInterceptDeclarer(); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv42/interceptors/QueryExecutorImplInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv42/interceptors/QueryExecutorImplInterceptor.java new file mode 100644 index 0000000000..8309f6395c --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv42/interceptors/QueryExecutorImplInterceptor.java @@ -0,0 +1,79 @@ +/* + * 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.postgresqlv42.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.postgresql.core.Query; +import org.postgresql.core.v3.QueryExecutorImpl; +import org.postgresql.util.HostSpec; + +/** + * 执行SQL操作拦截器的测试类 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplInterceptor extends AbstractDatabaseInterceptor { + /** + * 无参构造方法 + */ + public QueryExecutorImplInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public QueryExecutorImplInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + public ExecuteContext doBefore(ExecuteContext context) { + DatabaseInfo databaseInfo = (DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO); + String database = databaseInfo.getDatabaseName(); + Query query = (Query) context.getArguments()[0]; + String sql = query.toString(); + if (SqlParserUtils.isWriteOperation(sql) + && DatabaseWriteProhibitionManager.getPostgreSqlProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + } + return context; + } + + @Override + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + QueryExecutorImpl queryExecutor = (QueryExecutorImpl) context.getObject(); + DatabaseInfo databaseInfo = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, databaseInfo); + databaseInfo.setDatabaseName(queryExecutor.getDatabase()); + HostSpec hostSpec = queryExecutor.getHostSpec(); + if (hostSpec == null) { + return; + } + databaseInfo.setHostAddress(hostSpec.getHost()); + databaseInfo.setPort(hostSpec.getPort()); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv42/utils/QueryExecutorImplEnhancementHelper.java b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv42/utils/QueryExecutorImplEnhancementHelper.java new file mode 100644 index 0000000000..ed35390329 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv42/utils/QueryExecutorImplEnhancementHelper.java @@ -0,0 +1,125 @@ +/* + * 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.postgresqlv42.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.postgresqlv42.interceptors.QueryExecutorImplInterceptor; + +/** + * postgresql拦截点辅助类 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplEnhancementHelper { + private static final String EXECUTE_METHOD_NAME = "sendQuery"; + + private static final String ENHANCE_CLASS_NAME = "org.postgresql.core.v3.QueryExecutorImpl"; + + private static final String INT_CLASS_NAME = "int"; + + private static final String QUERY_CLASS_NAME = "org.postgresql.core.Query"; + + private static final String V3_PARAMETER_LIST_CLASS_NAME = "org.postgresql.core.v3.V3ParameterList"; + + private static final String RESULT_HANDLER_CLASS_NAME = "org.postgresql.core.ResultHandler"; + + private static final String BATCH_RESULT_HANDLER_CLASS_NAME = "org.postgresql.jdbc.BatchResultHandler"; + + private static final String[] EXECUTE_INTERNAL_METHOD_PARAMS_TYPE_V1 = { + QUERY_CLASS_NAME, + V3_PARAMETER_LIST_CLASS_NAME, + INT_CLASS_NAME, INT_CLASS_NAME, + INT_CLASS_NAME, + RESULT_HANDLER_CLASS_NAME, + BATCH_RESULT_HANDLER_CLASS_NAME + }; + + private static final String BOOLEAN_CLASS_NAME = "boolean"; + + private static final String[] EXECUTE_INTERNAL_METHOD_PARAMS_TYPE_V2 = { + QUERY_CLASS_NAME, + V3_PARAMETER_LIST_CLASS_NAME, + INT_CLASS_NAME, INT_CLASS_NAME, + INT_CLASS_NAME, + RESULT_HANDLER_CLASS_NAME, + BATCH_RESULT_HANDLER_CLASS_NAME, + BOOLEAN_CLASS_NAME + }; + + private QueryExecutorImplEnhancementHelper() { + } + + private static MethodMatcher getSendQueryMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_METHOD_NAME) + .and(MethodMatcher.paramTypesEqual(EXECUTE_INTERNAL_METHOD_PARAMS_TYPE_V1) + .or(MethodMatcher.paramTypesEqual(EXECUTE_INTERNAL_METHOD_PARAMS_TYPE_V2))); + } + + /** + * 获取QueryExecutorImpl sendQuery方法有参拦截声明器数组 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer[] QueryExecutorImpl sendQuery方法有参拦截声明器数组 + */ + public static InterceptDeclarer[] getQueryExecutorImplInterceptDeclarer( + DatabaseHandler handler) { + return new InterceptDeclarer[]{InterceptDeclarer.build(getSendQueryMethodMatcher(), + new QueryExecutorImplInterceptor(handler))}; + } + + /** + * 获取QueryExecutorImpl sendQuery方法无参拦截声明器数组 + * + * @return InterceptDeclarer[] QueryExecutorImpl sendQuery方法无参拦截声明器数组 + */ + public static InterceptDeclarer[] getQueryExecutorImplInterceptDeclarer() { + return new InterceptDeclarer[]{InterceptDeclarer.build(getSendQueryMethodMatcher(), + new QueryExecutorImplInterceptor())}; + } + + /** + * 获取QueryExecutorImpl sendQuery方法有参拦截声明器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer QueryExecutorImpl sendQuery方法有参拦截声明器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor(handler)); + } + + /** + * 获取QueryExecutorImpl sendQuery方法无参拦截声明器 + * + * @return InterceptDeclarer QueryExecutorImpl sendQuery方法无参拦截声明器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer() { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor()); + } + + /** + * 获取QueryExecutorImpl类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getQueryExecutorImplClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS_NAME); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer new file mode 100644 index 0000000000..0fc527b5c5 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-42.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.postgresqlv42.declarers.QueryExecutorImplDeclarer \ No newline at end of file diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/pom.xml b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/pom.xml new file mode 100644 index 0000000000..69202abbcc --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/pom.xml @@ -0,0 +1,69 @@ + + + + + sermant-database-write-prohibition + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + postgresql-9.4.x-plugin + + + 8 + 8 + false + plugin + 9.4-1200-jdbc4 + + + + + com.huaweicloud.sermant + sermant-agentcore-core + provided + + + org.postgresql + postgresql + ${postgresql.version} + provided + + + com.huaweicloud.sermant + database-controller + ${project.version} + + + junit + junit + test + + + org.mockito + mockito-inline + test + + + + + + + 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/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/declarers/Jdbc4StatementDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/declarers/Jdbc4StatementDeclarer.java new file mode 100644 index 0000000000..db098bd60e --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/declarers/Jdbc4StatementDeclarer.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.postgresqlv9.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.postgresqlv9.utils.PostgresqlEnhancementHelper; + +/** + * SQL执行器增强声明器 + * + * @author zhp + * @since 2024-02-04 + **/ +public class Jdbc4StatementDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return PostgresqlEnhancementHelper.getJdbc4StatementClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return PostgresqlEnhancementHelper.getJdbc4StatementInterceptDeclarer(); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/declarers/QueryExecutorImplDeclarer.java b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/declarers/QueryExecutorImplDeclarer.java new file mode 100644 index 0000000000..d5b9adf2b1 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/declarers/QueryExecutorImplDeclarer.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.postgresqlv9.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.postgresqlv9.utils.PostgresqlEnhancementHelper; + +/** + * SQL执行器增强声明器 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + return PostgresqlEnhancementHelper.getQueryExecutorImplClassMatcher(); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return PostgresqlEnhancementHelper.getQueryExecutorImplInterceptDeclarer(); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/interceptors/Jdbc4StatementInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/interceptors/Jdbc4StatementInterceptor.java new file mode 100644 index 0000000000..c82fb32f82 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/interceptors/Jdbc4StatementInterceptor.java @@ -0,0 +1,85 @@ +/* + * 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.postgresqlv9.interceptors; + +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; +import com.huaweicloud.sermant.postgresqlv9.utils.ThreadConnectionUtil; + +import org.postgresql.jdbc3g.AbstractJdbc3gStatement; + +/** + * 执行SQL操作的拦截器 + * + * @author zhp + * @since 2024-02-04 + **/ +public class Jdbc4StatementInterceptor extends AbstractInterceptor { + /** + * 自定义数据库处理handle + */ + protected DatabaseHandler handler; + + /** + * 无参构造方法 + */ + public Jdbc4StatementInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public Jdbc4StatementInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + public ExecuteContext before(ExecuteContext context) { + if (handler != null) { + handler.doBefore(context); + return context; + } + AbstractJdbc3gStatement statement = (AbstractJdbc3gStatement) context.getObject(); + + // 存放链接信息,保证QueryExecutorImplInterceptor可以获取到数据库信息 + ThreadConnectionUtil.setConnection(statement.getPGConnection()); + return context; + } + + @Override + public ExecuteContext after(ExecuteContext context) throws Exception { + if (handler != null) { + handler.doAfter(context); + return context; + } + ThreadConnectionUtil.removeConnection(); + return context; + } + + @Override + public ExecuteContext onThrow(ExecuteContext context) throws Exception { + if (handler != null) { + handler.doOnThrow(context); + return context; + } + ThreadConnectionUtil.removeConnection(); + return context; + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/interceptors/QueryExecutorImplInterceptor.java b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/interceptors/QueryExecutorImplInterceptor.java new file mode 100644 index 0000000000..f367d4898c --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/interceptors/QueryExecutorImplInterceptor.java @@ -0,0 +1,99 @@ +/* + * 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.postgresqlv9.interceptors; + +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.utils.StringUtils; +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 com.huaweicloud.sermant.postgresqlv9.utils.ThreadConnectionUtil; + +import org.postgresql.Driver; +import org.postgresql.core.Query; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * 执行SQL操作的拦截器 + * + * @author zhp + * @since 2024-02-04 + **/ +public class QueryExecutorImplInterceptor extends AbstractDatabaseInterceptor { + private static final Logger LOGGER = LoggerFactory.getLogger(); + + /** + * 无参构造方法 + */ + public QueryExecutorImplInterceptor() { + } + + /** + * 有参构造方法 + * + * @param handler 写操作处理器 + */ + public QueryExecutorImplInterceptor(DatabaseHandler handler) { + this.handler = handler; + } + + @Override + public ExecuteContext doBefore(ExecuteContext context) { + DatabaseInfo databaseInfo = (DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO); + Query query = (Query) context.getArguments()[0]; + String sql = query.toString(); + String database = databaseInfo.getDatabaseName(); + if (SqlParserUtils.isWriteOperation(sql) + && DatabaseWriteProhibitionManager.getPostgreSqlProhibitionDatabases().contains(database)) { + DatabaseController.disableDatabaseWriteOperation(database, context); + } + return context; + } + + @Override + protected void createAndCacheDatabaseInfo(ExecuteContext context) { + DatabaseInfo databaseInfo = new DatabaseInfo(); + context.setLocalFieldValue(DATABASE_INFO, databaseInfo); + Connection connection = ThreadConnectionUtil.getConnection(); + if (connection == null) { + return; + } + try { + DatabaseMetaData databaseMetaData = connection.getMetaData(); + if (databaseMetaData == null || StringUtils.isEmpty(databaseMetaData.getURL())) { + return; + } + Properties properties = new Properties(); + properties = Driver.parseURL(databaseMetaData.getURL(), properties); + databaseInfo.setHostAddress(properties.getProperty("PGHOST")); + databaseInfo.setPort(Integer.parseInt(properties.getProperty("PGPORT"))); + databaseInfo.setDatabaseName(properties.getProperty("PGDBNAME")); + } catch (SQLException e) { + LOGGER.log(Level.SEVERE, "can not obtain the database information.", e); + } + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/utils/PostgresqlEnhancementHelper.java b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/utils/PostgresqlEnhancementHelper.java new file mode 100644 index 0000000000..c9b2c47b35 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/utils/PostgresqlEnhancementHelper.java @@ -0,0 +1,203 @@ +/* + * 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.postgresqlv9.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.postgresqlv9.interceptors.Jdbc4StatementInterceptor; +import com.huaweicloud.sermant.postgresqlv9.interceptors.QueryExecutorImplInterceptor; + +/** + * postgresql拦截点辅助类 + * + * @author zhp + * @since 2024-02-04 + **/ +public class PostgresqlEnhancementHelper { + private static final String SEND_QUERY_METHOD_NAME = "sendQuery"; + + private static final String QUERY_EXECUTOR_CLASS_NAME = "org.postgresql.core.v3.QueryExecutorImpl"; + + private static final String INT_CLASS_NAME = "int"; + + private static final String QUERY_CLASS_NAME = "org.postgresql.core.Query"; + + private static final String PARAMETER_LIST_CLASS_NAME = "org.postgresql.core.ParameterList"; + + private static final String ERROR_TRACKING_RESULT_HANDLER_CLASS_NAME = + "org.postgresql.core.v3.ErrorTrackingResultHandler"; + + private static final String[] SEND_QUERY_METHOD_PARAMS_TYPE = { + QUERY_CLASS_NAME, + PARAMETER_LIST_CLASS_NAME, + INT_CLASS_NAME, + INT_CLASS_NAME, + INT_CLASS_NAME, + ERROR_TRACKING_RESULT_HANDLER_CLASS_NAME + }; + + private static final String EXECUTE_METHOD_NAME = "execute"; + + private static final String EXECUTE_BATCH_METHOD_NAME = "executeBatch"; + + private static final String STATEMENT_CLASS_NAME = "org.postgresql.jdbc4.Jdbc4Statement"; + + private static final String[] EXECUTE_METHOD_PARAMS_TYPE = { + QUERY_CLASS_NAME, + PARAMETER_LIST_CLASS_NAME, + INT_CLASS_NAME + }; + + private PostgresqlEnhancementHelper() { + } + + private static MethodMatcher getSendQueryMethodMatcher() { + return MethodMatcher.nameEquals(SEND_QUERY_METHOD_NAME) + .and(MethodMatcher.paramTypesEqual(SEND_QUERY_METHOD_PARAMS_TYPE)); + } + + /** + * 获取QueryExecutorImpl sendQuery方法有参拦截声明器数组 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer[] QueryExecutorImpl sendQuery方法有参拦截声明器数组 + */ + public static InterceptDeclarer[] getQueryExecutorImplInterceptDeclarer( + DatabaseHandler handler) { + return new InterceptDeclarer[]{InterceptDeclarer.build(getSendQueryMethodMatcher(), + new QueryExecutorImplInterceptor(handler))}; + } + + /** + * 获取QueryExecutorImpl sendQuery方法无参拦截声明器数组 + * + * @return InterceptDeclarer[] QueryExecutorImpl sendQuery方法无参拦截声明器数组 + */ + public static InterceptDeclarer[] getQueryExecutorImplInterceptDeclarer() { + return new InterceptDeclarer[]{InterceptDeclarer.build(getSendQueryMethodMatcher(), + new QueryExecutorImplInterceptor())}; + } + + /** + * 获取QueryExecutorImpl sendQuery方法有参拦截声明器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer QueryExecutorImpl sendQuery方法有参拦截声明器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor(handler)); + } + + /** + * 获取QueryExecutorImpl sendQuery方法无参拦截声明器 + * + * @return InterceptDeclarer QueryExecutorImpl sendQuery方法无参拦截声明器 + */ + public static InterceptDeclarer getSendQueryInterceptDeclarer() { + return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor()); + } + + /** + * 获取QueryExecutorImpl类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getQueryExecutorImplClassMatcher() { + return ClassMatcher.nameEquals(QUERY_EXECUTOR_CLASS_NAME); + } + + /** + * 获取Jdbc4Statement类的ClassMatcher + * + * @return ClassMatcher 类匹配器 + */ + public static ClassMatcher getJdbc4StatementClassMatcher() { + return ClassMatcher.nameEquals(STATEMENT_CLASS_NAME); + } + + /** + * 获取Jdbc4Statement execute和executeBatch方法有参拦截声明器数组 + * + * @return InterceptDeclarer[] Jdbc4Statement execute和executeBatch方法有参拦截声明器数组 + */ + public static InterceptDeclarer[] getJdbc4StatementInterceptDeclarer() { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(getExecuteMethodMatcher(), new Jdbc4StatementInterceptor()), + InterceptDeclarer.build(getExecuteBatchMethodMatcher(), new Jdbc4StatementInterceptor())}; + } + + /** + * 获取Jdbc4Statement execute和executeBatch方法拦截声明器数组 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer[] Jdbc4Statement execute和executeBatch方法拦截声明器数组 + */ + public static InterceptDeclarer[] getJdbc4StatementInterceptDeclarer(DatabaseHandler handler) { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(getExecuteMethodMatcher(), new Jdbc4StatementInterceptor(handler)), + InterceptDeclarer.build(getExecuteBatchMethodMatcher(), new Jdbc4StatementInterceptor(handler))}; + } + + /** + * 获取Jdbc4Statement execute方法无参拦截声明器 + * + * @return InterceptDeclarer Jdbc4Statement execute方法无参拦截声明器 + */ + public static InterceptDeclarer getExecuteInterceptDeclarer() { + return InterceptDeclarer.build(getExecuteMethodMatcher(), new Jdbc4StatementInterceptor()); + } + + /** + * 获取Jdbc4Statement execute方法有参拦截声明器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer Jdbc4Statement execute方法有参拦截声明器 + */ + public static InterceptDeclarer getExecuteInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getExecuteMethodMatcher(), new Jdbc4StatementInterceptor(handler)); + } + + /** + * 获取Jdbc4Statement executeBatch方法无参拦截声明器 + * + * @return InterceptDeclarer Jdbc4Statement executeBatch方法无参拦截声明器 + */ + public static InterceptDeclarer getExecuteBatchInterceptDeclarer() { + return InterceptDeclarer.build(getExecuteMethodMatcher(), new Jdbc4StatementInterceptor()); + } + + /** + * 获取Jdbc4Statement executeBatch方法有参拦截声明器 + * + * @param handler 数据库自定义处理器 + * @return InterceptDeclarer Jdbc4Statement executeBatch方法有参拦截声明器 + */ + public static InterceptDeclarer getExecuteBatchInterceptDeclarer(DatabaseHandler handler) { + return InterceptDeclarer.build(getExecuteMethodMatcher(), new Jdbc4StatementInterceptor(handler)); + } + + private static MethodMatcher getExecuteMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_METHOD_NAME) + .and(MethodMatcher.paramTypesEqual(EXECUTE_METHOD_PARAMS_TYPE)); + } + + private static MethodMatcher getExecuteBatchMethodMatcher() { + return MethodMatcher.nameEquals(EXECUTE_BATCH_METHOD_NAME); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/utils/ThreadConnectionUtil.java b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/utils/ThreadConnectionUtil.java new file mode 100644 index 0000000000..ac92a2735d --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/java/com/huaweicloud/sermant/postgresqlv9/utils/ThreadConnectionUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023-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.postgresqlv9.utils; + +import java.sql.Connection; + +/** + * 线程工具类,用于线程数据传递 + * + * @author zhp + * @since 2024-02-06 + */ +public class ThreadConnectionUtil { + /** + * 线程变量存储,主要存储链接信息 + */ + private static final ThreadLocal CONNECTION_THREAD_LOCAL = new InheritableThreadLocal<>(); + + /** + * 构造函数 + */ + private ThreadConnectionUtil() { + } + + /** + * 设置链接信息 + * + * @param connection 连接信息 + */ + public static void setConnection(Connection connection) { + CONNECTION_THREAD_LOCAL.set(connection); + } + + /** + * 获取链接信息 + * + * @return 请求开始时间 + */ + public static Connection getConnection() { + return CONNECTION_THREAD_LOCAL.get(); + } + + /** + * 移除链接信息 + */ + public static void removeConnection() { + CONNECTION_THREAD_LOCAL.remove(); + } +} diff --git a/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.4.x-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer new file mode 100644 index 0000000000..f8055a36f1 --- /dev/null +++ b/sermant-plugins/sermant-database-write-prohibition/postgresql-9.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.postgresqlv9.declarers.QueryExecutorImplDeclarer +com.huaweicloud.sermant.postgresqlv9.declarers.Jdbc4StatementDeclarer \ No newline at end of file