Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add database write prohibition function implementation for postgresql and openGauss #1447

Merged
merged 1 commit into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@

import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext;
import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor;
import com.huaweicloud.sermant.database.controller.DatabaseController;
import com.huaweicloud.sermant.database.entity.DatabaseInfo;
import com.huaweicloud.sermant.database.handler.DatabaseHandler;
import com.huaweicloud.sermant.database.utils.SqlParserUtils;

import java.util.Set;

/**
* 数据库抽象interceptor
Expand Down Expand Up @@ -90,4 +94,19 @@ public ExecuteContext onThrow(ExecuteContext context) throws Exception {
protected DatabaseInfo getDataBaseInfo(ExecuteContext context) {
return (DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO);
}

/**
* 如果当前数据库开启禁写,并且为写操作,则执行禁写逻辑处理,
*
* @param sql 执行的SQL
* @param databaseName 执行SQL的数据库名称
* @param prohibitionDatabases 禁写的数据库集合
* @param context 上下文信息
*/
protected void handleWriteOperationIfWriteDisabled(String sql, String databaseName,
Set<String> prohibitionDatabases, ExecuteContext context) {
if (prohibitionDatabases.contains(databaseName) && SqlParserUtils.isWriteOperation(sql)) {
DatabaseController.disableDatabaseWriteOperation(databaseName, context);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sermant-database-write-prohibition</artifactId>
<groupId>com.huaweicloud.sermant</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>opengauss-3.0.x-plugin</artifactId>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<config.skip.flag>false</config.skip.flag>
<package.plugin.type>plugin</package.plugin.type>
<opengauss.version>3.0.0</opengauss.version>
</properties>

<dependencies>
<dependency>
<groupId>com.huaweicloud.sermant</groupId>
<artifactId>sermant-agentcore-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.opengauss</groupId>
<artifactId>opengauss-jdbc</artifactId>
<version>${opengauss.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.huaweicloud.sermant</groupId>
<artifactId>database-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -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 new InterceptDeclarer[]{QueryExecutorImplEnhancementHelper.getSendQueryInterceptDeclarer()};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* 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.common.LoggerFactory;
import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext;
import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager;
import com.huaweicloud.sermant.database.constant.DatabaseType;
import com.huaweicloud.sermant.database.entity.DatabaseInfo;
import com.huaweicloud.sermant.database.handler.DatabaseHandler;
import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor;

import org.opengauss.core.Query;
import org.opengauss.core.v3.QueryExecutorImpl;
import org.opengauss.util.HostSpec;

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 = getDataBaseInfo(context);
String database = databaseInfo.getDatabaseName();
Query query = (Query) context.getArguments()[0];
String sql = query.getNativeSql();
handleWriteOperationIfWriteDisabled(sql, database,
DatabaseWriteProhibitionManager.getOpenGaussProhibitionDatabases(), context);
return context;
}

@Override
protected void createAndCacheDatabaseInfo(ExecuteContext context) {
QueryExecutorImpl queryExecutor = (QueryExecutorImpl) context.getObject();
DatabaseInfo databaseInfo = new DatabaseInfo(DatabaseType.OPENGAUSS);
context.setLocalFieldValue(DATABASE_INFO, databaseInfo);
databaseInfo.setDatabaseName(queryExecutor.getDatabase());
HostSpec hostSpec = queryExecutor.getHostSpec();
if (hostSpec == null) {
LOGGER.info("Unable to obtain the link address of the database.");
return;
}
databaseInfo.setPort(hostSpec.getPort());
databaseInfo.setHostAddress(hostSpec.getHost());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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 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());
}
lilai23 marked this conversation as resolved.
Show resolved Hide resolved

/**
* 获取QueryExecutorImpl类的ClassMatcher
*
* @return ClassMatcher 类匹配器
*/
public static ClassMatcher getQueryExecutorImplClassMatcher() {
return ClassMatcher.nameEquals(ENHANCE_CLASS_NAME);
}
}
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading