From 9e4d692d6b3f4ea6949dcb0f84e87a297078f424 Mon Sep 17 00:00:00 2001 From: kailixu Date: Mon, 1 Apr 2024 00:49:25 +0800 Subject: [PATCH] feat: support encryption --- include/common/tgrant.h | 4 +- include/util/tdef.h | 2 - source/common/src/tglobal.c | 2 +- source/dnode/mgmt/mgmt_dnode/inc/dmInt.h | 1 + source/dnode/mgmt/mgmt_dnode/src/dmHandle.c | 20 ++++++ source/dnode/mgmt/mgmt_dnode/src/dmWorker.c | 3 + source/dnode/mgmt/mgmt_mnode/src/mmHandle.c | 1 + source/dnode/mgmt/node_util/src/dmFile.c | 33 +++++++--- source/dnode/mnode/impl/inc/mndInt.h | 9 ++- source/dnode/mnode/impl/src/mndDnode.c | 68 +++++++++++++++++---- source/libs/parser/src/parTranslater.c | 2 +- 11 files changed, 116 insertions(+), 29 deletions(-) diff --git a/include/common/tgrant.h b/include/common/tgrant.h index ac0d3155c7..c1e37787c2 100644 --- a/include/common/tgrant.h +++ b/include/common/tgrant.h @@ -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 diff --git a/include/util/tdef.h b/include/util/tdef.h index f7e6bcf221..717bf4e611 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -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 diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c index ed41a759af..c543f3702b 100644 --- a/source/common/src/tglobal.c +++ b/source/common/src/tglobal.c @@ -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 diff --git a/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h b/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h index 975246a10f..9e1fe69714 100644 --- a/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h +++ b/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h @@ -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); diff --git a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c index a1c8dfc217..daaff3456d 100644 --- a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c +++ b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c @@ -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; diff --git a/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c b/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c index cecb3d1581..d124eb74be 100644 --- a/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c +++ b/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c @@ -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); diff --git a/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c b/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c index 7e38b994df..e0ea499b2b 100644 --- a/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c +++ b/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c @@ -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; diff --git a/source/dnode/mgmt/node_util/src/dmFile.c b/source/dnode/mgmt/node_util/src/dmFile.c index 40394526e1..f68fb1f6f2 100644 --- a/source/dnode/mgmt/node_util/src/dmFile.c +++ b/source/dnode/mgmt/node_util/src/dmFile.c @@ -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; @@ -344,11 +353,15 @@ int32_t updateEncryptKey(char *key) { if(writeCheckCode(checkFile, realCheckFile, key) != 0){ 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()); diff --git a/source/dnode/mnode/impl/inc/mndInt.h b/source/dnode/mnode/impl/inc/mndInt.h index daba037d2c..2da14c65d2 100644 --- a/source/dnode/mnode/impl/inc/mndInt.h +++ b/source/dnode/mnode/impl/inc/mndInt.h @@ -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; diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c index 7d77e31667..6d6c97f64b 100644 --- a/source/dnode/mnode/impl/src/mndDnode.c +++ b/source/dnode/mnode/impl/src/mndDnode.c @@ -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; diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 778e3cf606..107fcd2403 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -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) {