开发者
数据保险柜测试验证

数据保险柜测试验证

openGauss机密计算

发表于 2026/05/22

0

数据保险柜测试验证

数据保险柜oGRecorder)是一款数据库日志保护软件。其典型部署场景是运行于virtCCA中,南向对接Dorado Worm存储,北向通过oGRecorderSDK对接数据库,实现对数据库WAL日志的实时同步,形成对用户数据库系统的日志安全保护的软硬一体组合方案。 其中virtCCA基于硬件硬隔离和机密计算能力,为oGRecorder的运行提供隔离于宿主机、REE的安全TEE计算环境;Dorado Worm存储提供Write Once Read Many技术,对数据存储只能新增、禁止删改,实现数据库日志的防篡改保护,防止出现数据库文件、备份数据发生勒索攻击时数据无法恢复;oGRecorder实现类vfs系统支持数据的高效写入和读取,支持和SDK之间安全认证、数据安全写入;而oGRecorderSDK提供完备的文件操作API,供第三方软件调用,进而实现对数据库日志的实时同步、灾备回放。

oGRecorder 7.0.0-RC3版本引入CM-RestAPI组件,支持查询数据保险柜集群信息并执行集群状态控制操作,便于对接外部管控平台,提升集群状态查询与运维控制效率,减少人工操作;通过认证与访问控制机制提升接口调用安全性。

安装部署

oGRecorder安装包生成依赖CBB通用基础模块https://gitcode.com/opengauss/CBB

所以需要环境先编译CBB模块。

openEuler-20.03-LTS arm系统架构为例,优先编译CBB模块

三方库地址:

https://opengauss.obs.cn-south-1.myhuaweicloud.com/latest/binarylibs/gcc10.3/openGauss-third_party_binarylibs_openEuler_arm.tar.gz

git clone https://gitcode.com/opengauss/CBB.git -b development

cd CBB/build/linux/opengauss

sh build.sh -3rd [binarylibs path] -m Release -t cmake

CBB模块编译成功后,编译oGRecorder代码生成安装包

git clone https://gitcode.com/opengauss/oGRecorder.git

cd oGRecorder/build

sh build.sh -3rd [binarylibs path] -m Release -t cmake -pkg

执行成功后会在oGRecorder目录下生成安装包;包名:openGauss-oGRecorder-xxxx.tar.gz

CM-RestAPIJAVA项目开发 ,所以使用时有软件限制,安装包生成需要如下版本要求:

Maven版本要求3.9.9

Java 版本要求 jdk-17

git clone https://gitcode.com/opengauss/CM-RestAPI.git

cd ./CM-RestAPI



sh build.sh

执行成功后会在源码目录下生成对应安装包。

部署参考官方材料:

https://docs.opengauss.org/zh/docs/latest/tool_and_commandreference/ogrecorder/ogrecorder_deployment_guide.html#部署流程

Rest-API 功能验证

本模块是Java项目,可通过借助三方工具postmanlinux工具curl等均可验证体验接口功能;以下介绍curl方式验证。

接口描述参考如下连接描述:

https://docs.opengauss.org/zh/docs/latest/tool_and_commandreference/features.html#支持集群信息查询和推送

api外部访问是需要添加白名单,默认无法外部访问,白名单配置路径:

$GAUSSHOME/bin/restWhiteList 配置如下:

192.168.0.11

192.168.0.12

针对多个Rest-API服务测试我们可以简单通过脚本使用curl工具完成验证:

我们可以使用如上python脚本执行完成接口测试验证。

2:返回结果json

3:返回结果msg中的cms信息

4:返回结果msg中的oGRecorder信息

5:返回结果msg中集群的状态信息

该模块涉及到POST类型接口,可以在如上请求方式指定post类型请求

r' -H "Content-type: application/json" -X POST ' \

           f'"https://server:8443/CMRestAPI/stopRestApi

oGRecorder SDK API功能验证

该模块是黑匣子核心对外暴露读写数据的API,方便数据库日志信息使用当前模块的API保留到黑匣子中,需要恢复数据时,使用当前模块读取正确的信息,回放数据完成数据恢复。接口涵盖了初始化实例、实例管理、配置管理、错误处理、VFS管理、文件操作等模块。接口定义可以参考官方文档:

https://docs.opengauss.org/zh/docs/latest/tool_and_commandreference/ogrecorder/ogrecorder_api_introduction.html#ogrecorder-sdk-api-文档

该模块采用C语言开发,对外接口测试需要C脚本验证;编写如下C脚本:


1.   #include <sys/stat.h>  

2.   #include <fcntl.h>  

3.   #include <unistd.h>  

4.   #include <stdio.h>  

5.   #include <errno.h>  

6.   #include <string.h>  

7.   #include <stdlib.h>  

8.   #include "gr_api.h"  

9.      

10. int errorcode = 0;  

11. const char *errormsg = NULL;  

12.  

13. void test_gr_delete_inst(gr_instance_handle ins_handle) {  

14.    int result = gr_delete_inst(ins_handle);  

15.    if (result != 0) {  

16.        gr_get_error(&errorcode, &errormsg);  

17.        printf("gr_delete_inst interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

18.        return;  

19.    }  

20.    printf("gr_delete_inst interaction success. code:%d\n", result);  

21. }  

22.  

23. void test_gr_vfs_unmount(gr_vfs_handle *vfs) {  

24.    printf("gr_vfs_unmount in parameter. vfs:%s \n", vfs);  

25.    int result = gr_vfs_unmount(vfs);  

26.    if (result != 0) {  

27.        gr_get_error(&errorcode, &errormsg);  

28.        printf("gr_vfs_unmount interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

29.        return;  

30.    }  

31.    printf("gr_vfs_unmount interaction success. code:%d\n", result);  

32. }  

33.  

34. void test_gr_file_close(gr_vfs_handle vfs, gr_file_handle *file_handle, bool need_lock) {  

35.    printf("gr_file_close in parameter. need_lock:%s \n", need_lock ? "true" : "false");  

36.    int result = gr_file_close(vfs, file_handle, need_lock);  

37.    if (result != 0) {  

38.        gr_get_error(&errorcode, &errormsg);  

39.        printf("gr_file_close interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

40.        return;  

41.    }  

42.    printf("gr_file_close interaction success. code:%d\n", result);  

43. }  

44.  

45. void test_gr_file_pread(gr_vfs_handle vfs, gr_file_handle file_handle, char *buf, long size, int offset) {  

46.    printf("gr_file_pread in parameter. size:%d offset:%d\n", size, offset);  

47.    int result = gr_file_pread(vfs, file_handle, buf, size, offset);  

48.    if (result != size) {  

49.        gr_get_error(&errorcode, &errormsg);  

50.        printf("gr_file_pread interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

51.        return;  

52.    }  

53.    printf("gr_file_pread interaction success. code:%d\n", result);  

54. }  

55.  

56. void test_gr_file_pwrite(gr_vfs_handle vfs, gr_file_handle *file_handle, char *buf, long size, int offset) {  

57.    printf("gr_file_pwrite in parameter. data buf length:%d grite file size:%d offset:%d\n", strlen(buf), size, offset);  

58.    int result = gr_file_pwrite(vfs, file_handle, buf, size, offset);  

59.    if (result != size) {  

60.        gr_get_error(&errorcode, &errormsg);  

61.        printf("gr_file_pwrite interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

62.        return;  

63.    }  

64.    printf("gr_file_pwrite interaction success. code:%d\n", result);  

65. }  

66.  

67. void test_gr_file_stat(gr_vfs_handle vfs, char *fileName, long long *offset, long long *count, int *mode, char **atime) {  

68.    int result = gr_file_stat(vfs, fileName, offset, count, mode, atime);  

69.    if (result != 0) {  

70.        gr_get_error(&errorcode, &errormsg);  

71.        printf("gr_file_stat interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

72.        return;  

73.    }  

74.    printf("gr_file_stat interaction success. code:%d\n", result);  

75.    printf("fileName:%s offset:%ld count:%ld mode:%d atime:%s\n", fileName, *offset, *count, *mode, *atime);  

76. }  

77.  

78. void test_gr_file_open(gr_vfs_handle vfs, const char *fileName, int flags, gr_file_handle *file_handle) {  

79.    printf("gr_file_open in parameter. fileName:%s\n", fileName);  

80.    int result = gr_file_open(vfs, fileName, flags, file_handle);  

81.    if (result != 0) {  

82.        gr_get_error(&errorcode, &errormsg);  

83.        printf("gr_file_open interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

84.        return;  

85.    }  

86.    printf("gr_file_open interaction success. code:%d\n", result);  

87. }  

88.  

89. void test_gr_file_create(gr_vfs_handle vfs, const char *fileName, FileParameter *param) {  

90.    printf("gr_file_create in parameter. fileName:%s\n", fileName);  

91.    int result = gr_file_create(vfs, fileName, param);  

92.    if (result != 0) {  

93.        gr_get_error(&errorcode, &errormsg);  

94.        printf("gr_file_create interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

95.        return;  

96.    }  

97.    printf("gr_file_create interaction success. code:%d\n", result);  

98. }  

99.  

100.  void test_gr_vfs_mount(gr_instance_handle instHandle, char *vfsName, gr_vfs_handle *vfs) {  

101.      printf("gr_vfs_mount in parameter. vfsName:%s\n", vfsName);  

102.      int result = gr_vfs_mount(instHandle, vfsName, vfs);  

103.      if (result != 0) {  

104.          gr_get_error(&errorcode, &errormsg);  

105.          printf("gr_vfs_mount interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

106.          return;  

107.      }  

108.      printf("gr_vfs_mount interaction success. code:%d\n", result);  

109.  }  

110.    

111.  void test_gr_vfs_create(gr_instance_handle instHandle, const char *vfsName, int attrFlag) {  

112.      printf("gr_vfs_create in parameter. vfsName:%s , attrFlag:%d\n", vfsName, attrFlag);  

113.      int result = gr_vfs_create(instHandle, vfsName, attrFlag);  

114.      if (result != 0) {  

115.          gr_get_error(&errorcode, &errormsg);  

116.          printf("gr_vfs_create interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

117.          return;  

118.      }  

119.      printf("gr_vfs_create interaction success. code:%d\n", result);  

120.  }  

121.    

122.  void test_gr_create_inst(char *serverAddr, gr_instance_handle *ins_handle) {  

123.      int result = gr_create_inst(serverAddr, ins_handle);  

124.      if (result != 0) {  

125.          gr_get_error(&errorcode, &errormsg);  

126.          printf("gr_create_inst interaction failure. code:%d msg:%s\n", errorcode, errormsg);  

127.          return;  

128.      }  

129.      printf("gr_create_inst interaction success. code:%d\n", result);  

130.  }  

131.    

132.  int main(int argc, char *argv[]) {  

133.      char *serverAddr = argv[1];  

134.      // 建连  

135.      gr_instance_handle ins_handle;  

136.      test_gr_create_inst(serverAddr, &ins_handle);  

137.      // 创建目录  

138.      char *vfsName = "worm_case001";  

139.      int attrFlag = 0;  

140.      test_gr_vfs_create(ins_handle, vfsName, attrFlag);  

141.      // 挂载目录  

142.      gr_vfs_handle vfs;  

143.      test_gr_vfs_mount(ins_handle, vfsName, &vfs);  

144.      // 创建文件  

145.      char *fileName = "worm_case001_file";  

146.      FileParameter param;  

147.      test_gr_file_create(vfs, fileName, ¶m);  

148.      // create模式打开文件  

149.      gr_file_handle file_handle;  

150.      int flags = O_RDWR | O_SYNC;  

151.      test_gr_file_open(vfs, fileName, flags, &file_handle);  

152.      // 查询文件状态  

153.      long long foffset, count;  

154.      int mode;  

155.      char *atime;  

156.      test_gr_file_stat(vfs, fileName, &foffset, &count, &mode, &atime);  

157.      // 文件读写  

158.      long dataSize = 8 * 1024;  

159.      char *buf = (char*)malloc(dataSize);  

160.      memset(buf, 'A', dataSize);  

161.      int offset = 0;  

162.      test_gr_file_pwrite(vfs, &file_handle, buf, dataSize, offset);  

163.      char *read_buf = (char*)malloc(dataSize);  

164.      test_gr_file_pread(vfs, file_handle, read_buf, dataSize, offset);  

165.      // 查询文件状态  

166.      test_gr_file_stat(vfs, fileName, &foffset, &count, &mode, &atime);  

167.      // 关闭文件指定need_locktrue  

168.      test_gr_file_close(vfs, &file_handle, true);  

169.      // 查询文件状态  

170.      test_gr_file_stat(vfs, fileName, &foffset, &count, &mode, &atime);  

171.      // 卸载目录  

172.      test_gr_vfs_unmount(&vfs);  

173.      // 关闭连接  

174.      test_gr_delete_inst(ins_handle);  

175.      return 0;  

176.  }  

关闭文件后指定文件状态为锁定态,首先编译脚本,编译脚本需要oGRecorder编译源码产生的资源,需要指定源码的头文件和动态资源,编译命令如下:

gcc -o Opengauss_gr_Worm_Case001 Opengauss_gr_Worm_Case001.c -I oGRecorder/src/interface -lgrapi -L oGRecorder/output/lib

最后执行脚本指定交互节点的ip

6oGRecorder SDK API验证脚本执行结果

文件指定锁定态后,资源不能被篡改、删除,保护资源不被破坏;对资源进行破坏验证:

篡改文件内容;通过vim等工具打开资源,添加一些数据,保存文件。

7:篡改文件验证

•  删除文件;强行删除文件失败。

8:删除资源验证

参考链接:

openGauss 文档oGRecorder 概述:

https://docs.opengauss.org/zh/docs/latest/tool_and_commandreference/ogrecorder/ogrecorder_overview.html

openGauss 文档oGRecorder SDK API 介绍:https://docs.opengauss.org/zh/docs/latest/tool_and_commandreference/ogrecorder/ogrecorder_api_introduction.html

openGauss 文档oGRecorder 部署与运维指南: https://docs.opengauss.org/zh/docs/latest/tool_and_commandreference/ogrecorder/ogrecorder_deployment_guide.html


本页内容