---
title: 数据保险柜测试验证-官方技术文章-鲲鹏社区
description: 数据保险柜（oGRecorder）是一款数据库日志保护软件。其典型部署场景是运行于virtCCA中，南向对接Dorado Worm存储，北向通过oGRecorderSDK对接数据库，实现对数据库WAL日志的实时同步，形成对用户数据库系统的日志安全保护的软硬一体组合方案。 其中virtCCA基于硬件硬隔离和机密计算能力，为oGRecorder的运行提供隔离于宿主机、REE的安全TEE计算环境；Dor
keywords: 数据保险柜测试验证,官方技术文章,鲲鹏社区,安装部署,Rest,API,功能验证,GRecorder
url: https://www.hikunpeng.com/developer/techArticles/20260522-1?envFlag=1
section: (其他)
---

# 数据保险柜测试验证-官方技术文章-鲲鹏社区

URL: https://www.hikunpeng.com/developer/techArticles/20260522-1?envFlag=1
描述: 数据保险柜（oGRecorder）是一款数据库日志保护软件。其典型部署场景是运行于virtCCA中，南向对接Dorado Worm存储，北向通过oGRecorderSDK对接数据库，实现对数据库WAL日志的实时同步，形成对用户数据库系统的日志安全保护的软硬一体组合方案。 其中virtCCA基于硬件硬隔离和机密计算能力，为oGRecorder的运行提供隔离于宿主机、REE的安全TEE计算环境；Dor
关键词: 数据保险柜测试验证,官方技术文章,鲲鹏社区,安装部署,Rest,API,功能验证,GRecorder

官方技术文章 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles)

数据保险柜测试验证

数据保险柜测试验证

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 [了解详情](https://opengauss.obs.cn-south-1.myhuaweicloud.com/latest/binarylibs/gcc10.3/openGauss-third_party_binarylibs_openEuler_arm.tar.gz)

git clonehttps://gitcode.com/opengauss/CBB.git-b development

cd CBB/build/linux/opengauss

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

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

git clonehttps://gitcode.com/opengauss/oGRecorder.git

cd oGRecorder/build

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

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

CM-RestAPI是JAVA项目开发，所以使用时有软件限制，安装包生成需要如下版本要求：

•Maven版本要求3.9.9

•Java版本要求jdk-17

git clonehttps://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#部署流程 [了解详情](https://docs.opengauss.org/zh/docs/latest/tool_and_commandreference/ogrecorder/ogrecorder_deployment_guide.html#部署流程)

## Rest-API功能验证

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

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

https://docs.opengauss.org/zh/docs/latest/tool_and_commandreference/features.html#支持集群信息查询和推送 [了解详情](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.interrorcode = 0;

11.constchar*errormsg = NULL;

12.

13.voidtest_gr_delete_inst(gr_instance_handle ins_handle) {

14.intresult = 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.voidtest_gr_vfs_unmount(gr_vfs_handle *vfs) {

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

25.intresult = 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.voidtest_gr_file_close(gr_vfs_handle vfs, gr_file_handle *file_handle,boolneed_lock) {

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

36.intresult = 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.voidtest_gr_file_pread(gr_vfs_handle vfs, gr_file_handle file_handle,char*buf,longsize,intoffset) {

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

47.intresult = 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.voidtest_gr_file_pwrite(gr_vfs_handle vfs, gr_file_handle *file_handle,char*buf,longsize,intoffset) {

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

58.intresult = 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.voidtest_gr_file_stat(gr_vfs_handle vfs,char*fileName,longlong*offset,longlong*count,int*mode,char**atime) {

68.intresult = 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.voidtest_gr_file_open(gr_vfs_handle vfs,constchar*fileName,intflags, gr_file_handle *file_handle) {

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

80.intresult = 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.voidtest_gr_file_create(gr_vfs_handle vfs,constchar*fileName, FileParameter *param) {

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

91.intresult = 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.voidtest_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.intresult = 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.voidtest_gr_vfs_create(gr_instance_handle instHandle,constchar*vfsName,intattrFlag) {

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

113.intresult = 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.voidtest_gr_create_inst(char*serverAddr, gr_instance_handle *ins_handle) {

123.intresult = 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.intmain(intargc,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.intattrFlag = 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.intflags = O_RDWR | O_SYNC;

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

152.//查询文件状态

153.longlongfoffset, count;

154.intmode;

155.char*atime;

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

157.//文件读写

158.longdataSize = 8 * 1024;

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

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

161.intoffset = 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_lock为true

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.return0;

176.}

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

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

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

图6：oGRecorder 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 [了解详情](https://docs.opengauss.org/zh/docs/latest/tool_and_commandreference/ogrecorder/ogrecorder_deployment_guide.html)

本页内容
