github.com/polarismesh/polaris@v1.17.8/auth/defaultauth/utils.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  	"context"
    22  	"errors"
    23  	"regexp"
    24  	"unicode/utf8"
    25  
    26  	"github.com/golang/protobuf/ptypes/wrappers"
    27  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    28  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    29  	"go.uber.org/zap"
    30  
    31  	api "github.com/polarismesh/polaris/common/api/v1"
    32  	"github.com/polarismesh/polaris/common/model"
    33  	"github.com/polarismesh/polaris/common/utils"
    34  )
    35  
    36  var (
    37  	// MustOwner 必须超级账户 or 主账户
    38  	MustOwner = true
    39  	// NotOwner 任意账户
    40  	NotOwner = false
    41  	// WriteOp 写操作
    42  	WriteOp = true
    43  	// ReadOp 读操作
    44  	ReadOp = false
    45  )
    46  
    47  var (
    48  	regNameStr = regexp.MustCompile("^[\u4E00-\u9FA5A-Za-z0-9_\\-.]+$")
    49  	regEmail   = regexp.MustCompile(`^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$`)
    50  )
    51  
    52  // checkName 名称检查
    53  func checkName(name *wrappers.StringValue) error {
    54  	if name == nil {
    55  		return errors.New(utils.NilErrString)
    56  	}
    57  
    58  	if name.GetValue() == "" {
    59  		return errors.New(utils.EmptyErrString)
    60  	}
    61  
    62  	if name.GetValue() == "polariadmin" {
    63  		return errors.New("illegal username")
    64  	}
    65  
    66  	if utf8.RuneCountInString(name.GetValue()) > utils.MaxNameLength {
    67  		return errors.New("name too long")
    68  	}
    69  
    70  	if ok := regNameStr.MatchString(name.GetValue()); !ok {
    71  		return errors.New("name contains invalid character")
    72  	}
    73  
    74  	return nil
    75  }
    76  
    77  // checkPassword 密码检查
    78  func checkPassword(password *wrappers.StringValue) error {
    79  	if password == nil {
    80  		return errors.New(utils.NilErrString)
    81  	}
    82  
    83  	if password.GetValue() == "" {
    84  		return errors.New(utils.EmptyErrString)
    85  	}
    86  
    87  	if pLen := len(password.GetValue()); pLen < 6 || pLen > 17 {
    88  		return errors.New("password len need 6 ~ 17")
    89  	}
    90  
    91  	return nil
    92  }
    93  
    94  // checkOwner 检查用户的 owner 信息
    95  func checkOwner(owner *wrappers.StringValue) error {
    96  	if owner == nil {
    97  		return errors.New(utils.NilErrString)
    98  	}
    99  
   100  	if owner.GetValue() == "" {
   101  		return errors.New(utils.EmptyErrString)
   102  	}
   103  
   104  	if utf8.RuneCountInString(owner.GetValue()) > utils.MaxOwnersLength {
   105  		return errors.New("owners too long")
   106  	}
   107  
   108  	return nil
   109  }
   110  
   111  // checkMobile 检查用户的 mobile 信息
   112  func checkMobile(mobile *wrappers.StringValue) error {
   113  	if mobile == nil {
   114  		return nil
   115  	}
   116  
   117  	if mobile.GetValue() == "" {
   118  		return nil
   119  	}
   120  
   121  	if utf8.RuneCountInString(mobile.GetValue()) != 11 {
   122  		return errors.New("invalid mobile")
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  // checkEmail 检查用户的 email 信息
   129  func checkEmail(email *wrappers.StringValue) error {
   130  	if email == nil {
   131  		return nil
   132  	}
   133  
   134  	if email.GetValue() == "" {
   135  		return nil
   136  	}
   137  
   138  	if ok := regEmail.MatchString(email.GetValue()); !ok {
   139  		return errors.New("invalid email")
   140  	}
   141  
   142  	return nil
   143  }
   144  
   145  // verifyAuth 用于 user、group 以及 strategy 模块的鉴权工作检查
   146  func verifyAuth(ctx context.Context, isWrite bool,
   147  	needOwner bool, authMgn *DefaultAuthChecker) (context.Context, *apiservice.Response) {
   148  	reqId := utils.ParseRequestID(ctx)
   149  	authToken := utils.ParseAuthToken(ctx)
   150  
   151  	if authToken == "" {
   152  		log.Error("[Auth][Server] auth token is empty", utils.ZapRequestID(reqId))
   153  		return nil, api.NewAuthResponse(apimodel.Code_EmptyAutToken)
   154  	}
   155  
   156  	authCtx := model.NewAcquireContext(
   157  		model.WithRequestContext(ctx),
   158  		model.WithModule(model.AuthModule),
   159  	)
   160  
   161  	// case 1. 如果 error 不是 token 被禁止的 error,直接返回
   162  	// case 2. 如果 error 是 token 被禁止,按下面情况判断
   163  	// 		i. 如果当前只是一个数据的读取操作,则放通
   164  	// 		ii. 如果当前是一个数据的写操作,则只能允许处于正常的 token 进行操作
   165  	if err := authMgn.VerifyCredential(authCtx); err != nil {
   166  		log.Error("[Auth][Server] verify auth token", utils.ZapRequestID(reqId),
   167  			zap.Error(err))
   168  		return nil, api.NewAuthResponse(apimodel.Code_AuthTokenForbidden)
   169  	}
   170  
   171  	tokenInfo := authCtx.GetAttachment(model.TokenDetailInfoKey).(OperatorInfo)
   172  
   173  	if isWrite && tokenInfo.Disable {
   174  		log.Error("[Auth][Server] token is disabled", utils.ZapRequestID(reqId),
   175  			zap.String("operation", authCtx.GetMethod()))
   176  		return nil, api.NewAuthResponse(apimodel.Code_TokenDisabled)
   177  	}
   178  
   179  	if !tokenInfo.IsUserToken {
   180  		log.Error("[Auth][Server] only user role can access this API", utils.ZapRequestID(reqId))
   181  		return nil, api.NewAuthResponse(apimodel.Code_OperationRoleForbidden)
   182  	}
   183  
   184  	if needOwner && IsSubAccount(tokenInfo) {
   185  		log.Error("[Auth][Server] only admin/owner account can access this API", utils.ZapRequestID(reqId))
   186  		return nil, api.NewAuthResponse(apimodel.Code_OperationRoleForbidden)
   187  	}
   188  
   189  	return authCtx.GetRequestContext(), nil
   190  }