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 }