feat: support encryption

This commit is contained in:
kailixu 2024-04-01 00:49:25 +08:00
parent d6ae4d37cc
commit 9e4d692d6b
11 changed files with 116 additions and 29 deletions

View File

@ -58,9 +58,11 @@ typedef enum {
TSDB_GRANT_BACKUP_RESTORE,
} EGrantType;
int32_t checkAndGetCryptKey(const char *encryptCode, const char *machineId, char **key);
int32_t generateEncryptCode(const char *key, const char *machineId, char **encryptCode);
int32_t grantCheck(EGrantType grant);
int32_t grantCheckExpire(EGrantType grant);
char* tGetMachineId();
char *tGetMachineId();
// #ifndef GRANTS_CFG
#ifdef TD_ENTERPRISE

View File

@ -296,8 +296,6 @@ typedef enum ELogicConditionType {
#define TSDB_DNODE_CONFIG_LEN 128
#define TSDB_DNODE_VALUE_LEN 256
#define TSDB_ENCRYPT_KEY_LEN 16
#define TSDB_CLUSTER_VALUE_LEN 1000
#define TSDB_GRANT_LOG_COL_LEN 15600

View File

@ -98,7 +98,7 @@ int64_t tsDndUpTime = 0;
// dnode misc
uint32_t tsEncryptionKeyChksum = 0;
int8_t tsEncryptionKeyStat = ENCRYPT_KEY_STAT_LOADED; //ENCRYPT_KEY_STAT_UNKNOWN;
int8_t tsEncryptionKeyStat = ENCRYPT_KEY_STAT_UNKNOWN;
int8_t tsGrant = 1;
// monitor

View File

@ -57,6 +57,7 @@ int32_t dmProcessServerRunStatus(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t dmProcessRetrieve(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);
int32_t dmProcessGrantReq(void *pInfo, SRpcMsg *pMsg);
int32_t dmProcessGrantNotify(void *pInfo, SRpcMsg *pMsg);
int32_t dmProcessCreateEncryptKeyReq(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);
// dmWorker.c
int32_t dmPutNodeMsgToMgmtQueue(SDnodeMgmt *pMgmt, SRpcMsg *pMsg);

View File

@ -224,6 +224,26 @@ int32_t dmProcessConfigReq(SDnodeMgmt *pMgmt, SRpcMsg *pMsg) {
return 0;
}
int32_t dmProcessCreateEncryptKeyReq(SDnodeMgmt *pMgmt, SRpcMsg *pMsg) {
#ifdef TD_ENTERPRISE
int32_t code = 0;
SDCfgDnodeReq cfgReq = {0};
if (tDeserializeSDCfgDnodeReq(pMsg->pCont, pMsg->contLen, &cfgReq) != 0) {
code = TSDB_CODE_INVALID_MSG;
goto _exit;
}
code = updateEncryptKey(cfgReq.value);
pMsg->code = code;
pMsg->info.rsp = NULL;
pMsg->info.rspLen = 0;
_exit:
return code;
#endif
return 0;
}
static void dmGetServerRunStatus(SDnodeMgmt *pMgmt, SServerStatusRsp *pStatus) {
pStatus->statusCode = TSDB_SRV_STATUS_SERVICE_OK;
pStatus->details[0] = 0;

View File

@ -359,6 +359,9 @@ static void dmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
case TDMT_MND_GRANT_NOTIFY:
code = dmProcessGrantNotify(NULL, pMsg);
break;
case TDMT_DND_CREATE_ENCRYPT_KEY:
code = dmProcessCreateEncryptKeyReq(pMgmt, pMsg);
break;
default:
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
dGError("msg:%p, not processed in mgmt queue", pMsg);

View File

@ -113,6 +113,7 @@ SArray *mmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_DND_ALTER_VNODE_TYPE_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_SYNC_CONFIG_CHANGE_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_DND_CREATE_ENCRYPT_KEY_RSP, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_CONNECT, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_ACCT, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;

View File

@ -15,6 +15,7 @@
#define _DEFAULT_SOURCE
#include "dmUtil.h"
#include "tchecksum.h"
#include "tjson.h"
#include "tgrant.h"
#include "crypt.h"
@ -304,15 +305,17 @@ _OVER:
}
int32_t updateEncryptKey(char *key) {
int32_t code = -1;
int32_t code = -1;
char *machineId = NULL;
char *encryptCode = NULL;
char folder[PATH_MAX] = {0};
char folder[PATH_MAX] = {0};
char encryptFile[PATH_MAX] = {0};
char realEncryptFile[PATH_MAX] = {0};
char encryptFile[PATH_MAX] = {0};
char realEncryptFile[PATH_MAX] = {0};
char checkFile[PATH_MAX] = {0};
char realCheckFile[PATH_MAX] = {0};
char checkFile[PATH_MAX] = {0};
char realCheckFile[PATH_MAX] = {0};
snprintf(folder, sizeof(folder), "%s%sdnode", tsDataDir, TD_DIRSEP);
snprintf(encryptFile, sizeof(realEncryptFile), "%s%s%s.bak", folder, TD_DIRSEP, DM_ENCRYPT_CODE_FILE);
@ -335,8 +338,14 @@ int32_t updateEncryptKey(char *key) {
}
//TODO: dmchen parse key from code
char* encryptCode = NULL;
//generateEncryptCode(key, tGetMachineId(), &encryptCode);
if (!(machineId = tGetMachineId())) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
goto _OVER;
}
if (generateEncryptCode(key, machineId, &encryptCode) != 0) {
goto _OVER;
}
if(writeEncryptCode(encryptFile, realEncryptFile, encryptCode) != 0){
goto _OVER;
@ -346,9 +355,13 @@ int32_t updateEncryptKey(char *key) {
goto _OVER;
}
tsEncryptionKeyChksum = taosCalcChecksum(0, key, strlen(key));
tsEncryptionKeyStat = ENCRYPT_KEY_STAT_LOADED;
code = 0;
_OVER:
taosMemoryFree(encryptCode);
taosMemoryFree(machineId);
if (code != 0) {
if (terrno == 0) terrno = TAOS_SYSTEM_ERROR(errno);
dError("failed to update encrypt key since %s", terrstr());

View File

@ -104,6 +104,13 @@ typedef struct {
int64_t timeseriesAllowed;
} SGrantInfo;
typedef struct {
int8_t encrypting;
int16_t nEncrypt;
int16_t nSuccess;
int16_t nFailed;
} SEncryptMgmt;
typedef struct SMnode {
int32_t selfDnodeId;
int64_t clusterId;
@ -114,7 +121,6 @@ typedef struct SMnode {
bool stopped;
bool restored;
bool deploy;
int8_t encrypting;
char *path;
int64_t checkTime;
SyncIndex applied;
@ -128,6 +134,7 @@ typedef struct SMnode {
SProfileMgmt profileMgmt;
STelemMgmt telemMgmt;
SSyncMgmt syncMgmt;
SEncryptMgmt encryptMgmt;
SGrantInfo grant;
MndMsgFp msgFp[TDMT_MAX];
SMsgCb msgCb;

View File

@ -80,6 +80,7 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq);
static int32_t mndProcessNotifyReq(SRpcMsg *pReq);
static int32_t mndProcessRestoreDnodeReq(SRpcMsg *pReq);
static int32_t mndProcessStatisReq(SRpcMsg *pReq);
static int32_t mndProcessCreateEncryptKeyRsp(SRpcMsg *pRsp);
static int32_t mndRetrieveConfigs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
static void mndCancelGetNextConfig(SMnode *pMnode, void *pIter);
@ -116,6 +117,7 @@ int32_t mndInitDnode(SMnode *pMnode) {
mndSetMsgHandle(pMnode, TDMT_MND_SHOW_VARIABLES, mndProcessShowVariablesReq);
mndSetMsgHandle(pMnode, TDMT_MND_RESTORE_DNODE, mndProcessRestoreDnodeReq);
mndSetMsgHandle(pMnode, TDMT_MND_STATIS, mndProcessStatisReq);
mndSetMsgHandle(pMnode, TDMT_DND_CREATE_ENCRYPT_KEY_RSP, mndProcessCreateEncryptKeyRsp);
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_CONFIGS, mndRetrieveConfigs);
mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_CONFIGS, mndCancelGetNextConfig);
@ -468,7 +470,7 @@ static int32_t mndCheckClusterCfgPara(SMnode *pMnode, SDnodeObj *pDnode, const S
return DND_REASON_ENABLE_WHITELIST_NOT_MATCH;
}
if (!atomic_load_8(&pMnode->encrypting) &&
if (!atomic_load_8(&pMnode->encryptMgmt.encrypting) &&
(pCfg->encryptionKeyStat != tsEncryptionKeyStat || pCfg->encryptionKeyChksum != tsEncryptionKeyChksum)) {
mError("dnode:%d, encryptionKey:%" PRIi8 "-%u inconsistent with cluster:%" PRIi8 "-%u", pDnode->id,
pCfg->encryptionKeyStat, pCfg->encryptionKeyChksum, tsEncryptionKeyStat, tsEncryptionKeyChksum);
@ -1407,32 +1409,49 @@ _err:
return -1;
}
static int32_t mndProcessCreateEncryptKeyReq(SMnode *pMnode, int32_t dnodeId, SDCfgDnodeReq *pDcfgReq) {
static int32_t mndProcessCreateEncryptKeyReq(SRpcMsg *pReq, int32_t dnodeId, SDCfgDnodeReq *pDcfgReq) {
int32_t code = 0;
SMnode *pMnode = pReq->info.node;
SSdb *pSdb = pMnode->pSdb;
void *pIter = NULL;
int8_t encrypting = 0;
if (0 != atomic_val_compare_exchange_8(&pMnode->encrypting, 0, 1)) {
const STraceId *trace = &pReq->info.traceId;
if (0 != (encrypting = atomic_val_compare_exchange_8(&pMnode->encryptMgmt.encrypting, 0, 1))) {
mGWarn("msg:%p, failed to create encrypt key since %s, encrypting:%" PRIi8, pReq, tstrerror(code), encrypting);
code = TSDB_CODE_QRY_DUPLICATED_OPERATION;
return code; // don't use go to exit since encrypting is released in _exit
goto _exit;
}
if (tsEncryptionKeyStat == ENCRYPT_KEY_STAT_SET || tsEncryptionKeyStat == ENCRYPT_KEY_STAT_LOADED) {
code = TSDB_CODE_QRY_DUPLICATED_OPERATION;
atomic_store_8(&pMnode->encryptMgmt.encrypting, 0);
mGWarn("msg:%p, failed to create encrypt key since %s, stat:%" PRIi8 ", checksum:%u", pReq, tstrerror(code),
tsEncryptionKeyStat, tsEncryptionKeyChksum);
goto _exit;
}
atomic_store_16(&pMnode->encryptMgmt.nEncrypt, 0);
atomic_store_16(&pMnode->encryptMgmt.nSuccess, 0);
atomic_store_16(&pMnode->encryptMgmt.nFailed, 0);
while (1) {
SDnodeObj *pDnode = NULL;
pIter = sdbFetch(pSdb, SDB_DNODE, pIter, (void **)&pDnode);
if (pIter == NULL) break;
if (pDnode->offlineReason != DND_REASON_ONLINE) continue;
if (pDnode->id == dnodeId || dnodeId == -1 || dnodeId == 0) {
if (dnodeId == -1 || pDnode->id == dnodeId || dnodeId == 0) {
SEpSet epSet = mndGetDnodeEpset(pDnode);
int32_t bufLen = tSerializeSDCfgDnodeReq(NULL, 0, pDcfgReq);
void *pBuf = rpcMallocCont(bufLen);
if (pBuf != NULL) {
tSerializeSDCfgDnodeReq(pBuf, bufLen, pDcfgReq);
SRpcMsg rpcMsg = {.msgType = TDMT_DND_CONFIG_DNODE, .pCont = pBuf, .contLen = bufLen};
tmsgSendReq(&epSet, &rpcMsg);
code = 0;
SRpcMsg rpcMsg = {.msgType = TDMT_DND_CREATE_ENCRYPT_KEY, .pCont = pBuf, .contLen = bufLen};
if (0 == tmsgSendReq(&epSet, &rpcMsg)) {
atomic_add_fetch_16(&pMnode->encryptMgmt.nEncrypt, 1);
}
}
}
@ -1440,7 +1459,6 @@ static int32_t mndProcessCreateEncryptKeyReq(SMnode *pMnode, int32_t dnodeId, SD
}
_exit:
atomic_store_8(&pMnode->encrypting, 0);
return code;
}
@ -1512,16 +1530,16 @@ static int32_t mndProcessConfigDnodeReq(SRpcMsg *pReq) {
snprintf(dcfgReq.value, TSDB_DNODE_VALUE_LEN, "%d", flag);
} else if (strncasecmp(cfgReq.config, "encrypt_key", 12) == 0) {
int32_t vlen = strlen(cfgReq.value);
if (vlen > TSDB_ENCRYPT_KEY_LEN || vlen < 8) {
mError("dnode:%d, failed to create encrypt_key since invalid vlen:%d, valid range:[%d, %d]", cfgReq.dnodeId,
vlen, 8, TSDB_ENCRYPT_KEY_LEN);
if (vlen > ENCRYPT_KEY_LEN || vlen < 8) {
mError("dnode:%d, failed to create encrypt_key since invalid vlen:%d, valid range:[%d, %d]", cfgReq.dnodeId, vlen,
8, ENCRYPT_KEY_LEN); // ENCRYPT_TODO: range[min, max]
terrno = TSDB_CODE_INVALID_CFG;
goto _err_out;
}
strcpy(dcfgReq.config, cfgReq.config);
strcpy(dcfgReq.value, cfgReq.value);
tFreeSMCfgDnodeReq(&cfgReq);
return mndProcessCreateEncryptKeyReq(pMnode, cfgReq.dnodeId, &dcfgReq);
return mndProcessCreateEncryptKeyReq(pReq, cfgReq.dnodeId, &dcfgReq);
#endif
} else {
if (mndMCfg2DCfg(&cfgReq, &dcfgReq)) goto _err_out;
@ -1555,6 +1573,30 @@ static int32_t mndProcessConfigDnodeRsp(SRpcMsg *pRsp) {
return 0;
}
static int32_t mndProcessCreateEncryptKeyRsp(SRpcMsg *pRsp) {
SMnode *pMnode = pRsp->info.node;
int16_t nSuccess = 0;
int16_t nFailed = 0;
if (0 == pRsp->code) {
nSuccess = atomic_add_fetch_16(&pMnode->encryptMgmt.nSuccess, 1);
} else {
nFailed = atomic_add_fetch_16(&pMnode->encryptMgmt.nFailed, 1);
}
int16_t nReq = atomic_load_16(&pMnode->encryptMgmt.nEncrypt);
bool finished = nSuccess + nFailed >= nReq;
if (finished) {
atomic_store_8(&pMnode->encryptMgmt.encrypting, 0);
}
mInfo("create encrypt key rsp, nReq:%" PRIi16 ", nSucess:%" PRIi16 ", nFailed:%" PRIi16 ", %s", nReq, nSuccess,
nFailed, finished ? "encrypt done" : "in encrypting") return 0;
return 0;
}
static int32_t mndRetrieveConfigs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
SMnode *pMnode = pReq->info.node;
int32_t totalRows = 0;

View File

@ -5574,7 +5574,7 @@ static int32_t checkDatabaseOptions(STranslateContext* pCxt, const char* pDbName
TSDB_MAX_DB_WITH_ARBITRATOR);
}
if (TSDB_CODE_SUCCESS == code) {
code = checkDbEnumOption(pCxt, "encryptionAlgorithm", pOptions->encryptAlgorithm, TSDB_MIN_ENCRYPT_ALGO,
code = checkDbEnumOption(pCxt, "encryptAlgorithm", pOptions->encryptAlgorithm, TSDB_MIN_ENCRYPT_ALGO,
TSDB_MAX_ENCRYPT_ALGO);
}
if (TSDB_CODE_SUCCESS == code) {