github.com/polarismesh/polaris@v1.17.8/service/server_authability.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 service 19 20 import ( 21 "context" 22 "errors" 23 24 apifault "github.com/polarismesh/specification/source/go/api/v1/fault_tolerance" 25 apimodel "github.com/polarismesh/specification/source/go/api/v1/model" 26 apisecurity "github.com/polarismesh/specification/source/go/api/v1/security" 27 apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" 28 apitraffic "github.com/polarismesh/specification/source/go/api/v1/traffic_manage" 29 "go.uber.org/zap" 30 31 "github.com/polarismesh/polaris/auth" 32 "github.com/polarismesh/polaris/cache" 33 "github.com/polarismesh/polaris/common/model" 34 "github.com/polarismesh/polaris/common/utils" 35 ) 36 37 // serverAuthAbility 带有鉴权能力的 discoverServer 38 // 39 // 该层会对请求参数做一些调整,根据具体的请求发起人,设置为数据对应的 owner,不可为为别人进行创建资源 40 type serverAuthAbility struct { 41 targetServer *Server 42 userMgn auth.UserServer 43 strategyMgn auth.StrategyServer 44 } 45 46 func newServerAuthAbility(targetServer *Server, 47 userMgn auth.UserServer, strategyMgn auth.StrategyServer) DiscoverServer { 48 proxy := &serverAuthAbility{ 49 targetServer: targetServer, 50 userMgn: userMgn, 51 strategyMgn: strategyMgn, 52 } 53 54 targetServer.SetResourceHooks(proxy) 55 56 return proxy 57 } 58 59 // Cache Get cache management 60 func (svr *serverAuthAbility) Cache() *cache.CacheManager { 61 return svr.targetServer.Cache() 62 } 63 64 // GetServiceInstanceRevision 获取服务实例的版本号 65 func (svr *serverAuthAbility) GetServiceInstanceRevision(serviceID string, 66 instances []*model.Instance) (string, error) { 67 return svr.targetServer.GetServiceInstanceRevision(serviceID, instances) 68 } 69 70 // collectServiceAuthContext 对于服务的处理,收集所有的与鉴权的相关信息 71 // 72 // @receiver svr serverAuthAbility 73 // @param ctx 请求上下文 ctx 74 // @param req 实际请求对象 75 // @param resourceOp 该接口的数据操作类型 76 // @return *model.AcquireContext 返回鉴权上下文 77 func (svr *serverAuthAbility) collectServiceAuthContext(ctx context.Context, req []*apiservice.Service, 78 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 79 return model.NewAcquireContext( 80 model.WithRequestContext(ctx), 81 model.WithOperation(resourceOp), 82 model.WithModule(model.DiscoverModule), 83 model.WithMethod(methodName), 84 model.WithAccessResources(svr.queryServiceResource(req)), 85 ) 86 } 87 88 // collectServiceAliasAuthContext 对于服务别名的处理,收集所有的与鉴权的相关信息 89 // 90 // @receiver svr serverAuthAbility 91 // @param ctx 请求上下文 ctx 92 // @param req 实际请求对象 93 // @param resourceOp 该接口的数据操作类型 94 // @return *model.AcquireContext 返回鉴权上下文 95 func (svr *serverAuthAbility) collectServiceAliasAuthContext(ctx context.Context, req []*apiservice.ServiceAlias, 96 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 97 return model.NewAcquireContext( 98 model.WithRequestContext(ctx), 99 model.WithOperation(resourceOp), 100 model.WithModule(model.DiscoverModule), 101 model.WithMethod(methodName), 102 model.WithAccessResources(svr.queryServiceAliasResource(req)), 103 ) 104 } 105 106 // collectInstanceAuthContext 对于服务实例的处理,收集所有的与鉴权的相关信息 107 // 108 // @receiver svr serverAuthAbility 109 // @param ctx 请求上下文 ctx 110 // @param req 实际请求对象 111 // @param resourceOp 该接口的数据操作类型 112 // @return *model.AcquireContext 返回鉴权上下文 113 func (svr *serverAuthAbility) collectInstanceAuthContext(ctx context.Context, req []*apiservice.Instance, 114 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 115 return model.NewAcquireContext( 116 model.WithRequestContext(ctx), 117 model.WithOperation(resourceOp), 118 model.WithModule(model.DiscoverModule), 119 model.WithMethod(methodName), 120 model.WithAccessResources(svr.queryInstanceResource(req)), 121 ) 122 } 123 124 // collectClientInstanceAuthContext 对于服务实例的处理,收集所有的与鉴权的相关信息 125 func (svr *serverAuthAbility) collectClientInstanceAuthContext(ctx context.Context, req []*apiservice.Instance, 126 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 127 return model.NewAcquireContext( 128 model.WithRequestContext(ctx), 129 model.WithOperation(resourceOp), 130 model.WithModule(model.DiscoverModule), 131 model.WithMethod(methodName), 132 model.WithFromClient(), 133 model.WithAccessResources(svr.queryInstanceResource(req)), 134 ) 135 } 136 137 // collectCircuitBreakerAuthContext 对于服务熔断的处理,收集所有的与鉴权的相关信息 138 // 139 // @receiver svr serverAuthAbility 140 // @param ctx 请求上下文 ctx 141 // @param req 实际请求对象 142 // @param resourceOp 该接口的数据操作类型 143 // @return *model.AcquireContext 返回鉴权上下文 144 func (svr *serverAuthAbility) collectCircuitBreakerAuthContext(ctx context.Context, req []*apifault.CircuitBreaker, 145 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 146 return model.NewAcquireContext( 147 model.WithRequestContext(ctx), 148 model.WithOperation(resourceOp), 149 model.WithModule(model.DiscoverModule), 150 model.WithMethod(methodName), 151 model.WithAccessResources(svr.queryCircuitBreakerResource(req)), 152 ) 153 } 154 155 // collectCircuitBreakerReleaseAuthContext 156 // 157 // @receiver svr 158 // @param ctx 159 // @param req 160 // @param resourceOp 161 // @return *model.AcquireContext 162 func (svr *serverAuthAbility) collectCircuitBreakerReleaseAuthContext(ctx context.Context, 163 req []*apiservice.ConfigRelease, resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 164 return model.NewAcquireContext( 165 model.WithRequestContext(ctx), 166 model.WithOperation(resourceOp), 167 model.WithModule(model.DiscoverModule), 168 model.WithMethod(methodName), 169 model.WithAccessResources(svr.queryCircuitBreakerReleaseResource(req)), 170 ) 171 } 172 173 // collectRouteRuleAuthContext 对于服务路由规则的处理,收集所有的与鉴权的相关信息 174 // 175 // @receiver svr serverAuthAbility 176 // @param ctx 请求上下文 ctx 177 // @param req 实际请求对象 178 // @param resourceOp 该接口的数据操作类型 179 // @return *model.AcquireContext 返回鉴权上下文 180 func (svr *serverAuthAbility) collectRouteRuleAuthContext(ctx context.Context, req []*apitraffic.Routing, 181 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 182 return model.NewAcquireContext( 183 model.WithRequestContext(ctx), 184 model.WithOperation(resourceOp), 185 model.WithModule(model.DiscoverModule), 186 model.WithMethod(methodName), 187 model.WithAccessResources(svr.queryRouteRuleResource(req)), 188 ) 189 } 190 191 // collectRateLimitAuthContext 对于服务限流规则的处理,收集所有的与鉴权的相关信息 192 // 193 // @receiver svr serverAuthAbility 194 // @param ctx 请求上下文 ctx 195 // @param req 实际请求对象 196 // @param resourceOp 该接口的数据操作类型 197 // @return *model.AcquireContext 返回鉴权上下文 198 func (svr *serverAuthAbility) collectRateLimitAuthContext(ctx context.Context, req []*apitraffic.Rule, 199 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 200 return model.NewAcquireContext( 201 model.WithRequestContext(ctx), 202 model.WithOperation(resourceOp), 203 model.WithModule(model.DiscoverModule), 204 model.WithMethod(methodName), 205 model.WithAccessResources(svr.queryRateLimitConfigResource(req)), 206 ) 207 } 208 209 // collectRouteRuleV2AuthContext 收集路由v2规则 210 func (svr *serverAuthAbility) collectRouteRuleV2AuthContext(ctx context.Context, req []*apitraffic.RouteRule, 211 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 212 return model.NewAcquireContext( 213 model.WithRequestContext(ctx), 214 model.WithOperation(resourceOp), 215 model.WithModule(model.DiscoverModule), 216 model.WithMethod(methodName), 217 model.WithAccessResources(map[apisecurity.ResourceType][]model.ResourceEntry{}), 218 ) 219 } 220 221 // collectRouteRuleV2AuthContext 收集熔断v2规则 222 func (svr *serverAuthAbility) collectCircuitBreakerRuleV2AuthContext(ctx context.Context, 223 req []*apifault.CircuitBreakerRule, 224 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 225 return model.NewAcquireContext( 226 model.WithRequestContext(ctx), 227 model.WithOperation(resourceOp), 228 model.WithModule(model.DiscoverModule), 229 model.WithMethod(methodName), 230 model.WithAccessResources(map[apisecurity.ResourceType][]model.ResourceEntry{}), 231 ) 232 } 233 234 // collectRouteRuleV2AuthContext 收集主动探测规则 235 func (svr *serverAuthAbility) collectFaultDetectAuthContext(ctx context.Context, 236 req []*apifault.FaultDetectRule, 237 resourceOp model.ResourceOperation, methodName string) *model.AcquireContext { 238 return model.NewAcquireContext( 239 model.WithRequestContext(ctx), 240 model.WithOperation(resourceOp), 241 model.WithModule(model.DiscoverModule), 242 model.WithMethod(methodName), 243 model.WithAccessResources(map[apisecurity.ResourceType][]model.ResourceEntry{}), 244 ) 245 } 246 247 // queryServiceResource 根据所给的 service 信息,收集对应的 ResourceEntry 列表 248 func (svr *serverAuthAbility) queryServiceResource( 249 req []*apiservice.Service) map[apisecurity.ResourceType][]model.ResourceEntry { 250 if len(req) == 0 { 251 return make(map[apisecurity.ResourceType][]model.ResourceEntry) 252 } 253 254 names := utils.NewSet[string]() 255 svcSet := utils.NewMap[string, *model.Service]() 256 257 for index := range req { 258 svcName := req[index].GetName().GetValue() 259 svcNamespace := req[index].GetNamespace().GetValue() 260 names.Add(svcNamespace) 261 svc := svr.Cache().Service().GetServiceByName(svcName, svcNamespace) 262 if svc != nil { 263 svcSet.Store(svc.ID, svc) 264 } 265 } 266 267 ret := svr.convertToDiscoverResourceEntryMaps(names, svcSet) 268 if authLog.DebugEnabled() { 269 authLog.Debug("[Auth][Server] collect service access res", zap.Any("res", ret)) 270 } 271 return ret 272 } 273 274 // queryServiceAliasResource 根据所给的 servicealias 信息,收集对应的 ResourceEntry 列表 275 func (svr *serverAuthAbility) queryServiceAliasResource( 276 req []*apiservice.ServiceAlias) map[apisecurity.ResourceType][]model.ResourceEntry { 277 if len(req) == 0 { 278 return make(map[apisecurity.ResourceType][]model.ResourceEntry) 279 } 280 281 names := utils.NewSet[string]() 282 svcSet := utils.NewMap[string, *model.Service]() 283 284 for index := range req { 285 aliasSvcName := req[index].GetAlias().GetValue() 286 aliasSvcNamespace := req[index].GetAliasNamespace().GetValue() 287 svcNamespace := req[index].GetNamespace().GetValue() 288 names.Add(svcNamespace) 289 alias := svr.Cache().Service().GetServiceByName(aliasSvcName, aliasSvcNamespace) 290 if alias != nil { 291 svc := svr.Cache().Service().GetServiceByID(alias.Reference) 292 if svc != nil { 293 svcSet.Store(svc.ID, svc) 294 } 295 } 296 } 297 298 ret := svr.convertToDiscoverResourceEntryMaps(names, svcSet) 299 if authLog.DebugEnabled() { 300 authLog.Debug("[Auth][Server] collect service alias access res", zap.Any("res", ret)) 301 } 302 return ret 303 } 304 305 // queryInstanceResource 根据所给的 instances 信息,收集对应的 ResourceEntry 列表 306 // 由于实例是注册到服务下的,因此只需要判断,是否有对应服务的权限即可 307 func (svr *serverAuthAbility) queryInstanceResource( 308 req []*apiservice.Instance) map[apisecurity.ResourceType][]model.ResourceEntry { 309 if len(req) == 0 { 310 return make(map[apisecurity.ResourceType][]model.ResourceEntry) 311 } 312 313 names := utils.NewSet[string]() 314 svcSet := utils.NewMap[string, *model.Service]() 315 316 for index := range req { 317 svcName := req[index].GetService().GetValue() 318 svcNamespace := req[index].GetNamespace().GetValue() 319 item := req[index] 320 if svcNamespace != "" && svcName != "" { 321 svc := svr.Cache().Service().GetServiceByName(svcName, svcNamespace) 322 if svc != nil { 323 svcSet.Store(svc.ID, svc) 324 } else { 325 names.Add(svcNamespace) 326 } 327 } else { 328 ins := svr.Cache().Instance().GetInstance(item.GetId().GetValue()) 329 if ins != nil { 330 svc := svr.Cache().Service().GetServiceByID(ins.ServiceID) 331 if svc != nil { 332 svcSet.Store(svc.ID, svc) 333 } else { 334 names.Add(svcNamespace) 335 } 336 } 337 } 338 } 339 340 ret := svr.convertToDiscoverResourceEntryMaps(names, svcSet) 341 if authLog.DebugEnabled() { 342 authLog.Debug("[Auth][Server] collect instance access res", zap.Any("res", ret)) 343 } 344 return ret 345 } 346 347 // queryCircuitBreakerResource 根据所给的 CircuitBreaker 信息,收集对应的 ResourceEntry 列表 348 func (svr *serverAuthAbility) queryCircuitBreakerResource( 349 req []*apifault.CircuitBreaker) map[apisecurity.ResourceType][]model.ResourceEntry { 350 if len(req) == 0 { 351 return make(map[apisecurity.ResourceType][]model.ResourceEntry) 352 } 353 354 names := utils.NewSet[string]() 355 svcSet := utils.NewMap[string, *model.Service]() 356 357 for index := range req { 358 svcName := req[index].GetService().GetValue() 359 svcNamespace := req[index].GetNamespace().GetValue() 360 svc := svr.Cache().Service().GetServiceByName(svcName, svcNamespace) 361 if svc != nil { 362 svcSet.Store(svc.ID, svc) 363 } 364 } 365 ret := svr.convertToDiscoverResourceEntryMaps(names, svcSet) 366 if authLog.DebugEnabled() { 367 authLog.Debug("[Auth][Server] collect circuit-breaker access res", zap.Any("res", ret)) 368 } 369 return ret 370 } 371 372 // queryCircuitBreakerReleaseResource 根据所给的 CircuitBreakerRelease 信息,收集对应的 ResourceEntry 列表 373 func (svr *serverAuthAbility) queryCircuitBreakerReleaseResource( 374 req []*apiservice.ConfigRelease) map[apisecurity.ResourceType][]model.ResourceEntry { 375 if len(req) == 0 { 376 return make(map[apisecurity.ResourceType][]model.ResourceEntry) 377 } 378 379 names := utils.NewSet[string]() 380 svcSet := utils.NewMap[string, *model.Service]() 381 382 for index := range req { 383 svcName := req[index].GetService().GetName().GetValue() 384 svcNamespace := req[index].GetService().GetNamespace().GetValue() 385 svc := svr.Cache().Service().GetServiceByName(svcName, svcNamespace) 386 if svc != nil { 387 svcSet.Store(svc.ID, svc) 388 } 389 } 390 391 ret := svr.convertToDiscoverResourceEntryMaps(names, svcSet) 392 if authLog.DebugEnabled() { 393 authLog.Debug("[Auth][Server] collect circuit-breaker-release access res", zap.Any("res", ret)) 394 } 395 return ret 396 } 397 398 // queryRouteRuleResource 根据所给的 RouteRule 信息,收集对应的 ResourceEntry 列表 399 func (svr *serverAuthAbility) queryRouteRuleResource( 400 req []*apitraffic.Routing) map[apisecurity.ResourceType][]model.ResourceEntry { 401 if len(req) == 0 { 402 return make(map[apisecurity.ResourceType][]model.ResourceEntry) 403 } 404 405 names := utils.NewSet[string]() 406 svcSet := utils.NewMap[string, *model.Service]() 407 408 for index := range req { 409 svcName := req[index].GetService().GetValue() 410 svcNamespace := req[index].GetNamespace().GetValue() 411 svc := svr.Cache().Service().GetServiceByName(svcName, svcNamespace) 412 if svc != nil { 413 svcSet.Store(svc.ID, svc) 414 } 415 } 416 417 ret := svr.convertToDiscoverResourceEntryMaps(names, svcSet) 418 if authLog.DebugEnabled() { 419 authLog.Debug("[Auth][Server] collect route-rule access res", zap.Any("res", ret)) 420 } 421 return ret 422 } 423 424 // queryRateLimitConfigResource 根据所给的 RateLimit 信息,收集对应的 ResourceEntry 列表 425 func (svr *serverAuthAbility) queryRateLimitConfigResource( 426 req []*apitraffic.Rule) map[apisecurity.ResourceType][]model.ResourceEntry { 427 if len(req) == 0 { 428 return make(map[apisecurity.ResourceType][]model.ResourceEntry) 429 } 430 431 names := utils.NewSet[string]() 432 svcSet := utils.NewMap[string, *model.Service]() 433 434 for index := range req { 435 svcName := req[index].GetService().GetValue() 436 svcNamespace := req[index].GetNamespace().GetValue() 437 svc := svr.Cache().Service().GetServiceByName(svcName, svcNamespace) 438 if svc != nil { 439 svcSet.Store(svc.ID, svc) 440 } 441 } 442 443 ret := svr.convertToDiscoverResourceEntryMaps(names, svcSet) 444 if authLog.DebugEnabled() { 445 authLog.Debug("[Auth][Server] collect rate-limit access res", zap.Any("res", ret)) 446 } 447 return ret 448 } 449 450 // convertToDiscoverResourceEntryMaps 通用方法,进行转换为期望的、服务相关的 ResourceEntry 451 func (svr *serverAuthAbility) convertToDiscoverResourceEntryMaps(nsSet *utils.Set[string], 452 svcSet *utils.Map[string, *model.Service]) map[apisecurity.ResourceType][]model.ResourceEntry { 453 var ( 454 param = nsSet.ToSlice() 455 nsArr = svr.Cache().Namespace().GetNamespacesByName(param) 456 nsRet = make([]model.ResourceEntry, 0, len(nsArr)) 457 ) 458 for index := range nsArr { 459 ns := nsArr[index] 460 nsRet = append(nsRet, model.ResourceEntry{ 461 ID: ns.Name, 462 Owner: ns.Owner, 463 }) 464 } 465 466 svcRet := make([]model.ResourceEntry, 0, svcSet.Len()) 467 svcSet.Range(func(key string, svc *model.Service) { 468 svcRet = append(svcRet, model.ResourceEntry{ 469 ID: svc.ID, 470 Owner: svc.Owner, 471 }) 472 }) 473 474 return map[apisecurity.ResourceType][]model.ResourceEntry{ 475 apisecurity.ResourceType_Namespaces: nsRet, 476 apisecurity.ResourceType_Services: svcRet, 477 } 478 } 479 480 func convertToErrCode(err error) apimodel.Code { 481 if errors.Is(err, model.ErrorTokenNotExist) { 482 return apimodel.Code_TokenNotExisted 483 } 484 if errors.Is(err, model.ErrorTokenDisabled) { 485 return apimodel.Code_TokenDisabled 486 } 487 return apimodel.Code_NotAllowedAccess 488 }