diff --git a/include/common/systable.h b/include/common/systable.h index 69c0d9e5c14d..bcb36b829bdb 100644 --- a/include/common/systable.h +++ b/include/common/systable.h @@ -131,6 +131,8 @@ void getPerfDbMeta(const SSysTableMeta** pPerfsTableMeta, size_t* size); void getVisibleInfosTablesNum(bool sysInfo, size_t* size); bool invisibleColumn(bool sysInfo, int8_t tableType, int8_t flags); +const SSysTableMeta* getSysTableMeta(const char* dbName, const char* tbName); + #ifdef __cplusplus } #endif diff --git a/include/common/tcommon.h b/include/common/tcommon.h index 7ac9edaba445..d4adade167ca 100644 --- a/include/common/tcommon.h +++ b/include/common/tcommon.h @@ -443,7 +443,14 @@ typedef struct STUidTagInfo { #define NOTIFY_EVENT_STR_COLUMN_INDEX 0 int32_t taosGenCrashJsonMsg(int signum, char** pMsg, int64_t clusterId, int64_t startTime); -int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol, char* likePattern); + +#define SHOW_VAR_PRIV_SYSTEM 0x01 +#define SHOW_VAR_PRIV_SECURITY 0x02 +#define SHOW_VAR_PRIV_AUDIT 0x04 +#define SHOW_VAR_PRIV_DEBUG 0x08 +#define SHOW_VAR_PRIV_ALL (SHOW_VAR_PRIV_SYSTEM | SHOW_VAR_PRIV_SECURITY | SHOW_VAR_PRIV_AUDIT | SHOW_VAR_PRIV_DEBUG) + +int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol, char* likePattern, uint8_t showPrivMask); #define TSMA_RES_STB_POSTFIX "_tsma_res_stb_" #define MD5_OUTPUT_LEN 32 diff --git a/include/libs/command/command.h b/include/libs/command/command.h index 438095e88674..85a76b1e1169 100644 --- a/include/libs/command/command.h +++ b/include/libs/command/command.h @@ -23,7 +23,8 @@ typedef struct SExplainCtx SExplainCtx; typedef struct SExplainPlanCtx SExplainPlanCtx; -int32_t qExecCommand(int64_t* pConnId, bool sysInfoUser, SNode *pStmt, SRetrieveTableRsp **pRsp, int8_t biMode, void* charsetCxt); +int32_t qExecCommand(int64_t *pConnId, bool sysInfoUser, uint8_t showVarPrivMask, SNode *pStmt, + SRetrieveTableRsp **pRsp, int8_t biMode, void *charsetCxt); int32_t qExecStaticExplain(SQueryPlan *pDag, SRetrieveTableRsp **pRsp); int32_t qExecExplainBegin(SQueryPlan *pDag, SExplainCtx **pCtx, int64_t startTs); diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 339cd060c753..84f1da167174 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -140,6 +140,7 @@ typedef struct SParseContext { union { uint16_t privInfo; struct { + // N.B. keep the order of the bit definition unchanged uint16_t minSecLevel : 3; // user min security level uint16_t privInfoBasic : 1; uint16_t privInfoPrivileged : 1; @@ -148,7 +149,7 @@ typedef struct SParseContext { uint16_t privPerfBasic : 1; uint16_t privPerfPrivileged : 1; uint16_t maxSecLevel : 3; // user max security level - uint16_t macMode : 1; // 1 = MAC mandatory (mirrors macActive, propagates to executor) + uint16_t macMode : 1; // 1 = MAC mandatory, propagates to executor uint16_t reserved1 : 3; }; }; diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 3da6b135b91a..9a6d56cd1fde 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -430,12 +430,43 @@ int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtC return code; } +#ifdef TD_ENTERPRISE +static uint8_t getShowVarPrivMask(SRequestObj* pRequest) { + SCatalog* pCatalog = NULL; + SGetUserAuthRsp authRsp = {0}; + STscObj* pTscObj = pRequest->pTscObj; + SRequestConnInfo conn = {.pTrans = pTscObj->pAppInfo->pTransporter, + .requestId = pRequest->requestId, + .requestObjRefId = pRequest->self, + .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)}; + + if (TSDB_CODE_SUCCESS != catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCatalog)) { + return 0; + } + if (TSDB_CODE_SUCCESS != catalogGetUserAuth(pCatalog, &conn, pTscObj->user, &authRsp)) { + return 0; + } + + uint8_t mask = 0; + if (PRIV_HAS(&authRsp.sysPrivs, PRIV_VAR_SYSTEM_SHOW)) mask |= SHOW_VAR_PRIV_SYSTEM; + if (PRIV_HAS(&authRsp.sysPrivs, PRIV_VAR_SECURITY_SHOW)) mask |= SHOW_VAR_PRIV_SECURITY; + if (PRIV_HAS(&authRsp.sysPrivs, PRIV_VAR_AUDIT_SHOW)) mask |= SHOW_VAR_PRIV_AUDIT; + if (PRIV_HAS(&authRsp.sysPrivs, PRIV_VAR_DEBUG_SHOW)) mask |= SHOW_VAR_PRIV_DEBUG; + return mask; +} +#endif int32_t execLocalCmd(SRequestObj* pRequest, SQuery* pQuery) { SRetrieveTableRsp* pRsp = NULL; int8_t biMode = atomic_load_8(&pRequest->pTscObj->biMode); - int32_t code = qExecCommand(&pRequest->pTscObj->id, pRequest->pTscObj->sysInfo, pQuery->pRoot, &pRsp, biMode, - pRequest->pTscObj->optionInfo.charsetCxt); + uint8_t showVarPrivMask = SHOW_VAR_PRIV_ALL; +#ifdef TD_ENTERPRISE + if (pQuery->pRoot != NULL && nodeType(pQuery->pRoot) == QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT) { + showVarPrivMask = getShowVarPrivMask(pRequest); + } +#endif + int32_t code = qExecCommand(&pRequest->pTscObj->id, pRequest->pTscObj->sysInfo, showVarPrivMask, pQuery->pRoot, &pRsp, + biMode, pRequest->pTscObj->optionInfo.charsetCxt); if (TSDB_CODE_SUCCESS == code && NULL != pRsp) { code = setQueryResultFromRsp(&pRequest->body.resInfo, pRsp, pRequest->body.resInfo.convertUcs4, pRequest->stmtBindVersion > 0); @@ -473,7 +504,13 @@ void asyncExecLocalCmd(SRequestObj* pRequest, SQuery* pQuery) { return; } - int32_t code = qExecCommand(&pRequest->pTscObj->id, pRequest->pTscObj->sysInfo, pQuery->pRoot, &pRsp, + uint8_t showVarPrivMask = SHOW_VAR_PRIV_ALL; +#ifdef TD_ENTERPRISE + if (pQuery->pRoot != NULL && nodeType(pQuery->pRoot) == QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT) { + showVarPrivMask = getShowVarPrivMask(pRequest); + } +#endif + int32_t code = qExecCommand(&pRequest->pTscObj->id, pRequest->pTscObj->sysInfo, showVarPrivMask, pQuery->pRoot, &pRsp, atomic_load_8(&pRequest->pTscObj->biMode), pRequest->pTscObj->optionInfo.charsetCxt); if (TSDB_CODE_SUCCESS == code && NULL != pRsp) { code = setQueryResultFromRsp(&pRequest->body.resInfo, pRsp, pRequest->body.resInfo.convertUcs4, diff --git a/source/common/src/systable.c b/source/common/src/systable.c index 499819b43fb7..c5634ffec417 100644 --- a/source/common/src/systable.c +++ b/source/common/src/systable.c @@ -972,3 +972,25 @@ bool invisibleColumn(bool sysInfo, int8_t tableType, int8_t flags) { } return 0 != (flags & COL_IS_SYSINFO); } + +/** + * information_schema or performance_schema + */ +const SSysTableMeta* getSysTableMeta(const char* dbName, const char* tbName) { + const SSysTableMeta* pMeta = NULL; + size_t size = 0; + if (!dbName || !tbName) { + return NULL; + } + if (dbName[0] == 'i' || dbName[0] == 'I') { + getInfosDbMeta(&pMeta, &size); + } else { + getPerfDbMeta(&pMeta, &size); + } + for (size_t i = 0; i < size; ++i) { + if (strcasecmp(pMeta[i].name, tbName) == 0) { + return pMeta + i; + } + } + return NULL; +} diff --git a/source/common/src/tmisce.c b/source/common/src/tmisce.c index dd0497810f31..c684d56120be 100644 --- a/source/common/src/tmisce.c +++ b/source/common/src/tmisce.c @@ -336,7 +336,24 @@ int32_t taosGenCrashJsonMsg(int signum, char** pMsg, int64_t clusterId, int64_t TAOS_RETURN(code); } -int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol, char* likePattern) { +#ifdef TD_ENTERPRISE +static bool showVarPrivAllowed(uint8_t showPrivMask, int8_t cfgPrivType) { + switch (cfgPrivType) { + case CFG_PRIV_SYSTEM: + return (showPrivMask & SHOW_VAR_PRIV_SYSTEM) != 0; + case CFG_PRIV_SECURITY: + return (showPrivMask & SHOW_VAR_PRIV_SECURITY) != 0; + case CFG_PRIV_AUDIT: + return (showPrivMask & SHOW_VAR_PRIV_AUDIT) != 0; + case CFG_PRIV_DEBUG: + return (showPrivMask & SHOW_VAR_PRIV_DEBUG) != 0; + default: + return false; + } +} +#endif + +int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol, char* likePattern, uint8_t showPrivMask) { int32_t code = 0; SConfig* pConf = taosGetCfg(); if (pConf == NULL) { @@ -373,6 +390,11 @@ int32_t dumpConfToDataBlock(SSDataBlock* pBlock, int32_t startCol, char* likePat if (likePattern && rawStrPatternMatch(pItem->name, likePattern) != TSDB_PATTERN_MATCH) { continue; } +#ifdef TD_ENTERPRISE + if (!showVarPrivAllowed(showPrivMask, pItem->privType)) { + continue; + } +#endif STR_WITH_MAXSIZE_TO_VARSTR(name, pItem->name, TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE); SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, col++); diff --git a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c index cd80efb1afc0..1396c9e2be69 100644 --- a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c +++ b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c @@ -1683,7 +1683,7 @@ int32_t dmBuildVariablesBlock(SSDataBlock **ppBlock) { } int32_t dmAppendVariablesToBlock(SSDataBlock *pBlock, int32_t dnodeId) { - int32_t code = dumpConfToDataBlock(pBlock, 1, NULL); + int32_t code = dumpConfToDataBlock(pBlock, 1, NULL, SHOW_VAR_PRIV_ALL); if (code != 0) { return code; } diff --git a/source/dnode/mnode/impl/inc/mndPrivilege.h b/source/dnode/mnode/impl/inc/mndPrivilege.h index 2a4ca881b740..92e8835aa34d 100644 --- a/source/dnode/mnode/impl/inc/mndPrivilege.h +++ b/source/dnode/mnode/impl/inc/mndPrivilege.h @@ -41,6 +41,8 @@ int32_t mndCheckTokenPrivilege(SMnode *pMnode, const char *opUser, const char *o int32_t mndCheckSysObjPrivilege(SMnode *pMnode, SUserObj *pUser, const char *token, EPrivType privType, EPrivObjType objType, int64_t ownerId, const char *objFName, const char *tbName); +uint64_t mndBuildSysPrivBatchMask(SMnode *pMnode, SUserObj *pUser, const char *token, + const EPrivType *privTypes, int32_t numPrivTypes); int32_t mndCheckObjPrivilegeRec(SMnode *pMnode, SUserObj *pUser, EPrivType privType, EPrivObjType objType, int64_t ownerId, int32_t acctId, const char *objName, const char *tbName); int32_t mndCheckObjPrivilegeRecF(SMnode *pMnode, SUserObj *pUser, EPrivType privType, EPrivObjType objType, diff --git a/source/dnode/mnode/impl/src/mndConfig.c b/source/dnode/mnode/impl/src/mndConfig.c index b7d781f32896..7cb4609091af 100644 --- a/source/dnode/mnode/impl/src/mndConfig.c +++ b/source/dnode/mnode/impl/src/mndConfig.c @@ -1232,7 +1232,43 @@ static void cfgObjArrayCleanUp(SArray *array) { taosArrayDestroy(array); } -static SArray *initVariablesFromItems(SArray *pItems, const char* likePattern) { +#ifdef TD_ENTERPRISE +static bool mndShowVarPrivAllowed(uint8_t showPrivMask, int8_t cfgPrivType) { + switch (cfgPrivType) { + case CFG_PRIV_SYSTEM: + return (showPrivMask & SHOW_VAR_PRIV_SYSTEM) != 0; + case CFG_PRIV_SECURITY: + return (showPrivMask & SHOW_VAR_PRIV_SECURITY) != 0; + case CFG_PRIV_AUDIT: + return (showPrivMask & SHOW_VAR_PRIV_AUDIT) != 0; + case CFG_PRIV_DEBUG: + return (showPrivMask & SHOW_VAR_PRIV_DEBUG) != 0; + default: + return false; + } +} + +static uint8_t mndBuildShowVarPrivMask(SMnode *pMnode, SUserObj *pUser, const char *token) { + static const EPrivType kShowVarPrivTypes[] = { + PRIV_VAR_SYSTEM_SHOW, + PRIV_VAR_SECURITY_SHOW, + PRIV_VAR_AUDIT_SHOW, + PRIV_VAR_DEBUG_SHOW, + }; + + uint64_t rawMask = + mndBuildSysPrivBatchMask(pMnode, pUser, token, kShowVarPrivTypes, (int32_t)ARRAY_SIZE(kShowVarPrivTypes)); + + uint8_t mask = 0; + if (rawMask & (1ULL << 0)) mask |= SHOW_VAR_PRIV_SYSTEM; + if (rawMask & (1ULL << 1)) mask |= SHOW_VAR_PRIV_SECURITY; + if (rawMask & (1ULL << 2)) mask |= SHOW_VAR_PRIV_AUDIT; + if (rawMask & (1ULL << 3)) mask |= SHOW_VAR_PRIV_DEBUG; + return mask; +} +#endif + +static SArray *initVariablesFromItems(SArray *pItems, const char* likePattern, uint8_t showPrivMask) { if (pItems == NULL) { return NULL; } @@ -1251,6 +1287,11 @@ static SArray *initVariablesFromItems(SArray *pItems, const char* likePattern) { if (likePattern != NULL && rawStrPatternMatch(pItem->name, likePattern) != TSDB_PATTERN_MATCH) { continue; } +#ifdef TD_ENTERPRISE + if (!mndShowVarPrivAllowed(showPrivMask, pItem->privType)) { + continue; + } +#endif // init info value switch (pItem->dtype) { @@ -1319,7 +1360,9 @@ static int32_t mndProcessShowVariablesReq(SRpcMsg *pReq) { SShowVariablesRsp rsp = {0}; int32_t code = TSDB_CODE_SUCCESS; SShowVariablesReq req = {0}; - SArray *array = NULL; + SUserObj *pUser = NULL; + uint8_t showPrivMask = 0; + SMnode *pMnode = pReq->info.node; code = tDeserializeSShowVariablesReq(pReq->pCont, pReq->contLen, &req); if (code != 0) { @@ -1327,13 +1370,19 @@ static int32_t mndProcessShowVariablesReq(SRpcMsg *pReq) { goto _OVER; } - if ((code = mndCheckOperPrivilege(pReq->info.node, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_SHOW_VARIABLES)) != 0) { + if ((code = mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_SHOW_VARIABLES)) != 0) { goto _OVER; } + if ((code = mndAcquireUser(pMnode, RPC_MSG_USER(pReq), &pUser)) != 0) { + goto _OVER; + } +#ifdef TD_ENTERPRISE + showPrivMask = mndBuildShowVarPrivMask(pMnode, pUser, RPC_MSG_TOKEN(pReq)); +#endif SVariablesInfo info = {0}; char *likePattern = req.opType == OP_TYPE_LIKE ? req.val : NULL; - rsp.variables = initVariablesFromItems(taosGetGlobalCfg(tsCfg), likePattern); + rsp.variables = initVariablesFromItems(taosGetGlobalCfg(tsCfg), likePattern, showPrivMask); if (rsp.variables == NULL) { code = terrno; goto _OVER; @@ -1360,6 +1409,7 @@ static int32_t mndProcessShowVariablesReq(SRpcMsg *pReq) { if (code != 0) { mError("failed to get show variables info since %s", tstrerror(code)); } + mndReleaseUser(pMnode, pUser); tFreeSShowVariablesReq(&req); tFreeSShowVariablesRsp(&rsp); TAOS_RETURN(code); diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c index 1cc60f1b4d6b..42ef9ef3f470 100644 --- a/source/dnode/mnode/impl/src/mndDb.c +++ b/source/dnode/mnode/impl/src/mndDb.c @@ -2857,7 +2857,9 @@ static int32_t mndProcessTrimDbReq(SRpcMsg *pReq) { TAOS_CHECK_EXIT(code); } - TAOS_CHECK_EXIT(mndCheckDbPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_TRIM_DB, pDb)); + TAOS_CHECK_EXIT(mndCheckDbPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), + trimReq.optrType == TSDB_OPTR_ROLLUP ? MND_OPER_ROLLUP_DB : MND_OPER_TRIM_DB, + pDb)); if (pDb->cfg.isMount) { TAOS_CHECK_EXIT(TSDB_CODE_MND_MOUNT_OBJ_NOT_SUPPORT); diff --git a/source/dnode/mnode/impl/src/mndMount.c b/source/dnode/mnode/impl/src/mndMount.c index 6c86c4c200c7..a419a1273bf2 100644 --- a/source/dnode/mnode/impl/src/mndMount.c +++ b/source/dnode/mnode/impl/src/mndMount.c @@ -518,8 +518,7 @@ static int32_t mndProcessCreateMountReq(SRpcMsg *pReq) { goto _exit; } } - // mount operation share the privileges of db - TAOS_CHECK_EXIT(mndCheckDbPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_CREATE_MOUNT, (SDbObj *)pObj)); + TAOS_CHECK_EXIT(mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_CREATE_MOUNT)); TAOS_CHECK_EXIT(grantCheck(TSDB_GRANT_MOUNT)); TAOS_CHECK_EXIT(mndAcquireUser(pMnode, RPC_MSG_USER(pReq), &pUser)); char fullMountName[TSDB_MOUNT_NAME_LEN + 32] = {0}; @@ -689,8 +688,7 @@ static int32_t mndProcessDropMountReq(SRpcMsg *pReq) { goto _exit; } - // mount operation share the privileges of db - TAOS_CHECK_GOTO(mndCheckDbPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_DROP_MOUNT, (SDbObj *)pObj), NULL, _exit); + TAOS_CHECK_GOTO(mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_DROP_MOUNT), NULL, _exit); code = mndDropMount(pMnode, pReq, pObj); if (code == TSDB_CODE_SUCCESS) { diff --git a/source/dnode/mnode/impl/src/mndPrivilege.c b/source/dnode/mnode/impl/src/mndPrivilege.c index 7af6b1530baf..08ec351ef28a 100644 --- a/source/dnode/mnode/impl/src/mndPrivilege.c +++ b/source/dnode/mnode/impl/src/mndPrivilege.c @@ -52,6 +52,13 @@ int32_t mndCheckSysObjPrivilege(SMnode *pMnode, SUserObj *pUser, const char *tok EPrivObjType objType, int64_t ownerId, const char *objFName, const char *tbName) { return 0; } +uint64_t mndBuildSysPrivBatchMask(SMnode *pMnode, SUserObj *pUser, const char *token, + const EPrivType *privTypes, int32_t numPrivTypes) { + if (numPrivTypes <= 0) { + return 0; + } + return numPrivTypes >= 64 ? UINT64_MAX : ((1ULL << numPrivTypes) - 1); +} int32_t mndCheckObjPrivilegeRec(SMnode *pMnode, SUserObj *pUser, EPrivType privType, EPrivObjType objType, int64_t ownerId, int32_t acctId, const char *objName, const char *tbName) { return 0; diff --git a/source/dnode/mnode/impl/src/mndSma.c b/source/dnode/mnode/impl/src/mndSma.c index a3d4ea68cb37..4fac77afa3b0 100644 --- a/source/dnode/mnode/impl/src/mndSma.c +++ b/source/dnode/mnode/impl/src/mndSma.c @@ -1461,7 +1461,7 @@ static int32_t mndRetrieveTSMA(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlo showAll = (0 == mndCheckSysObjPrivilege(pMnode, pUser, RPC_MSG_TOKEN(pReq), PRIV_CM_SHOW, PRIV_OBJ_TSMA, 0, objFName, objLevel == 0 ? NULL : "*")); if (!showAll && pShow->db[0] != 0) { - showAll = (0 == mndCheckSysObjPrivilege(pMnode, pUser, RPC_MSG_TOKEN(pReq), PRIV_CM_SHOW, PRIV_OBJ_TSMA, pUser->uid, + showAll = (0 == mndCheckSysObjPrivilege(pMnode, pUser, RPC_MSG_TOKEN(pReq), PRIV_CM_SHOW, PRIV_OBJ_TSMA, pDb->ownerId, pShow->db, objLevel == 0 ? NULL : "*")); } diff --git a/source/dnode/mnode/impl/src/mndSubscribe.c b/source/dnode/mnode/impl/src/mndSubscribe.c index bab8888cfeb9..bc29c000af0a 100644 --- a/source/dnode/mnode/impl/src/mndSubscribe.c +++ b/source/dnode/mnode/impl/src/mndSubscribe.c @@ -1829,7 +1829,9 @@ static int32_t retrieveSub(SRpcMsg *pReq, SMqSubscribeObj *pSub, SUserObj *pOper varDataSetLen(cgroup, strlen(varDataVal(cgroup))); if (!showAll) { - (void)mndAcquireTopic(pMnode, topic, &pTopic); + char topicFName[TSDB_TOPIC_FNAME_LEN + 1] = {0}; + (void)snprintf(topicFName, sizeof(topicFName), "%d.%s", pOperUser->acctId, varDataVal(topic)); + (void)mndAcquireTopic(pMnode, topicFName, &pTopic); if (pTopic) { SName name = {0}; // 1.topic1 if (0 == tNameFromString(&name, pTopic->name, T_NAME_ACCT | T_NAME_DB)) { diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c index fa74dc32b308..3243f60a6e3c 100644 --- a/source/libs/command/src/command.c +++ b/source/libs/command/src/command.c @@ -1254,7 +1254,7 @@ static int32_t buildLocalVariablesResultDataBlock(SSDataBlock** pOutput) { return terrno; } -static int32_t execShowLocalVariables(SShowStmt* pStmt, SRetrieveTableRsp** pRsp) { +static int32_t execShowLocalVariables(SShowStmt* pStmt, uint8_t showVarPrivMask, SRetrieveTableRsp** pRsp) { SSDataBlock* pBlock = NULL; char* likePattern = NULL; int32_t code = buildLocalVariablesResultDataBlock(&pBlock); @@ -1264,7 +1264,7 @@ static int32_t execShowLocalVariables(SShowStmt* pStmt, SRetrieveTableRsp** pRsp } } if (TSDB_CODE_SUCCESS == code) { - code = dumpConfToDataBlock(pBlock, 0, likePattern); + code = dumpConfToDataBlock(pBlock, 0, likePattern, showVarPrivMask); } if (TSDB_CODE_SUCCESS == code) { code = buildRetrieveTableRsp(pBlock, SHOW_LOCAL_VARIABLES_RESULT_COLS, pRsp); @@ -1363,8 +1363,8 @@ static int32_t execShowCreateRsma(SShowCreateRsmaStmt* pStmt, SRetrieveTableRsp* return code; } -int32_t qExecCommand(int64_t* pConnId, bool sysInfoUser, SNode* pStmt, SRetrieveTableRsp** pRsp, int8_t biMode, - void* charsetCxt) { +int32_t qExecCommand(int64_t* pConnId, bool sysInfoUser, uint8_t showVarPrivMask, SNode* pStmt, + SRetrieveTableRsp** pRsp, int8_t biMode, void* charsetCxt) { switch (nodeType(pStmt)) { case QUERY_NODE_DESCRIBE_STMT: return execDescribe(sysInfoUser, pStmt, pRsp, biMode); @@ -1385,7 +1385,7 @@ int32_t qExecCommand(int64_t* pConnId, bool sysInfoUser, SNode* pStmt, SRetrieve case QUERY_NODE_ALTER_LOCAL_STMT: return execAlterLocal((SAlterLocalStmt*)pStmt); case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT: - return execShowLocalVariables((SShowStmt*)pStmt, pRsp); + return execShowLocalVariables((SShowStmt*)pStmt, showVarPrivMask, pRsp); case QUERY_NODE_SELECT_STMT: return execSelectWithoutFrom((SSelectStmt*)pStmt, pRsp); default: diff --git a/source/libs/executor/src/sysscanoperator.c b/source/libs/executor/src/sysscanoperator.c index 221a15a96c1b..c78b097a7f22 100644 --- a/source/libs/executor/src/sysscanoperator.c +++ b/source/libs/executor/src/sysscanoperator.c @@ -35,6 +35,7 @@ #include "storageapi.h" #include "tcompare.h" #include "thash.h" +#include "tref.h" #include "trpc.h" #include "ttypes.h" // RPC timeout for virtual table reference validation (5 seconds) @@ -79,6 +80,8 @@ typedef struct SSysTableScanInfo { SRetrieveTableReq req; SEpSet epSet; tsem_t ready; + int64_t self; // ref ID in sysTableScanRefPool (for callback safety) + int32_t rspCode; // error code set by the RPC callback SReadHandle readHandle; const char* pUser; int32_t accountId; @@ -124,12 +127,28 @@ typedef struct SSysTableScanInfo { STableListInfo* pSubTableListInfo; } SSysTableScanInfo; -typedef struct SSysTableLoadCtx { - tsem_t ready; - SRetrieveMetaTableRsp* pRsp; - int32_t rspCode; - int32_t refs; -} SSysTableLoadCtx; +// Lightweight wrapper passed as RPC callback param; stores only the ref ID so +// the callback can safely acquire the SSysTableScanInfo from the ref pool. +typedef struct SSysTableScanCbParam { + int64_t sysTableScanId; +} SSysTableScanCbParam; + +// Per-file ref pool used to decouple the callback lifetime from the operator +// lifetime, following the same pattern as fetchObjRefPool in exchangeoperator.c. +static int32_t sysTableScanRefPool = -1; +static TdThreadOnce sysTableScanRefPoolOnce = PTHREAD_ONCE_INIT; + +static void doDestroySysTableScanInfo(void* param); + +static void cleanupSysTableScanRefPool(void) { + int32_t ref = atomic_val_compare_exchange_32(&sysTableScanRefPool, sysTableScanRefPool, 0); + taosCloseRef(ref); +} + +static void initSysTableScanRefPool(void) { + sysTableScanRefPool = taosOpenRef(64, doDestroySysTableScanInfo); + (void)atexit(cleanupSysTableScanRefPool); +} typedef struct { const char* name; @@ -208,25 +227,6 @@ static void destroySysScanOperator(void* param); static int32_t loadSysTableCallback(void* param, SDataBuf* pMsg, int32_t code); static __optSysFilter optSysGetFilterFunc(int32_t ctype, bool* reverse, bool* equal); -static void freeSysTableLoadCtx(void* param) { - SSysTableLoadCtx* pCtx = (SSysTableLoadCtx*)param; - if (pCtx == NULL) { - return; - } - - if (atomic_sub_fetch_32(&pCtx->refs, 1) != 0) { - return; - } - - int32_t code = tsem_destroy(&pCtx->ready); - if (code != TSDB_CODE_SUCCESS) { - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code)); - } - - taosMemoryFreeClear(pCtx->pRsp); - taosMemoryFreeClear(pCtx); -} - static int32_t sysTableUserTagsFillOneTableTags(const SSysTableScanInfo* pInfo, SMetaReader* smrSuperTable, SMetaReader* smrChildTable, const char* dbname, const char* tableName, int32_t* pNumOfRows, const SSDataBlock* dataBlock); @@ -4945,32 +4945,25 @@ static SSDataBlock* sysTableScanFromMNode(SOperatorInfo* pOperator, SSysTableSca return NULL; } - SSysTableLoadCtx* pLoadCtx = taosMemoryCalloc(1, sizeof(SSysTableLoadCtx)); - if (pLoadCtx == NULL) { - qError("%s prepare callback context failed", GET_TASKID(pTaskInfo)); - pTaskInfo->code = terrno; - taosMemoryFree(buf1); - taosMemoryFree(pMsgSendInfo); - return NULL; - } + int32_t msgType = (strcasecmp(name, TSDB_INS_TABLE_DNODE_VARIABLES) == 0) ? TDMT_DND_SYSTABLE_RETRIEVE + : TDMT_MND_SYSTABLE_RETRIEVE; - code = tsem_init(&pLoadCtx->ready, 0, 0); - if (code != TSDB_CODE_SUCCESS) { - qError("%s init callback context failed since %s", GET_TASKID(pTaskInfo), tstrerror(code)); + // Allocate a lightweight wrapper that holds only the ref ID; the callback + // frees it via paramFreeFp = taosAutoMemoryFree after the callback returns. + SSysTableScanCbParam* pWrapper = taosMemoryCalloc(1, sizeof(SSysTableScanCbParam)); + if (!pWrapper) { + pTaskInfo->code = terrno; taosMemoryFree(buf1); taosMemoryFree(pMsgSendInfo); - taosMemoryFree(pLoadCtx); - pTaskInfo->code = code; - return NULL; + T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); } - pLoadCtx->rspCode = TSDB_CODE_SUCCESS; - pLoadCtx->refs = 2; + pWrapper->sysTableScanId = pInfo->self; - int32_t msgType = (strcasecmp(name, TSDB_INS_TABLE_DNODE_VARIABLES) == 0) ? TDMT_DND_SYSTABLE_RETRIEVE - : TDMT_MND_SYSTABLE_RETRIEVE; + // reset rspCode from the previous iteration + pInfo->rspCode = 0; - pMsgSendInfo->param = pLoadCtx; - pMsgSendInfo->paramFreeFp = freeSysTableLoadCtx; + pMsgSendInfo->param = pWrapper; + pMsgSendInfo->paramFreeFp = taosAutoMemoryFree; pMsgSendInfo->msgInfo.pData = buf1; pMsgSendInfo->msgInfo.len = contLen; pMsgSendInfo->msgType = msgType; @@ -4979,31 +4972,24 @@ static SSDataBlock* sysTableScanFromMNode(SOperatorInfo* pOperator, SSysTableSca code = asyncSendMsgToServer(pInfo->readHandle.pMsgCb->clientRpc, &pInfo->epSet, NULL, pMsgSendInfo); if (code != TSDB_CODE_SUCCESS) { - freeSysTableLoadCtx(pLoadCtx); qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code)); pTaskInfo->code = code; T_LONG_JMP(pTaskInfo->env, code); } - code = tsem_timewait(&pLoadCtx->ready, VTB_REF_RPC_TIMEOUT_MS); + // Block this worker thread until the response arrives. qSemWait notifies + // the worker pool and waits, then re-acquires on wake-up. + code = qSemWait((qTaskInfo_t)pTaskInfo, &pInfo->ready); if (code != TSDB_CODE_SUCCESS) { - freeSysTableLoadCtx(pLoadCtx); - qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code)); + qError("%s tsem_wait failed at line %d since %s", __func__, __LINE__, tstrerror(code)); pTaskInfo->code = code; T_LONG_JMP(pTaskInfo->env, code); } - if (pLoadCtx->rspCode != TSDB_CODE_SUCCESS) { - pTaskInfo->code = pLoadCtx->rspCode; - } else { - pInfo->pRsp = pLoadCtx->pRsp; - pLoadCtx->pRsp = NULL; - } - freeSysTableLoadCtx(pLoadCtx); - - if (pTaskInfo->code) { + if (pInfo->rspCode != TSDB_CODE_SUCCESS) { qError("%s load meta data from mnode failed, totalRows:%" PRIu64 ", code:%s", GET_TASKID(pTaskInfo), - pInfo->loadInfo.totalRows, tstrerror(pTaskInfo->code)); + pInfo->loadInfo.totalRows, tstrerror(pInfo->rspCode)); + pTaskInfo->code = pInfo->rspCode; return NULL; } @@ -5187,6 +5173,17 @@ int32_t createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNo } pInfo->epSet = pScanPhyNode->mgmtEpSet; pInfo->readHandle = *(SReadHandle*)readHandle; + + // Register pInfo in the per-file ref pool so that loadSysTableCallback can + // safely acquire/release it even after the operator has been destroyed. + (void)taosThreadOnce(&sysTableScanRefPoolOnce, initSysTableScanRefPool); + int64_t refId = taosAddRef(sysTableScanRefPool, pInfo); + if (refId < 0) { + qError("%s failed to add ref for sysTableScan since %s", GET_TASKID(pTaskInfo), tstrerror(terrno)); + code = terrno; + goto _error; + } + pInfo->self = refId; } pInfo->pSubTableListInfo = pTableListInfo; @@ -5236,7 +5233,13 @@ void extractTbnameSlotId(SSysTableScanInfo* pInfo, const SScanPhysiNode* pScanNo } } -void destroySysScanOperator(void* param) { +// doDestroySysTableScanInfo: actual teardown for SSysTableScanInfo. +// For operators that use the ref pool (MNode path, self > 0), this function +// is the pool destructor invoked automatically when the last ref is dropped +// via taosRemoveRef / taosReleaseRef — do NOT call it directly on those. +// For local-scan operators (self == 0), destroySysScanOperator calls it +// directly since there is no ref pool involved. +static void doDestroySysTableScanInfo(void* param) { SSysTableScanInfo* pInfo = (SSysTableScanInfo*)param; int32_t code = tsem_destroy(&pInfo->ready); if (code != TSDB_CODE_SUCCESS) { @@ -5284,32 +5287,73 @@ void destroySysScanOperator(void* param) { taosMemoryFreeClear(param); } -int32_t loadSysTableCallback(void* param, SDataBuf* pMsg, int32_t code) { - SSysTableLoadCtx* pCtx = (SSysTableLoadCtx*)param; - if (pCtx == NULL) { +// destroySysScanOperator: operator destroy callback. For operators that use +// the ref pool (MNode path), we just remove our reference — actual cleanup +// happens inside doDestroySysTableScanInfo when all refs are released. For +// local-scan operators (no ref pool entry), do the teardown inline. +static void destroySysScanOperator(void* param) { + SSysTableScanInfo* pInfo = (SSysTableScanInfo*)param; + if (pInfo->self > 0) { + // MNode path: remove the operator's own ref; the pool calls + // doDestroySysTableScanInfo when all refs (operator + any in-flight + // callbacks) are dropped. + int32_t refCode = taosRemoveRef(sysTableScanRefPool, pInfo->self); + if (refCode != TSDB_CODE_SUCCESS) { + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(refCode)); + } + } else { + // Local scan path: no ref pool — destroy directly. + doDestroySysTableScanInfo(pInfo); + } +} + +static int32_t loadSysTableCallback(void* param, SDataBuf* pMsg, int32_t code) { + SSysTableScanCbParam* pWrapper = (SSysTableScanCbParam*)param; + + // Acquire the SSysTableScanInfo from the ref pool. If it returns NULL the + // operator has already been destroyed — discard the response safely. + SSysTableScanInfo* pInfo = (SSysTableScanInfo*)taosAcquireRef(sysTableScanRefPool, pWrapper->sysTableScanId); + if (pInfo == NULL) { + // Operator is gone; free the response payload and bail out. + taosMemoryFree(pMsg->pData); + taosMemoryFree(pMsg->pEpSet); return TSDB_CODE_SUCCESS; } if (TSDB_CODE_SUCCESS == code) { - pCtx->pRsp = pMsg->pData; - pMsg->pData = NULL; - pCtx->rspCode = TSDB_CODE_SUCCESS; + pInfo->pRsp = pMsg->pData; - SRetrieveMetaTableRsp* pRsp = pCtx->pRsp; + SRetrieveMetaTableRsp* pRsp = pInfo->pRsp; pRsp->numOfRows = htonl(pRsp->numOfRows); pRsp->useconds = htobe64(pRsp->useconds); pRsp->handle = htobe64(pRsp->handle); pRsp->compLen = htonl(pRsp->compLen); } else { - pCtx->rspCode = rpcCvtErrCode(code); - if (pCtx->rspCode != code) { - qError("load systable rsp received, error:%s, cvted error:%s", tstrerror(code), tstrerror(pCtx->rspCode)); + int32_t cvtCode = rpcCvtErrCode(code); + if (cvtCode != code) { + qError("load systable rsp received, error:%s, cvted error:%s", tstrerror(code), tstrerror(cvtCode)); } else { qError("load systable rsp received, error:%s", tstrerror(code)); } + pInfo->rspCode = cvtCode; + taosMemoryFree(pMsg->pData); } + taosMemoryFree(pMsg->pEpSet); - int32_t res = tsem_post(&pCtx->ready); + // Release our acquired ref BEFORE posting the semaphore. + // If we post first, the waiter can race ahead: task completes → taosRemoveRef + // drops the count to 1, then doDestroyTask frees the task memory pool (which + // owns pInfo). Our subsequent taosReleaseRef would then drop the count to 0 + // and call doDestroySysTableScanInfo on already-freed memory. + // By releasing first (count 2→1, destructor not triggered), pInfo remains + // valid for the tsem_post call below, and doDestroySysTableScanInfo is + // called only later, inside destroySysScanOperator, when pInfo is still live. + int32_t refCode = taosReleaseRef(sysTableScanRefPool, pWrapper->sysTableScanId); + if (refCode != TSDB_CODE_SUCCESS) { + qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(refCode)); + } + + int32_t res = tsem_post(&pInfo->ready); if (res != TSDB_CODE_SUCCESS) { qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(res)); } diff --git a/source/libs/parser/inc/parInt.h b/source/libs/parser/inc/parInt.h index 82228568b087..3def97fcc9c7 100644 --- a/source/libs/parser/inc/parInt.h +++ b/source/libs/parser/inc/parInt.h @@ -59,6 +59,8 @@ void getExprSubQueryResType(SNode* pNode, SDataType* pType); int32_t validateExprSubQuery(SNode* pNode); void getExprSubQueryResCols(SNode* pNode, int32_t* cols); +EPrivType getAlterUserPrivType(const char* pCurrentUser, const SAlterUserStmt* pStmt); + #ifdef TD_ENTERPRISE int32_t translateView(STranslateContext* pCxt, SNode** pTable, SName* pName, bool inJoin); int32_t getViewMetaFromMetaCache(STranslateContext* pCxt, SName* pName, SViewMeta** ppViewMeta); diff --git a/source/libs/parser/inc/parTranslater.h b/source/libs/parser/inc/parTranslater.h index 9836d71b37a1..51530faa6cbb 100644 --- a/source/libs/parser/inc/parTranslater.h +++ b/source/libs/parser/inc/parTranslater.h @@ -55,6 +55,7 @@ typedef struct STranslateContext { bool skipCheck; bool refTable; bool isCurrOpIn; + ENodeType origStmtType; SParseStreamInfo streamInfo; } STranslateContext; diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c index 413458ed8bb3..663e45564ee8 100644 --- a/source/libs/parser/src/parAstParser.c +++ b/source/libs/parser/src/parAstParser.c @@ -1469,7 +1469,12 @@ static int32_t collectMetaKeyFromShowMounts(SCollectMetaKeyCxt* pCxt, SShowStmt* } static int32_t collectMetaKeyFromShowCreateDatabase(SCollectMetaKeyCxt* pCxt, SShowCreateDatabaseStmt* pStmt) { - return reserveDbCfgInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache); + int32_t code = reserveDbCfgInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache); + if (TSDB_CODE_SUCCESS == code) { + code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pStmt->dbName, NULL, + PRIV_CM_SHOW_CREATE, PRIV_OBJ_DB, pCxt->pMetaCache); + } + return code; } static int32_t collectMetaKeyFromShowCreateTable(SCollectMetaKeyCxt* pCxt, SShowCreateTableStmt* pStmt) { @@ -1945,6 +1950,31 @@ static int32_t collectMetaKeyFromAlterLocalStmt(SCollectMetaKeyCxt* pCxt, SAlter return TSDB_CODE_SUCCESS; } +EPrivType getAlterUserPrivType(const char* pCurrentUser, const SAlterUserStmt* pStmt) { + EPrivType privType = PRIV_USER_ALTER; + SUserOptions* pOptions = pStmt->pUserOptions; + if ((pOptions->hasPassword) && + !(pOptions->hasTotpseed || pOptions->hasEnable || pOptions->hasSysinfo || pOptions->hasIsImport || + pOptions->hasChangepass || pOptions->hasCreatedb || pOptions->hasSessionPerUser || pOptions->hasConnectTime || + pOptions->hasConnectIdleTime || pOptions->hasCallPerSession || pOptions->hasVnodePerCall || + pOptions->hasFailedLoginAttempts || pOptions->hasPasswordLifeTime || pOptions->hasPasswordReuseTime || + pOptions->hasPasswordReuseMax || pOptions->hasPasswordLockTime || pOptions->hasPasswordGraceTime || + pOptions->hasInactiveAccountTime || pOptions->hasAllowTokenNum || pOptions->pSecurityLevels)) { + if (pCurrentUser && strcmp(pCurrentUser, pStmt->userName) == 0) { + privType = PRIV_PASS_ALTER_SELF; + } else { + privType = PRIV_PASS_ALTER; + } + } + return privType; +} + +static int32_t collectMetaKeyFromAlterUserStmt(SCollectMetaKeyCxt* pCxt, SAlterUserStmt* pStmt) { + EPrivType privType = getAlterUserPrivType(pCxt->pParseCxt->pUser, pStmt); + return reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, NULL, NULL, privType, 0, + pCxt->pMetaCache); +} + static int32_t collectMetaKeyFromSysPrivStmt(SCollectMetaKeyCxt* pCxt, EPrivType privType) { return reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, NULL, NULL, privType, 0, pCxt->pMetaCache); @@ -2343,7 +2373,7 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) { code = collectMetaKeyFromSysPrivStmt(pCxt, PRIV_USER_CREATE); break; case QUERY_NODE_ALTER_USER_STMT: - code = collectMetaKeyFromSysPrivStmt(pCxt, PRIV_USER_ALTER); + code = collectMetaKeyFromAlterUserStmt(pCxt, (SAlterUserStmt*)pStmt); break; case QUERY_NODE_DROP_USER_STMT: code = collectMetaKeyFromSysPrivStmt(pCxt, PRIV_USER_DROP); diff --git a/source/libs/parser/src/parAuthenticator.c b/source/libs/parser/src/parAuthenticator.c index 6abada2a9468..3b30f0f7d12f 100644 --- a/source/libs/parser/src/parAuthenticator.c +++ b/source/libs/parser/src/parAuthenticator.c @@ -1027,6 +1027,11 @@ static int32_t authAlterLocal(SAuthCxt* pCxt, SAlterLocalStmt* pStmt) { return authSysPrivileges(pCxt, (void*)pStmt, privType); } +static int32_t authAlterUser(SAuthCxt* pCxt, SAlterUserStmt* pStmt) { + EPrivType privType = getAlterUserPrivType(pCxt->pParseCxt->pUser, pStmt); + return authSysPrivileges(pCxt, (void*)pStmt, privType); +} + static int32_t authDropRole(SAuthCxt* pCxt, SDropRoleStmt* pStmt) { return authSysPrivileges(pCxt, (SNode*)pStmt, PRIV_ROLE_DROP); } @@ -1098,7 +1103,7 @@ static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) { case QUERY_NODE_CREATE_USER_STMT: return authSysPrivileges(pCxt, pStmt, PRIV_USER_CREATE); case QUERY_NODE_ALTER_USER_STMT: - return authSysPrivileges(pCxt, pStmt, PRIV_USER_ALTER); + return authAlterUser(pCxt, (SAlterUserStmt*)pStmt); case QUERY_NODE_DROP_USER_STMT: return authDropUser(pCxt, (SDropUserStmt*)pStmt); case QUERY_NODE_DELETE_STMT: @@ -1132,17 +1137,19 @@ static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) { case QUERY_NODE_SHOW_BACKUP_NODES_STMT: case QUERY_NODE_SHOW_DB_ALIVE_STMT: // case QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT: - case QUERY_NODE_SHOW_CREATE_DATABASE_STMT: case QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT: // TODO: check in mnode // case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT: // not check local variables case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT: case QUERY_NODE_SHOW_SCORES_STMT: case QUERY_NODE_SHOW_ARBGROUPS_STMT: case QUERY_NODE_SHOW_ENCRYPTIONS_STMT: - case QUERY_NODE_SHOW_MOUNTS_STMT: case QUERY_NODE_SHOW_ENCRYPT_ALGORITHMS_STMT: case QUERY_NODE_SHOW_ENCRYPT_STATUS_STMT: return !pCxt->pParseCxt->enableSysInfo ? TSDB_CODE_PAR_PERMISSION_DENIED : TSDB_CODE_SUCCESS; + case QUERY_NODE_SHOW_CREATE_DATABASE_STMT: + return authObjPrivileges(pCxt, ((SShowCreateDatabaseStmt*)pStmt)->dbName, NULL, PRIV_CM_SHOW_CREATE, PRIV_OBJ_DB); + case QUERY_NODE_SHOW_MOUNTS_STMT: + return authSysPrivileges(pCxt, pStmt, PRIV_MOUNT_SHOW); case QUERY_NODE_SHOW_USERS_STMT: case QUERY_NODE_SHOW_USERS_FULL_STMT: return authSysPrivileges(pCxt, pStmt, PRIV_USER_SHOW); @@ -1157,10 +1164,8 @@ static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) { case QUERY_NODE_SHOW_QNODES_STMT: case QUERY_NODE_SHOW_SNODES_STMT: case QUERY_NODE_SHOW_BNODES_STMT: - return authSysPrivileges(pCxt, pStmt, PRIV_NODES_SHOW); case QUERY_NODE_SHOW_ANODES_STMT: case QUERY_NODE_SHOW_ANODES_FULL_STMT: - return TSDB_CODE_SUCCESS; case QUERY_NODE_SHOW_XNODES_STMT: case QUERY_NODE_SHOW_XNODE_AGENTS_STMT: return authSysPrivileges(pCxt, pStmt, PRIV_NODES_SHOW); @@ -1253,6 +1258,8 @@ static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) { return authSysPrivileges(pCxt, pStmt, PRIV_TRANS_KILL); case QUERY_NODE_SHOW_QUERIES_STMT: return authSysPrivileges(pCxt, pStmt, PRIV_QUERY_SHOW); + case QUERY_NODE_SHOW_CONNECTIONS_STMT: + return authSysPrivileges(pCxt, pStmt, PRIV_CONN_SHOW); case QUERY_NODE_KILL_QUERY_STMT: return authSysPrivileges(pCxt, pStmt, PRIV_QUERY_KILL); case QUERY_NODE_KILL_CONNECTION_STMT: diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index b9d2bd5da0dc..c67700dff5c4 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1134,6 +1134,7 @@ static int32_t initTranslateContext(SParseContext* pParseCxt, SParseMetaCache* p pCxt->currLevel = 0; pCxt->levelNo = 0; pCxt->currClause = 0; + pCxt->origStmtType = 0; pCxt->pMetaCache = pMetaCache; pCxt->pDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); pCxt->pTables = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); @@ -7199,6 +7200,49 @@ static bool isVirtualTable(STableMeta* meta) { static bool isVirtualSTable(STableMeta* meta) { return meta->virtualStb; } +#ifdef TD_ENTERPRISE +static bool transBypassSysTablePrivForShow(STranslateContext* pCxt, ENodeType stmtType) { + if (!pCxt->showRewrite || stmtType <= 0) { + return false; + } + return true; +} + +static int32_t transCheckSysTablePriv(STranslateContext* pCxt, const char* dbName, const char* tableName) { + SParseContext* pParCxt = pCxt->pParseCxt; + // keep the order of below codes unchanged + if (pParCxt->isSuperUser) return 0; // step 1 + if (transBypassSysTablePrivForShow(pCxt, pCxt->origStmtType)) return 0; // step 2 + if ((pParCxt->privInfo & 0x01F8u) == 0x01F8u) return 0; // step 3 + + const SSysTableMeta* pMeta = getSysTableMeta(dbName, tableName); + if (NULL == pMeta) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_TABLE_NOT_EXIST, "system table %s.%s does not exist", + dbName, tableName); + } + + bool isInfo = IS_INFORMATION_SCHEMA_DB(dbName); + bool allowed = false; + switch (pMeta->privCat) { + case PRIV_CAT_BASIC: + allowed = isInfo ? (pParCxt->privInfoBasic != 0) : (pParCxt->privPerfBasic != 0); + break; + case PRIV_CAT_PRIVILEGED: + allowed = isInfo ? (pParCxt->privInfoPrivileged != 0) : (pParCxt->privPerfPrivileged != 0); + break; + case PRIV_CAT_SECURITY: + allowed = (pParCxt->privInfoSec != 0); + break; + case PRIV_CAT_AUDIT: + allowed = (pParCxt->privInfoAudit != 0); + break; + default: + break; + } + return allowed ? 0 : TSDB_CODE_PAR_PERMISSION_DENIED; +} +#endif + static int32_t transSetSysDbPrivs(STranslateContext* pCxt, const char* qualDbName) { #ifdef TD_ENTERPRISE SParseContext* pParCxt = pCxt->pParseCxt; @@ -7273,7 +7317,10 @@ static int32_t translateRealTable(STranslateContext* pCxt, SNode** pTable, bool if (isSelectStmt(pCxt->pCurrStmt)) { ((SSelectStmt*)pCxt->pCurrStmt)->timeLineResMode = TIME_LINE_NONE; ((SSelectStmt*)pCxt->pCurrStmt)->timeLineCurMode = TIME_LINE_NONE; +#ifdef TD_ENTERPRISE PAR_ERR_JRET(transSetSysDbPrivs(pCxt, pRealTable->qualDbName)); + PAR_ERR_JRET(transCheckSysTablePriv(pCxt, pRealTable->table.dbName, pRealTable->table.tableName)); +#endif } else if (isDeleteStmt(pCxt->pCurrStmt)) { PAR_ERR_JRET(TSDB_CODE_TSC_INVALID_OPERATION); } @@ -14566,12 +14613,12 @@ static int32_t translateCheckUserOptsPriv(STranslateContext* pCxt, void* pStmt, "Permission denied to enable user"); } } else if (!PRIV_HAS(&authRsp.sysPrivs, PRIV_USER_LOCK)) { - return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_PERMISSION_DENIED, + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_PERMISSION_DENIED, "Permission denied to disable user"); } } - if (ops->hasChangepass) { + if (ops->hasPassword) { const char* targetUser = isAlter ? ((SAlterUserStmt*)pStmt)->userName : ((SCreateUserStmt*)pStmt)->userName; if (strncmp(authRsp.user, pParCxt->pUser, TSDB_USER_LEN) != 0) { if (!PRIV_HAS(&authRsp.sysPrivs, PRIV_PASS_ALTER)) { @@ -14594,10 +14641,10 @@ static int32_t translateCheckUserOptsPriv(STranslateContext* pCxt, void* pStmt, } } - if (ops->hasTotpseed || ops->hasSysinfo || ops->hasFailedLoginAttempts || ops->hasPasswordLifeTime || - ops->hasPasswordReuseTime || ops->hasPasswordReuseMax || ops->hasPasswordLockTime || ops->hasPasswordGraceTime || - ops->hasInactiveAccountTime || ops->hasAllowTokenNum || ops->pIpRanges || ops->pDropIpRanges || - ops->pTimeRanges || ops->pDropTimeRanges || ops->pSecurityLevels) { + if (ops->hasChangepass || ops->hasTotpseed || ops->hasSysinfo || ops->hasFailedLoginAttempts || + ops->hasPasswordLifeTime || ops->hasPasswordReuseTime || ops->hasPasswordReuseMax || ops->hasPasswordLockTime || + ops->hasPasswordGraceTime || ops->hasInactiveAccountTime || ops->hasAllowTokenNum || ops->pIpRanges || + ops->pDropIpRanges || ops->pTimeRanges || ops->pDropTimeRanges || ops->pSecurityLevels) { if (!PRIV_HAS(&authRsp.sysPrivs, PRIV_USER_SET_SECURITY)) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_PERMISSION_DENIED, "Permission denied to set user security info"); @@ -27227,6 +27274,7 @@ static int32_t rewriteShowXnodeStmt(STranslateContext* pCxt, SQuery* pQuery) { static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) { int32_t code = TSDB_CODE_SUCCESS; + pCxt->origStmtType = nodeType(pQuery->pRoot); switch (nodeType(pQuery->pRoot)) { case QUERY_NODE_SHOW_LICENCES_STMT: case QUERY_NODE_SHOW_DATABASES_STMT: diff --git a/source/libs/planner/test/planTestUtil.cpp b/source/libs/planner/test/planTestUtil.cpp index 93129221fe4d..fe7eeac2c888 100644 --- a/source/libs/planner/test/planTestUtil.cpp +++ b/source/libs/planner/test/planTestUtil.cpp @@ -363,6 +363,7 @@ class PlannerTestBaseImpl { cxt.msgLen = stmtEnv_.msgBuf_.max_size(); cxt.svrVer = "3.0.0.0"; cxt.enableSysInfo = true; + cxt.isSuperUser = true; if (prepare) { SStmtCallback stmtCb = {0}; cxt.pStmtCb = &stmtCb; diff --git a/test/cases/24-Users/test_user_cloud_compatible.py b/test/cases/24-Users/test_user_cloud_compatible.py index 81ee47addcf5..5e50ce3ee9d1 100644 --- a/test/cases/24-Users/test_user_cloud_compatible.py +++ b/test/cases/24-Users/test_user_cloud_compatible.py @@ -733,7 +733,7 @@ def do_topic_privileges(self): self.subscribe_topic_failed( CLOUD_SUB_USER, PWD, "cloud_group1", CLOUD_TOPIC, - TSDB_CODE_MND_NO_RIGHTS, + TSDB_CODE_PAR_DB_USE_PERMISSION_DENIED, ) tdLog.info(" sub_user subscribe without privilege blocked OK") @@ -768,7 +768,7 @@ def do_topic_privileges(self): self.subscribe_topic_failed( CLOUD_SUB_USER, PWD, "cloud_group2", CLOUD_TOPIC, - TSDB_CODE_MND_NO_RIGHTS, + TSDB_CODE_PAR_DB_USE_PERMISSION_DENIED, ) tdLog.info(" SUBSCRIBE revocation works OK") diff --git a/test/cases/24-Users/test_user_passwd.py b/test/cases/24-Users/test_user_passwd.py index 749a16b42375..0ba5a349d4f3 100644 --- a/test/cases/24-Users/test_user_passwd.py +++ b/test/cases/24-Users/test_user_passwd.py @@ -38,12 +38,12 @@ def test_passwd(self): apiPath = self.apiPath() tdLog.info(f"api path: {apiPath}") if platform.system().lower() == 'linux': - p = subprocess.Popen(f"cd {apiPath} && make", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p = subprocess.Popen(f"cd {apiPath} && make -f makefile_partial", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() if 0 != p.returncode: tdLog.exit("Test script passwdTest.c make failed") else: - p = subprocess.Popen(f"cd {apiPath} && jom -f makefile_win64.mak", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p = subprocess.Popen(f"cd {apiPath} && jom -f makefile_partial_win64.mak", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() if 0 != p.returncode: tdLog.exit("Test script passwdTest.c make failed") diff --git a/test/cases/24-Users/test_user_privilege_sysinfo.py b/test/cases/24-Users/test_user_privilege_sysinfo.py index 15afbc1943b9..6f60fb1187e3 100644 --- a/test/cases/24-Users/test_user_privilege_sysinfo.py +++ b/test/cases/24-Users/test_user_privilege_sysinfo.py @@ -163,7 +163,7 @@ def loop_check_sysinfo_0(): tdSql.query(f" show connections") tdSql.query(f" show apps") tdSql.query(f" show transactions") - tdSql.error(f"show create database d2") + tdSql.query(f"show create database d2") tdSql.query(f" show create table d2.stb2;") tdSql.query(f" show create table d2.ctb2;") tdSql.query(f" show create table d2.ntb2;") diff --git a/test/cases/25-Privileges/test_priv_control.py b/test/cases/25-Privileges/test_priv_control.py index c7fd46720bac..17697dabda14 100644 --- a/test/cases/25-Privileges/test_priv_control.py +++ b/test/cases/25-Privileges/test_priv_control.py @@ -236,6 +236,12 @@ def create_stable(self, db_name, stable_name, columns="ts TIMESTAMP, c1 INT", ta sql = f"CREATE STABLE {db_name}.{stable_name} ({columns}) TAGS ({tags})" tdSql.execute(sql) tdLog.info(f"Created stable: {db_name}.{stable_name}") + + def create_rsma(self, db_name, stable_name): + # Create a RSMA + sql = f"CREATE RSMA {stable_name}_rsma on {db_name}.{stable_name} function(avg(c1)) interval(1m,5m)" + tdSql.execute(sql) + tdLog.info(f"Created RSMA: {db_name}.{stable_name}_rsma") def create_table(self, db_name, table_name, columns="ts TIMESTAMP, c1 INT"): # Create a normal table @@ -602,10 +608,9 @@ def do_show_create_database_privilege(self): self.revoke_role("`SYSINFO_1`", user) #revoke default role # Test: user cannot show create database without privilege - '''BUG19 + '''BUG19''' self.login(user, pwd) self.exec_sql_failed(f"SHOW CREATE DATABASE {db_name}", TSDB_CODE_PAR_PERMISSION_DENIED) - ''' # Grant SHOW CREATE DATABASE privilege self.login() @@ -756,6 +761,8 @@ def do_rollup_database_privilege(self): db_name = "test_db" user = "test_user" self.create_database(db_name) + self.create_stable(db_name, "st1") + self.create_rsma(db_name, "st1") self.create_user(user, pwd) self.revoke_role("`SYSINFO_1`", user) #revoke default role @@ -772,9 +779,8 @@ def do_rollup_database_privilege(self): # Test: user can rollup database with privilege self.login(user, pwd) - '''BUG20 + '''BUG20 ''' self.exec_sql(f"ROLLUP DATABASE {db_name}") - ''' # Revoke self.login() @@ -2048,30 +2054,29 @@ def do_role_lock_unlock(self): lock_admin = "lock_admin" self.create_user(lock_admin, pwd) - '''BUG21 + '''BUG21''' self.grant_privilege("LOCK ROLE,UNLOCK ROLE", None, lock_admin) self.login(lock_admin, pwd) self.exec_sql(f"LOCK ROLE {role_name}") # Verify role is locked + tdSql.execute(f"reset query cache") self.login(user1, pwd) - self.exec_sql_failed(f"CREATE TABLE {db_name}.t4 (ts TIMESTAMP, c1 INT)", TSDB_CODE_PAR_PERMISSION_DENIED) + self.exec_sql_failed(f"CREATE TABLE {db_name}.t4 (ts TIMESTAMP, c1 INT)", TSDB_CODE_PAR_DB_USE_PERMISSION_DENIED) # Unlock as lock_admin self.login(lock_admin, pwd) self.exec_sql(f"UNLOCK ROLE {role_name}") self.login(user1, pwd) self.exec_sql(f"CREATE TABLE {db_name}.t4 (ts TIMESTAMP, c1 INT)") - ''' # Cleanup self.login() self.drop_database(db_name) self.drop_role(role_name) - '''BUG22 + '''BUG22''' self.drop_user(user1) self.drop_user(user2) self.drop_user(user3) self.drop_user(lock_admin) - ''' print("LOCK ROLE / UNLOCK ROLE .............. [ passed ] ") @@ -2345,7 +2350,7 @@ def do_totp_management_privileges(self): # Grant CREATE TOTP privilege self.login() - self.grant_privilege("CREATE TOTP", None, totp_admin) + self.grant_privilege("CREATE TOTP_SECRET", None, totp_admin) # Test: totp_admin can create TOTP self.login(totp_admin, pwd) @@ -2353,7 +2358,7 @@ def do_totp_management_privileges(self): # Grant DROP TOTP privilege self.login() - self.grant_privilege("DROP TOTP", None, totp_admin) + self.grant_privilege("DROP TOTP_SECRET", None, totp_admin) # Test: totp_admin can drop TOTP self.login(totp_admin, pwd) @@ -2381,7 +2386,7 @@ def do_password_management_privileges(self): # Test: Normal user cannot change others' password self.login(test_user, pwd) - self.exec_sql_failed(f"ALTER USER {pass_admin} PASS '{new_pwd}'", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed(f"ALTER USER {pass_admin} PASS '{new_pwd}'", TSDB_CODE_PAR_PERMISSION_DENIED) # Grant ALTER PASS privilege self.login() @@ -2390,14 +2395,16 @@ def do_password_management_privileges(self): # Test: pass_admin can change others' password self.login(pass_admin, pwd) #BUG12 - #self.exec_sql(f"ALTER USER {test_user} PASS '{new_pwd}'") + self.exec_sql(f"ALTER USER {test_user} PASS '{new_pwd}'") # Verify new password works - #self.login(test_user, new_pwd) + self.login(test_user, new_pwd) # Test: ALTER SELF PASS privilege self.login() self.drop_user(test_user) + tdSql.execute(f"reset query cache") self.create_user(test_user, pwd) # Recreate with original password + self.revoke_role("`SYSINFO_1`", test_user) # revoke default role self.grant_privilege("ALTER SELF PASS", None, test_user) self.login(test_user, pwd) @@ -2458,15 +2465,15 @@ def do_node_management_privileges(self): # Test have privilege self.login(test_user, pwd) #BUG13 - #self.exec_sql("CREATE DNODE 'localhost:6330'") - #self.exec_sql("CREATE MNODE ON DNODE 2") + self.exec_sql("CREATE DNODE 'localhost:6330'") + self.exec_sql("CREATE MNODE ON DNODE 2") self.exec_sql("CREATE SNODE ON DNODE 2") - #self.exec_sql("CREATE QNODE ON DNODE 2") - #self.exec_sql("DROP DNODE 4 FORCE") - #self.exec_sql("DROP DNODE 3") - #self.exec_sql("DROP MNODE ON DNODE 2") - #self.exec_sql("DROP SNODE ON DNODE 2") - #self.exec_sql("DROP QNODE ON DNODE 2") + self.exec_sql("CREATE QNODE ON DNODE 2") + self.exec_sql("DROP DNODE 4 FORCE") + self.exec_sql("DROP DNODE 3") + self.exec_sql("DROP MNODE ON DNODE 2") + self.exec_sql("DROP SNODE ON DNODE 2") + self.exec_sql("DROP QNODE ON DNODE 2") # Cleanup self.login() @@ -2490,7 +2497,7 @@ def do_mount_management_privileges(self): # Test: Normal user cannot show mounts self.login(test_user, pwd) #BUG13 - #self.exec_sql_failed("SHOW MOUNTS", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed("SHOW MOUNTS", TSDB_CODE_PAR_PERMISSION_DENIED) # Grant SHOW MOUNTS privilege self.login() @@ -2511,7 +2518,7 @@ def do_mount_management_privileges(self): # Test: CREATE/DROP MOUNT self.login(test_user, pwd) #BUG14 - #self.exec_sql_failed(sql_mount, TSDB_CODE_NO_SUCH_FILE) + self.exec_sql_failed(sql_mount, TSDB_CODE_NO_SUCH_FILE) # Cleanup self.login() @@ -2537,17 +2544,21 @@ def do_system_variable_privileges(self): self.revoke_privilege("SHOW SECURITY VARIABLES", None, test_user) self.revoke_privilege("ALTER SECURITY VARIABLE", None, test_user) self.revoke_privilege("SHOW DEBUG VARIABLES", None, test_user) - self.revoke_privilege("ALTER DEBUG VARIABLE", None, test_user) - + self.revoke_privilege("ALTER DEBUG VARIABLE", None, test_user) + # Test: no privilege self.login(test_user, pwd) - '''BUG15 + '''BUG15''' self.query_expect_rows("SHOW CLUSTER VARIABLES LIKE 'monitor'", 0) self.query_expect_rows("SHOW CLUSTER VARIABLES LIKE 'audit'", 0) self.query_expect_rows("SHOW CLUSTER VARIABLES LIKE 'enableStrongPassword'", 0) self.query_expect_rows("SHOW LOCAL VARIABLES LIKE 'numOfLogLines'", 0) - ''' - + self.exec_sql_failed("ALTER ALL DNODES 'monitor 1'", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed("ALTER ALL DNODES 'numOfLogLines 100000'", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed("ALTER ALL DNODES 'audit 0'", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed("ALTER ALL DNODES 'enableStrongPassword 0'", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed("ALTER LOCAL 'debugFlag 141'", TSDB_CODE_PAR_PERMISSION_DENIED) + # Grant privilege self.login() self.grant_privilege("SHOW SYSTEM VARIABLES", None, test_user) @@ -2585,12 +2596,16 @@ def do_system_variable_privileges(self): # Test: no privilege self.login(test_user, pwd) - '''BUG15 + '''BUG15''' self.query_expect_rows("SHOW CLUSTER VARIABLES LIKE 'monitor'", 0) self.query_expect_rows("SHOW CLUSTER VARIABLES LIKE 'audit'", 0) self.query_expect_rows("SHOW CLUSTER VARIABLES LIKE 'enableStrongPassword'", 0) self.query_expect_rows("SHOW LOCAL VARIABLES LIKE 'numOfLogLines'", 0) - ''' + self.exec_sql_failed("ALTER ALL DNODES 'monitor 1'", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed("ALTER ALL DNODES 'numOfLogLines 100000'", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed("ALTER ALL DNODES 'audit 0'", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed("ALTER ALL DNODES 'enableStrongPassword 0'", TSDB_CODE_MND_NO_RIGHTS) + self.exec_sql_failed("ALTER LOCAL 'debugFlag 141'", TSDB_CODE_PAR_PERMISSION_DENIED) # Cleanup self.login() @@ -2611,13 +2626,13 @@ def do_information_schema_privileges(self): # Test: without privilege self.login(test_user, pwd) - '''BUG16 - self.exec_sql_failed("SELECT * FROM information_schema.ins_databases", TSDB_CODE_MND_NO_RIGHTS) # basic - self.exec_sql_failed("SELECT * FROM information_schema.ins_users", TSDB_CODE_MND_NO_RIGHTS) # security - self.exec_sql_failed("SELECT * FROM information_schema.ins_grants_full", TSDB_CODE_MND_NO_RIGHTS) # privileged - self.exec_sql_failed("SELECT * FROM performance_schema.perf_connections", TSDB_CODE_MND_NO_RIGHTS) # basic - self.exec_sql_failed("SELECT * FROM performance_schema.perf_instances", TSDB_CODE_MND_NO_RIGHTS) # privileged - ''' + '''BUG16''' + self.exec_sql_failed("SELECT * FROM information_schema.ins_tables", TSDB_CODE_PAR_PERMISSION_DENIED) # basic + self.exec_sql_failed("SELECT * FROM information_schema.ins_databases", TSDB_CODE_PAR_PERMISSION_DENIED) # basic + self.exec_sql_failed("SELECT * FROM information_schema.ins_users", TSDB_CODE_PAR_PERMISSION_DENIED) # security + self.exec_sql_failed("SELECT * FROM information_schema.ins_grants_full", TSDB_CODE_PAR_PERMISSION_DENIED) # privileged + self.exec_sql_failed("SELECT * FROM performance_schema.perf_connections", TSDB_CODE_PAR_PERMISSION_DENIED) # basic + self.exec_sql_failed("SELECT * FROM performance_schema.perf_instances", TSDB_CODE_PAR_PERMISSION_DENIED) # privileged # Grant privilege self.login() @@ -2647,13 +2662,13 @@ def do_information_schema_privileges(self): # Test: without privilege self.login(test_user, pwd) - '''BUG16 - self.exec_sql_failed("SELECT * FROM information_schema.ins_databases", TSDB_CODE_MND_NO_RIGHTS) # basic - self.exec_sql_failed("SELECT * FROM information_schema.ins_users", TSDB_CODE_MND_NO_RIGHTS) # security - self.exec_sql_failed("SELECT * FROM information_schema.ins_grants_full", TSDB_CODE_MND_NO_RIGHTS) # privileged - self.exec_sql_failed("SELECT * FROM performance_schema.perf_connections", TSDB_CODE_MND_NO_RIGHTS) # basic - self.exec_sql_failed("SELECT * FROM performance_schema.perf_instances", TSDB_CODE_MND_NO_RIGHTS) # privileged - ''' + '''BUG16''' + self.exec_sql_failed("SELECT * FROM information_schema.ins_tables", TSDB_CODE_PAR_PERMISSION_DENIED) # basic + self.exec_sql_failed("SELECT * FROM information_schema.ins_databases", TSDB_CODE_PAR_PERMISSION_DENIED) # basic + self.exec_sql_failed("SELECT * FROM information_schema.ins_users", TSDB_CODE_PAR_PERMISSION_DENIED) # security + self.exec_sql_failed("SELECT * FROM information_schema.ins_grants_full", TSDB_CODE_PAR_PERMISSION_DENIED) # privileged + self.exec_sql_failed("SELECT * FROM performance_schema.perf_connections", TSDB_CODE_PAR_PERMISSION_DENIED) # basic + self.exec_sql_failed("SELECT * FROM performance_schema.perf_instances", TSDB_CODE_PAR_PERMISSION_DENIED) # privileged # Cleanup self.login() @@ -2713,9 +2728,8 @@ def do_system_monitoring_privileges(self): self.login(test_user, pwd) self.exec_sql_failed("SHOW TRANSACTIONS", TSDB_CODE_PAR_PERMISSION_DENIED) self.exec_sql_failed("SHOW QUERIES", TSDB_CODE_PAR_PERMISSION_DENIED) - '''BUG17 + '''BUG17''' self.exec_sql_failed("SHOW CONNECTIONS", TSDB_CODE_PAR_PERMISSION_DENIED) - ''' # Cleanup self.login() @@ -2736,9 +2750,12 @@ def do_show_grants_cluster_apps_privileges(self): # Test: without privilege self.login(test_user, pwd) - '''BUG18 - self.exec_sql_failed("SHOW GRANTS", TSDB_CODE_PAR_PERMISSION_DENIED) - ''' + '''BUG18''' + self.exec_sql("SHOW GRANTS") + self.exec_sql_failed("SHOW GRANTS FULL", TSDB_CODE_PAR_PERMISSION_DENIED) + self.exec_sql_failed("SHOW GRANTS LOGS", TSDB_CODE_PAR_PERMISSION_DENIED) + self.exec_sql_failed("SHOW CLUSTER MACHINES", TSDB_CODE_PAR_PERMISSION_DENIED) + self.exec_sql_failed("SHOW CLUSTER", TSDB_CODE_PAR_PERMISSION_DENIED) self.exec_sql_failed("SHOW APPS", TSDB_CODE_PAR_PERMISSION_DENIED) @@ -2749,8 +2766,11 @@ def do_show_grants_cluster_apps_privileges(self): self.grant_privilege("SHOW APPS", None, test_user) self.login(test_user, pwd) - self.exec_sql("SHOW GRANTS") - self.exec_sql("SHOW CLUSTER") + self.exec_sql("SHOW GRANTS") + self.exec_sql("SHOW GRANTS FULL") + self.exec_sql("SHOW GRANTS LOGS") + self.exec_sql("SHOW CLUSTER MACHINES") + self.exec_sql("SHOW CLUSTER") self.exec_sql("SHOW APPS") # Revoke @@ -2761,9 +2781,11 @@ def do_show_grants_cluster_apps_privileges(self): # Test: without privilege self.login(test_user, pwd) - '''BUG18 - self.exec_sql_failed("SHOW GRANTS", TSDB_CODE_PAR_PERMISSION_DENIED) - ''' + '''BUG18''' + self.exec_sql("SHOW GRANTS") + self.exec_sql_failed("SHOW GRANTS FULL", TSDB_CODE_PAR_PERMISSION_DENIED) + self.exec_sql_failed("SHOW GRANTS LOGS", TSDB_CODE_PAR_PERMISSION_DENIED) + self.exec_sql_failed("SHOW CLUSTER MACHINES", TSDB_CODE_PAR_PERMISSION_DENIED) self.exec_sql_failed("SHOW CLUSTER", TSDB_CODE_PAR_PERMISSION_DENIED) self.exec_sql_failed("SHOW APPS", TSDB_CODE_PAR_PERMISSION_DENIED) @@ -2979,10 +3001,10 @@ def do_create_tsma_privilege(self): # Test: user cannot show tsma without privilege #BUG10 - #self.query_expect_rows(f"SHOW {db_name}.TSMAS", 1) # tsma1(create owner) + self.query_expect_rows(f"SHOW {db_name}.TSMAS", 1) # tsma1(create owner) # Grant privilege self.login() - self.grant_privilege("SHOW", f"TSMA {db_name}.*", user) + self.grant_privilege("SHOW", f"TSMA {db_name}.tsma2", user) # Test: passed self.login(user, pwd) self.query_expect_rows(f"SHOW {db_name}.TSMAS", 2) # tsma1(create owner), tsma2(root) @@ -2991,7 +3013,7 @@ def do_create_tsma_privilege(self): self.revoke_privilege("SHOW", f"TSMA {db_name}.tsma2", user) self.login(user, pwd) #BUG10 - #self.query_expect_rows(f"SHOW {db_name}.TSMAS", 1) # tsma1(create owner) + self.query_expect_rows(f"SHOW {db_name}.TSMAS", 1) # tsma1(create owner) # Test: revoke for create tsma self.login() @@ -3390,13 +3412,14 @@ def do_topic_privileges(self): #self.grant_role("`SYSDBA`", consumer_user) # Test: consumer_user cannot consume topic without privilege - self.subscribe_topic_failed(consumer_user, pwd, "group1", topic_name, TSDB_CODE_MND_NO_RIGHTS) + self.subscribe_topic_failed(consumer_user, pwd, "group1", topic_name, TSDB_CODE_PAR_DB_USE_PERMISSION_DENIED) # Grant SUBSCRIBE privilege on topic + self.grant_privilege("USE", f"DATABASE {db_name}", consumer_user) self.grant_privilege("SUBSCRIBE", f"TOPIC {db_name}.{topic_name}", consumer_user) #BUG9 - #consumer1 = self.subscribe_topic(consumer_user, pwd, "group1", topic_name, expected_rows=1) - consumer1 = self.subscribe_topic("root", "taosdata", "group1", topic_name, expected_rows=1) + consumer1 = self.subscribe_topic(consumer_user, pwd, "group1", topic_name, expected_rows=1) + # consumer1 = self.subscribe_topic("root", "taosdata", "group1", topic_name, expected_rows=1) # Test: show consumers/subscriptions without privilege self.login(user1, pwd) @@ -3410,7 +3433,7 @@ def do_topic_privileges(self): self.login(user1, pwd) self.query_expect_rows("show consumers;", 1) # one consumer #BUG8 - #self.query_expect_rows("show subscriptions;", 2) # two vgroups + self.query_expect_rows("show subscriptions;", 2) # two vgroups self.login() consumer1.unsubscribe() @@ -4266,7 +4289,7 @@ def test_priv_control(self): print("[Role-Based Access Control]") self.do_role_privilege() self.do_role_creation_and_grant() - #self.do_role_lock_unlock() #can cause core BUG21 + self.do_role_lock_unlock() #can cause core BUG21 self.do_system_roles() self.do_audit_database_privileges() @@ -4293,14 +4316,14 @@ def test_priv_control(self): if platform.system().lower() != 'windows': # windows does not support tsma self.do_create_tsma_privilege() - self.do_create_rsma_privilege() + self.do_create_rsma_privilege() # View, topic and stream privilege tests (3.4.0.0+) print("") print("[View, Topic and Stream Privileges]") self.do_view_privileges() self.do_view_nested_privilege() - self.do_topic_privileges() + self.do_topic_privileges() self.do_stream_privileges() # Exception and reverse test cases diff --git a/test/cases/25-Privileges/test_priv_rbac.py b/test/cases/25-Privileges/test_priv_rbac.py index 42758996b8c9..9ed1ccdd44eb 100644 --- a/test/cases/25-Privileges/test_priv_rbac.py +++ b/test/cases/25-Privileges/test_priv_rbac.py @@ -52,6 +52,14 @@ def do_basic_user_privileges(self): tdSql.execute("grant use on database d0 to u1") tdSql.execute("grant lock role,unlock role,lock user,unlock user to u1") tdSql.execute("grant select(c0,c1),insert(ts,c0),delete on table d0.stb0 with t1=0 and ts=0 to u1") + tdSql.query("select user_name,priv_type from information_schema.ins_user_privileges where priv_type like '%TOTP_SECRET'") + tdSql.checkRows(0) + tdSql.execute("grant create totp_secret,drop totp_secret to u1") + tdSql.query("select user_name,priv_type from information_schema.ins_user_privileges where priv_type like '%TOTP_SECRET'") + tdSql.checkRows(2) + tdSql.execute("revoke create totp_secret,drop totp_secret from u1") + tdSql.query("select user_name,priv_type from information_schema.ins_user_privileges where priv_type like '%TOTP_SECRET'") + tdSql.checkRows(0) def do_basic_role_privileges(self): """Test basic role privileges(grant/revoke/show role privileges)""" diff --git a/test/new_test_framework/script/api/makefile_partial b/test/new_test_framework/script/api/makefile_partial new file mode 100644 index 000000000000..7b470406984c --- /dev/null +++ b/test/new_test_framework/script/api/makefile_partial @@ -0,0 +1,18 @@ +# Copyright (c) 2017 by TAOS Technologies, Inc. +# todo: library dependency, header file dependency + +ROOT=./ +TARGET=exe +LFLAGS = '-Wl,-rpath,/usr/local/taos/driver/' -ltaos -lpthread -lm -lrt +CFLAGS = -O0 -g -Wno-deprecated -fPIC -Wno-unused-result -Wconversion \ + -Wno-char-subscripts -D_REENTRANT -Wno-format -D_REENTRANT -DLINUX \ + -Wno-unused-function -D_M_X64 -I/usr/local/taos/include -std=gnu99 -Wno-sign-conversion +#CFLAGS += -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=shift-base -fno-sanitize=alignment + +all: $(TARGET) + +exe: + gcc $(CFLAGS) ./passwdTest.c -o $(ROOT)passwdTest $(LFLAGS) + +clean: + rm $(ROOT)passwdTest \ No newline at end of file diff --git a/test/new_test_framework/script/api/makefile_win64.mak b/test/new_test_framework/script/api/makefile_partial_win64.mak similarity index 100% rename from test/new_test_framework/script/api/makefile_win64.mak rename to test/new_test_framework/script/api/makefile_partial_win64.mak