github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/authenticate2.go (about) 1 // Copyright 2021 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package frontend 16 17 import ( 18 "context" 19 20 "github.com/matrixorigin/matrixone/pkg/pb/plan" 21 plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" 22 ) 23 24 // verifyAccountCanOperateClusterTable determines the account can operate 25 // the cluster table 26 func verifyAccountCanOperateClusterTable(account *TenantInfo, 27 dbName string, 28 clusterTableOperation clusterTableOperationType) bool { 29 if account.IsSysTenant() { 30 //sys account can do anything on the cluster table. 31 if dbName == moCatalog { 32 return true 33 } 34 } else { 35 //the general account can only read the cluster table 36 if dbName == moCatalog { 37 switch clusterTableOperation { 38 case clusterTableNone, clusterTableSelect: 39 return true 40 } 41 } 42 } 43 return false 44 } 45 46 // verifyLightPrivilege checks the privilege that does not need to 47 // access the privilege tables. 48 // case1 : checks if a real user from client is modifying the catalog databases (mo_catalog,information_schema,system, 49 // system_metric,mysql). 50 // case2 : checks if the user operates the cluster table. 51 func verifyLightPrivilege(ses *Session, 52 dbName string, 53 writeDBTableDirect bool, 54 isClusterTable bool, 55 clusterTableOperation clusterTableOperationType) bool { 56 var ok bool 57 if ses.GetFromRealUser() && writeDBTableDirect { 58 if len(dbName) == 0 { 59 dbName = ses.GetDatabaseName() 60 } 61 if ok2 := isBannedDatabase(dbName); ok2 { 62 if isClusterTable { 63 ok = verifyAccountCanOperateClusterTable(ses.GetTenantInfo(), dbName, clusterTableOperation) 64 } else { 65 ok = false 66 } 67 } else { 68 ok = !isClusterTable 69 } 70 } else { 71 ok = true 72 } 73 return ok 74 } 75 76 // getDefaultAccount returns the internal account 77 func getDefaultAccount() *TenantInfo { 78 return &TenantInfo{ 79 Tenant: sysAccountName, 80 User: rootName, 81 DefaultRole: moAdminRoleName, 82 TenantID: sysAccountID, 83 UserID: rootID, 84 DefaultRoleID: moAdminRoleID, 85 delimiter: ':', 86 } 87 } 88 89 // verifyPrivilegeEntryInMultiPrivilegeLevelsInCache checks privilege entry 90 // in the cache only. 91 func verifyPrivilegeEntryInMultiPrivilegeLevelsInCache( 92 ses *Session, 93 cache *privilegeCache, 94 entry privilegeEntry, 95 pls []privilegeLevelType) (bool, error) { 96 var yes bool 97 dbName := entry.databaseName 98 if len(dbName) == 0 { 99 dbName = ses.GetDatabaseName() 100 } 101 if cache != nil { 102 for _, pl := range pls { 103 yes = cache.has(entry.objType, pl, dbName, entry.tableName, entry.privilegeId) 104 if yes { 105 return true, nil 106 } 107 } 108 } 109 return false, nil 110 } 111 112 // checkPrivilegeInCache checks the privilege in the cache first. 113 func checkPrivilegeInCache(ctx context.Context, ses *Session, priv *privilege, enableCache bool) (bool, error) { 114 var err error 115 var pls []privilegeLevelType 116 var yes2, yes bool 117 cache := ses.GetPrivilegeCache() 118 if cache != nil && enableCache { 119 for _, entry := range priv.entries { 120 if entry.privilegeEntryTyp == privilegeEntryTypeGeneral { 121 pls, err = getPrivilegeLevelsOfObjectType(ctx, entry.objType) 122 if err != nil { 123 return false, err 124 } 125 126 yes2 = verifyLightPrivilege(ses, 127 entry.databaseName, 128 priv.writeDatabaseAndTableDirectly, 129 priv.isClusterTable, 130 priv.clusterTableOperation) 131 132 if yes2 { 133 yes, err = verifyPrivilegeEntryInMultiPrivilegeLevelsInCache(ses, cache, entry, pls) 134 if err != nil { 135 return false, err 136 } 137 } 138 139 if yes { 140 return true, nil 141 } 142 } else if entry.privilegeEntryTyp == privilegeEntryTypeCompound { 143 if entry.compound != nil { 144 allTrue := true 145 //multi privileges take effect together 146 for _, mi := range entry.compound.items { 147 if mi.privilegeTyp == PrivilegeTypeCanGrantRoleToOthersInCreateUser { 148 //TODO: normalize the name 149 //TODO: simplify the logic 150 //yes, err = determineUserCanGrantRolesToOthersInternal(ctx, bh, ses, []*tree.Role{mi.role}) 151 //if err != nil { 152 // return false, err 153 //} 154 //if yes { 155 // from := &verifiedRole{ 156 // typ: roleType, 157 // name: mi.role.UserName, 158 // } 159 // for _, user := range mi.users { 160 // to := &verifiedRole{ 161 // typ: userType, 162 // name: user.Username, 163 // } 164 // err = verifySpecialRolesInGrant(ctx, ses.GetTenantInfo(), from, to) 165 // if err != nil { 166 // return false, err 167 // } 168 // } 169 //} 170 } else { 171 tempEntry := privilegeEntriesMap[mi.privilegeTyp] 172 tempEntry.databaseName = mi.dbName 173 tempEntry.tableName = mi.tableName 174 tempEntry.privilegeEntryTyp = privilegeEntryTypeGeneral 175 tempEntry.compound = nil 176 pls, err = getPrivilegeLevelsOfObjectType(ctx, tempEntry.objType) 177 if err != nil { 178 return false, err 179 } 180 181 yes2 = verifyLightPrivilege(ses, 182 tempEntry.databaseName, 183 priv.writeDatabaseAndTableDirectly, 184 mi.isClusterTable, 185 mi.clusterTableOperation) 186 187 if yes2 { 188 //At least there is one success 189 yes, err = verifyPrivilegeEntryInMultiPrivilegeLevelsInCache(ses, cache, tempEntry, pls) 190 if err != nil { 191 return false, err 192 } 193 } 194 } 195 if !yes { 196 allTrue = false 197 break 198 } 199 } 200 201 if allTrue { 202 return allTrue, nil 203 } 204 } 205 } 206 } 207 } 208 return false, nil 209 } 210 211 // privilegeCacheIsEnabled checks if the privilege cache is enabled. 212 func privilegeCacheIsEnabled(ctx context.Context, ses *Session) (bool, error) { 213 var err error 214 var value interface{} 215 var newValue bool 216 value, err = ses.GetSessionVar(ctx, "enable_privilege_cache") 217 if err != nil { 218 return false, err 219 } 220 221 newValue, err = valueIsBoolTrue(value) 222 if err != nil { 223 return false, err 224 } 225 226 return newValue, err 227 } 228 229 // hasMoCtrl checks whether the plan has mo_ctrl 230 func hasMoCtrl(p *plan2.Plan) bool { 231 if p != nil && p.GetQuery() != nil { //select,insert select, update, delete 232 q := p.GetQuery() 233 if q.StmtType == plan.Query_INSERT || q.StmtType == plan.Query_SELECT { 234 for _, node := range q.Nodes { 235 if node != nil && node.NodeType == plan.Node_PROJECT { 236 //restrict : 237 // select mo_ctrl ... 238 // insert into ... select mo_ctrl ... 239 for _, proj := range node.ProjectList { 240 if plan2.HasMoCtrl(proj) { 241 return true 242 } 243 } 244 } 245 } 246 } 247 } 248 return false 249 } 250 251 // verifyAccountCanExecMoCtrl only sys account and moadmin role. 252 func verifyAccountCanExecMoCtrl(account *TenantInfo) bool { 253 return account.IsSysTenant() && account.IsMoAdminRole() 254 }