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  }