github.com/polarismesh/polaris@v1.17.8/auth/defaultauth/server.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package defaultauth 19 20 import ( 21 "errors" 22 23 apimodel "github.com/polarismesh/specification/source/go/api/v1/model" 24 apisecurity "github.com/polarismesh/specification/source/go/api/v1/security" 25 apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" 26 "go.uber.org/zap" 27 "golang.org/x/crypto/bcrypt" 28 29 "github.com/polarismesh/polaris/cache" 30 api "github.com/polarismesh/polaris/common/api/v1" 31 "github.com/polarismesh/polaris/common/model" 32 "github.com/polarismesh/polaris/common/utils" 33 "github.com/polarismesh/polaris/plugin" 34 "github.com/polarismesh/polaris/store" 35 ) 36 37 func NewServer(storage store.Store, 38 history plugin.History, 39 cacheMgn *cache.CacheManager, 40 authMgn *DefaultAuthChecker) *Server { 41 return &Server{ 42 storage: storage, 43 history: history, 44 cacheMgn: cacheMgn, 45 authMgn: authMgn, 46 } 47 } 48 49 type Server struct { 50 storage store.Store 51 history plugin.History 52 cacheMgn *cache.CacheManager 53 authMgn *DefaultAuthChecker 54 } 55 56 // initialize 57 func (svr *Server) initialize() error { 58 // 获取History插件,注意:插件的配置在bootstrap已经设置好 59 svr.history = plugin.GetHistory() 60 if svr.history == nil { 61 log.Warnf("Not Found History Log Plugin") 62 } 63 64 return nil 65 } 66 67 // Login 登录动作 68 func (svr *Server) Login(req *apisecurity.LoginRequest) *apiservice.Response { 69 username := req.GetName().GetValue() 70 ownerName := req.GetOwner().GetValue() 71 if ownerName == "" { 72 ownerName = username 73 } 74 user := svr.cacheMgn.User().GetUserByName(username, ownerName) 75 if user == nil { 76 return api.NewAuthResponse(apimodel.Code_NotFoundUser) 77 } 78 79 // TODO AES 解密操作,在进行密码比对计算 80 err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.GetPassword().GetValue())) 81 if err != nil { 82 if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) { 83 return api.NewAuthResponseWithMsg( 84 apimodel.Code_NotAllowedAccess, model.ErrorWrongUsernameOrPassword.Error()) 85 } 86 return api.NewAuthResponseWithMsg(apimodel.Code_ExecuteException, model.ErrorWrongUsernameOrPassword.Error()) 87 } 88 89 return api.NewLoginResponse(apimodel.Code_ExecuteSuccess, &apisecurity.LoginResponse{ 90 UserId: utils.NewStringValue(user.ID), 91 OwnerId: utils.NewStringValue(user.Owner), 92 Token: utils.NewStringValue(user.Token), 93 Name: utils.NewStringValue(user.Name), 94 Role: utils.NewStringValue(model.UserRoleNames[user.Type]), 95 }) 96 } 97 98 // RecordHistory Server对外提供history插件的简单封装 99 func (svr *Server) RecordHistory(entry *model.RecordEntry) { 100 // 如果插件没有初始化,那么不记录history 101 if svr.history == nil { 102 return 103 } 104 // 如果数据为空,则不需要打印了 105 if entry == nil { 106 return 107 } 108 109 // 调用插件记录history 110 svr.history.Record(entry) 111 } 112 113 // AfterResourceOperation 对于资源的添加删除操作,需要执行后置逻辑 114 // 所有子用户或者用户分组,都默认获得对所创建的资源的写权限 115 func (svr *Server) AfterResourceOperation(afterCtx *model.AcquireContext) error { 116 if !svr.authMgn.IsOpenAuth() || afterCtx.GetOperation() == model.Read { 117 return nil 118 } 119 120 // 如果客户端鉴权没有开启,且请求来自客户端,忽略 121 if afterCtx.IsFromClient() && !svr.authMgn.IsOpenClientAuth() { 122 return nil 123 } 124 // 如果控制台鉴权没有开启,且请求来自控制台,忽略 125 if afterCtx.IsFromConsole() && !svr.authMgn.IsOpenConsoleAuth() { 126 return nil 127 } 128 129 // 如果 token 信息为空,则代表当前创建的资源,任何人都可以进行操作,不做资源的后置逻辑处理 130 if IsEmptyOperator(afterCtx.GetAttachment(model.TokenDetailInfoKey).(OperatorInfo)) { 131 return nil 132 } 133 134 addUserIds := afterCtx.GetAttachment(model.LinkUsersKey).([]string) 135 addGroupIds := afterCtx.GetAttachment(model.LinkGroupsKey).([]string) 136 removeUserIds := afterCtx.GetAttachment(model.RemoveLinkUsersKey).([]string) 137 removeGroupIds := afterCtx.GetAttachment(model.RemoveLinkGroupsKey).([]string) 138 139 // 只有在创建一个资源的时候,才需要把当前的创建者一并加到里面去 140 if afterCtx.GetOperation() == model.Create { 141 tokenInfo := afterCtx.GetAttachment(model.TokenDetailInfoKey).(OperatorInfo) 142 if tokenInfo.IsUserToken { 143 addUserIds = append(addUserIds, tokenInfo.OperatorID) 144 } else { 145 addGroupIds = append(addGroupIds, tokenInfo.OperatorID) 146 } 147 } 148 149 log.Info("[Auth][Server] add resource to principal default strategy", 150 zap.Any("resource", afterCtx.GetAttachment(model.ResourceAttachmentKey)), 151 zap.Any("add_user", addUserIds), 152 zap.Any("add_group", addGroupIds), zap.Any("remove_user", removeUserIds), 153 zap.Any("remove_group", removeGroupIds), 154 ) 155 156 // 添加某些用户、用户组与资源的默认授权关系 157 if err := svr.handleUserStrategy(addUserIds, afterCtx, false); err != nil { 158 log.Error("[Auth][Server] add user link resource", zap.Error(err)) 159 return err 160 } 161 if err := svr.handleGroupStrategy(addGroupIds, afterCtx, false); err != nil { 162 log.Error("[Auth][Server] add group link resource", zap.Error(err)) 163 return err 164 } 165 166 // 清理某些用户、用户组与资源的默认授权关系 167 if err := svr.handleUserStrategy(removeUserIds, afterCtx, true); err != nil { 168 log.Error("[Auth][Server] remove user link resource", zap.Error(err)) 169 return err 170 } 171 if err := svr.handleGroupStrategy(removeGroupIds, afterCtx, true); err != nil { 172 log.Error("[Auth][Server] remove group link resource", zap.Error(err)) 173 return err 174 } 175 176 return nil 177 } 178 179 // handleUserStrategy 180 func (svr *Server) handleUserStrategy(userIds []string, afterCtx *model.AcquireContext, isRemove bool) error { 181 for index := range utils.StringSliceDeDuplication(userIds) { 182 userId := userIds[index] 183 user := svr.cacheMgn.User().GetUserByID(userId) 184 if user == nil { 185 return errors.New("not found target user") 186 } 187 188 ownerId := user.Owner 189 if ownerId == "" { 190 ownerId = user.ID 191 } 192 if err := svr.handlerModifyDefaultStrategy(userId, ownerId, model.PrincipalUser, 193 afterCtx, isRemove); err != nil { 194 return err 195 } 196 } 197 198 return nil 199 } 200 201 // handleGroupStrategy 202 func (svr *Server) handleGroupStrategy(groupIds []string, afterCtx *model.AcquireContext, isRemove bool) error { 203 for index := range utils.StringSliceDeDuplication(groupIds) { 204 groupId := groupIds[index] 205 group := svr.cacheMgn.User().GetGroup(groupId) 206 if group == nil { 207 return errors.New("not found target group") 208 } 209 210 ownerId := group.Owner 211 if err := svr.handlerModifyDefaultStrategy(groupId, ownerId, model.PrincipalGroup, 212 afterCtx, isRemove); err != nil { 213 return err 214 } 215 } 216 217 return nil 218 } 219 220 // handlerModifyDefaultStrategy 处理默认策略的修改 221 // case 1. 如果默认策略是全部放通 222 func (svr *Server) handlerModifyDefaultStrategy(id, ownerId string, uType model.PrincipalType, 223 afterCtx *model.AcquireContext, cleanRealtion bool) error { 224 // Get the default policy rules 225 strategy, err := svr.storage.GetDefaultStrategyDetailByPrincipal(id, uType) 226 if err != nil { 227 log.Error("[Auth][Server] get default strategy", 228 zap.String("owner", ownerId), zap.String("id", id), zap.Error(err)) 229 return err 230 } 231 232 if strategy == nil { 233 return errors.New("not found default strategy rule") 234 } 235 236 var ( 237 strategyResource = make([]model.StrategyResource, 0) 238 resources = afterCtx.GetAttachment( 239 model.ResourceAttachmentKey).(map[apisecurity.ResourceType][]model.ResourceEntry) 240 strategyId = strategy.ID 241 ) 242 243 // 资源删除时,清理该资源与所有策略的关联关系 244 if afterCtx.GetOperation() == model.Delete { 245 strategyId = "" 246 } 247 248 for rType, rIds := range resources { 249 for i := range rIds { 250 id := rIds[i] 251 strategyResource = append(strategyResource, model.StrategyResource{ 252 StrategyID: strategyId, 253 ResType: int32(rType), 254 ResID: id.ID, 255 }) 256 } 257 } 258 259 if afterCtx.GetOperation() == model.Delete || cleanRealtion { 260 if err = svr.storage.RemoveStrategyResources(strategyResource); err != nil { 261 log.Error("[Auth][Server] remove default strategy resource", 262 zap.String("owner", ownerId), zap.String("id", id), 263 zap.String("type", model.PrincipalNames[uType]), zap.Error(err)) 264 return err 265 } 266 267 return nil 268 } 269 // 如果是写操作,那么采用松添加操作进行新增资源的添加操作(仅忽略主键冲突的错误) 270 if err = svr.storage.LooseAddStrategyResources(strategyResource); err != nil { 271 log.Error("[Auth][Server] update default strategy resource", 272 zap.String("owner", ownerId), zap.String("id", id), zap.String("id", id), 273 zap.String("type", model.PrincipalNames[uType]), zap.Error(err)) 274 return err 275 } 276 277 return nil 278 } 279 280 func checkHasPassAll(rule *model.StrategyDetail) bool { 281 for i := range rule.Resources { 282 if rule.Resources[i].ResID == "*" { 283 return true 284 } 285 } 286 287 return false 288 }