This is an automated email from the ASF dual-hosted git repository.
tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git
The following commit(s) were added to refs/heads/master by this push:
new 462c741 SCB-2176 Add quota manage (#1028)
462c741 is described below
commit 462c74163b9522554be4bd4e2e385bee19d44c19
Author: little-cui <[email protected]>
AuthorDate: Mon May 31 08:55:03 2021 +0800
SCB-2176 Add quota manage (#1028)
* SCB-2176 use request context instead
* SCB-2176 Add quota manage
* SCB-2176 Add quota manage
---
datasource/etcd/client/client.go | 2 +-
etc/conf/app.yaml | 4 ++++
server/plugin/auth/buildin/buildin.go | 10 ++++-----
server/plugin/quota/buildin/buildin.go | 10 +++++++--
server/plugin/quota/quota.go | 38 +++++++++++++++++++++++++++++-----
server/resource/v4/auth_resource.go | 15 +++++++-------
server/resource/v4/role_resource.go | 11 +++++-----
server/service/rbac/authr_plugin.go | 2 +-
server/service/rbac/dao/account_dao.go | 8 ++++++-
server/service/rbac/dao/role_dao.go | 7 +++++++
10 files changed, 77 insertions(+), 30 deletions(-)
diff --git a/datasource/etcd/client/client.go b/datasource/etcd/client/client.go
index 60ad919..97606d6 100644
--- a/datasource/etcd/client/client.go
+++ b/datasource/etcd/client/client.go
@@ -104,7 +104,7 @@ func Delete(ctx context.Context, key string) (bool, error) {
if err != nil {
return false, err
}
- return resp.Count != 0, nil
+ return resp.Succeeded, nil
}
func BatchCommit(ctx context.Context, opts []PluginOp) error {
diff --git a/etc/conf/app.yaml b/etc/conf/app.yaml
index 2422dc5..5a255b2 100644
--- a/etc/conf/app.yaml
+++ b/etc/conf/app.yaml
@@ -187,6 +187,10 @@ quota:
limit: 100
tag:
limit: 100
+ account:
+ limit: 1000
+ role:
+ limit: 100
uuid:
kind: context
diff --git a/server/plugin/auth/buildin/buildin.go
b/server/plugin/auth/buildin/buildin.go
index 9b4a616..1b19d33 100644
--- a/server/plugin/auth/buildin/buildin.go
+++ b/server/plugin/auth/buildin/buildin.go
@@ -18,21 +18,19 @@
package buildin
import (
- "context"
"errors"
- "github.com/apache/servicecomb-service-center/pkg/util"
"net/http"
"strings"
- "github.com/apache/servicecomb-service-center/pkg/plugin"
- "github.com/go-chassis/cari/rbac"
-
errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
"github.com/apache/servicecomb-service-center/pkg/log"
+ "github.com/apache/servicecomb-service-center/pkg/plugin"
"github.com/apache/servicecomb-service-center/pkg/rest"
+ "github.com/apache/servicecomb-service-center/pkg/util"
authHandler
"github.com/apache/servicecomb-service-center/server/handler/auth"
"github.com/apache/servicecomb-service-center/server/plugin/auth"
rbacsvc
"github.com/apache/servicecomb-service-center/server/service/rbac"
+ "github.com/go-chassis/cari/rbac"
"github.com/go-chassis/go-chassis/v2/security/authr"
"github.com/go-chassis/go-chassis/v2/server/restful"
)
@@ -148,7 +146,7 @@ func checkPerm(roleList []string, project string, req
*http.Request, apiPattern,
return false, nil, errors.New("no valid resouce scope")
}
//TODO add project
- return rbacsvc.Allow(context.TODO(), project, normalRoles,
targetResource)
+ return rbacsvc.Allow(req.Context(), project, normalRoles,
targetResource)
}
func mustAuth(pattern string) bool {
diff --git a/server/plugin/quota/buildin/buildin.go
b/server/plugin/quota/buildin/buildin.go
index 9e53a17..5bc8e01 100644
--- a/server/plugin/quota/buildin/buildin.go
+++ b/server/plugin/quota/buildin/buildin.go
@@ -31,9 +31,11 @@ func init() {
func New() plugin.Instance {
quota.Init()
- log.Infof("quota init, service: %d, instance: %d, schema: %d/service,
tag: %d/service, rule: %d/service",
+ log.Infof("quota init, service: %d, instance: %d, schema: %d/service,
tag: %d/service, rule: %d/service"+
+ ", account: %d, role: %d",
quota.DefaultServiceQuota, quota.DefaultInstanceQuota,
- quota.DefaultSchemaQuota, quota.DefaultTagQuota,
quota.DefaultRuleQuota)
+ quota.DefaultSchemaQuota, quota.DefaultTagQuota,
quota.DefaultRuleQuota,
+ quota.DefaultAccountQuota, quota.DefaultRoleQuota)
return &Quota{}
}
@@ -52,6 +54,10 @@ func (q *Quota) GetQuota(ctx context.Context, t
quota.ResourceType) int64 {
return int64(quota.DefaultSchemaQuota)
case quota.TypeTag:
return int64(quota.DefaultTagQuota)
+ case quota.TypeAccount:
+ return int64(quota.DefaultAccountQuota)
+ case quota.TypeRole:
+ return int64(quota.DefaultRoleQuota)
default:
return 0
}
diff --git a/server/plugin/quota/quota.go b/server/plugin/quota/quota.go
index 989d044..6313f8b 100644
--- a/server/plugin/quota/quota.go
+++ b/server/plugin/quota/quota.go
@@ -41,6 +41,8 @@ const (
defaultSchemaLimit = 100
defaultRuleLimit = 100
defaultTagLimit = 100
+ defaultAccountLimit = 1000
+ defaultRoleLimit = 100
)
const (
@@ -49,6 +51,8 @@ const (
TypeTag
TypeService
TypeInstance
+ TypeAccount
+ TypeRole
)
var (
@@ -57,14 +61,18 @@ var (
DefaultSchemaQuota = defaultSchemaLimit
DefaultTagQuota = defaultTagLimit
DefaultRuleQuota = defaultRuleLimit
+ DefaultAccountQuota = defaultAccountLimit
+ DefaultRoleQuota = defaultRoleLimit
)
func Init() {
- DefaultServiceQuota = config.GetInt("quota.cap.service.limit",
defaultServiceLimit, config.WithStandby("QUOTA_SERVICE"))
- DefaultInstanceQuota = config.GetInt("quota.cap.instance.limit",
defaultInstanceLimit, config.WithStandby("QUOTA_INSTANCE"))
- DefaultSchemaQuota = config.GetInt("quota.cap.schema.limit",
defaultSchemaLimit, config.WithStandby("QUOTA_SCHEMA"))
- DefaultTagQuota = config.GetInt("quota.cap.tag.limit", defaultTagLimit,
config.WithStandby("QUOTA_TAG"))
- DefaultRuleQuota = config.GetInt("quota.cap.rule.limit",
defaultRuleLimit, config.WithStandby("QUOTA_RULE"))
+ DefaultServiceQuota = config.GetInt("quota.cap.service.limit",
defaultServiceLimit, config.WithENV("QUOTA_SERVICE"))
+ DefaultInstanceQuota = config.GetInt("quota.cap.instance.limit",
defaultInstanceLimit, config.WithENV("QUOTA_INSTANCE"))
+ DefaultSchemaQuota = config.GetInt("quota.cap.schema.limit",
defaultSchemaLimit, config.WithENV("QUOTA_SCHEMA"))
+ DefaultTagQuota = config.GetInt("quota.cap.tag.limit", defaultTagLimit,
config.WithENV("QUOTA_TAG"))
+ DefaultRuleQuota = config.GetInt("quota.cap.rule.limit",
defaultRuleLimit, config.WithENV("QUOTA_RULE"))
+ DefaultAccountQuota = config.GetInt("quota.cap.account.limit",
defaultAccountLimit, config.WithENV("QUOTA_ACCOUNT"))
+ DefaultRoleQuota = config.GetInt("quota.cap.role.limit",
defaultRoleLimit, config.WithENV("QUOTA_ROLE"))
}
type ApplyQuotaResource struct {
@@ -102,6 +110,10 @@ func (r ResourceType) String() string {
return "SERVICE"
case TypeInstance:
return "INSTANCE"
+ case TypeAccount:
+ return "ACCOUNT"
+ case TypeRole:
+ return "ROLE"
default:
return "RESOURCE" + strconv.Itoa(int(r))
}
@@ -165,6 +177,22 @@ func GetResourceUsage(ctx context.Context, res
*ApplyQuotaResource) (int64, erro
case TypeTag:
// always re-create the service old tags
return 0, nil
+ case TypeRole:
+ {
+ _, used, err := datasource.Instance().ListRole(ctx)
+ if err != nil {
+ return 0, err
+ }
+ return used, nil
+ }
+ case TypeAccount:
+ {
+ _, used, err := datasource.Instance().ListAccount(ctx)
+ if err != nil {
+ return 0, err
+ }
+ return used, nil
+ }
default:
return 0, fmt.Errorf("not define quota type '%s'",
res.QuotaType)
}
diff --git a/server/resource/v4/auth_resource.go
b/server/resource/v4/auth_resource.go
index 63536f4..26c4372 100644
--- a/server/resource/v4/auth_resource.go
+++ b/server/resource/v4/auth_resource.go
@@ -18,7 +18,6 @@
package v4
import (
- "context"
"encoding/json"
"fmt"
"io/ioutil"
@@ -77,7 +76,7 @@ func (ar *AuthResource) CreateAccount(w http.ResponseWriter,
req *http.Request)
rest.WriteError(w, discovery.ErrInvalidParams, err.Error())
return
}
- err = dao.CreateAccount(context.TODO(), a)
+ err = dao.CreateAccount(req.Context(), a)
if err != nil {
if err == datasource.ErrAccountDuplicated {
rest.WriteError(w, rbac.ErrAccountConflict, "")
@@ -95,7 +94,7 @@ func (ar *AuthResource) DeleteAccount(w http.ResponseWriter,
req *http.Request)
if ar.illegalCheck(w, req, name) {
return
}
- _, err := dao.DeleteAccount(context.TODO(), name)
+ _, err := dao.DeleteAccount(req.Context(), name)
if err != nil {
log.Error(errorsEx.MsgOperateAccountFailed, err)
rest.WriteError(w, discovery.ErrInternal,
errorsEx.MsgOperateAccountFailed)
@@ -122,7 +121,7 @@ func (ar *AuthResource) UpdateAccount(w
http.ResponseWriter, req *http.Request)
return
}
- err = dao.UpdateAccount(context.TODO(), name, a)
+ err = dao.UpdateAccount(req.Context(), name, a)
if err != nil {
log.Error(errorsEx.MsgOperateAccountFailed, err)
rest.WriteError(w, discovery.ErrInternal,
errorsEx.MsgOperateAccountFailed)
@@ -132,7 +131,7 @@ func (ar *AuthResource) UpdateAccount(w
http.ResponseWriter, req *http.Request)
}
func (ar *AuthResource) ListAccount(w http.ResponseWriter, r *http.Request) {
- as, n, err := dao.ListAccount(context.TODO())
+ as, n, err := dao.ListAccount(r.Context())
if err != nil {
log.Error(errorsEx.MsgGetAccountFailed, err)
rest.WriteError(w, discovery.ErrInternal,
errorsEx.MsgGetAccountFailed)
@@ -146,7 +145,7 @@ func (ar *AuthResource) ListAccount(w http.ResponseWriter,
r *http.Request) {
}
func (ar *AuthResource) GetAccount(w http.ResponseWriter, r *http.Request) {
- a, err := dao.GetAccount(context.TODO(), r.URL.Query().Get(":name"))
+ a, err := dao.GetAccount(r.Context(), r.URL.Query().Get(":name"))
if err != nil {
log.Error(errorsEx.MsgGetAccountFailed, err)
rest.WriteError(w, discovery.ErrInternal,
errorsEx.MsgGetAccountFailed)
@@ -201,7 +200,7 @@ func (ar *AuthResource) ChangePassword(w
http.ResponseWriter, req *http.Request)
rest.WriteError(w, discovery.ErrInternal, "can not parse
account info")
return
}
- err = rbacsvc.ChangePassword(context.TODO(), changer.Roles,
changer.Name, a)
+ err = rbacsvc.ChangePassword(req.Context(), changer.Roles,
changer.Name, a)
if err != nil {
if err == rbacsvc.ErrSamePassword ||
err == rbacsvc.ErrEmptyCurrentPassword ||
@@ -248,7 +247,7 @@ func (ar *AuthResource) Login(w http.ResponseWriter, r
*http.Request) {
rest.WriteError(w, discovery.ErrForbidden, "")
return
}
- t, err := authr.Login(context.TODO(), a.Name, a.Password,
+ t, err := authr.Login(r.Context(), a.Name, a.Password,
authr.ExpireAfter(a.TokenExpirationTime))
if err != nil {
if err == rbacsvc.ErrUnauthorized {
diff --git a/server/resource/v4/role_resource.go
b/server/resource/v4/role_resource.go
index 1a6b089..b768207 100644
--- a/server/resource/v4/role_resource.go
+++ b/server/resource/v4/role_resource.go
@@ -18,7 +18,6 @@
package v4
import (
- "context"
"encoding/json"
"io/ioutil"
"net/http"
@@ -50,7 +49,7 @@ func (rr *RoleResource) URLPatterns() []rest.Route {
//ListRoles list all roles and there's permissions
func (rr *RoleResource) ListRoles(w http.ResponseWriter, req *http.Request) {
- rs, num, err := dao.ListRole(context.TODO())
+ rs, num, err := dao.ListRole(req.Context())
if err != nil {
log.Error(errorsEx.MsgGetRoleFailed, err)
rest.WriteError(w, discovery.ErrInternal,
errorsEx.MsgGetRoleFailed)
@@ -89,7 +88,7 @@ func (rr *RoleResource) CreateRole(w http.ResponseWriter, req
*http.Request) {
return
}
- status, err := dao.CreateRole(context.TODO(), role)
+ status, err := dao.CreateRole(req.Context(), role)
if err != nil {
log.Error(errorsEx.MsgOperateRoleFailed, err)
rest.WriteError(w, discovery.ErrInternal, err.Error())
@@ -112,7 +111,7 @@ func (rr *RoleResource) UpdateRole(w http.ResponseWriter,
req *http.Request) {
rest.WriteError(w, discovery.ErrInvalidParams, errorsEx.MsgJSON)
return
}
- status, err := dao.EditRole(context.TODO(), name, role)
+ status, err := dao.EditRole(req.Context(), name, role)
if err != nil {
log.Error(errorsEx.MsgOperateRoleFailed, err)
rest.WriteError(w, discovery.ErrInternal,
errorsEx.MsgOperateRoleFailed)
@@ -124,7 +123,7 @@ func (rr *RoleResource) UpdateRole(w http.ResponseWriter,
req *http.Request) {
//GetRole get the role info according to role name
func (rr *RoleResource) GetRole(w http.ResponseWriter, r *http.Request) {
- resp, status, err := dao.GetRole(context.TODO(),
r.URL.Query().Get(":roleName"))
+ resp, status, err := dao.GetRole(r.Context(),
r.URL.Query().Get(":roleName"))
if err != nil {
log.Error(errorsEx.MsgGetRoleFailed, err)
rest.WriteError(w, discovery.ErrInternal,
errorsEx.MsgGetRoleFailed)
@@ -138,7 +137,7 @@ func (rr *RoleResource) GetRole(w http.ResponseWriter, r
*http.Request) {
func (rr *RoleResource) DeleteRole(w http.ResponseWriter, req *http.Request) {
n := req.URL.Query().Get(":roleName")
- status, err := dao.DeleteRole(context.TODO(), n)
+ status, err := dao.DeleteRole(req.Context(), n)
if err != nil {
log.Error(errorsEx.MsgJSON, err)
rest.WriteError(w, discovery.ErrInternal, errorsEx.MsgJSON)
diff --git a/server/service/rbac/authr_plugin.go
b/server/service/rbac/authr_plugin.go
index d113ecf..00008bc 100644
--- a/server/service/rbac/authr_plugin.go
+++ b/server/service/rbac/authr_plugin.go
@@ -92,7 +92,7 @@ func (a *EmbeddedAuthenticator) Authenticate(ctx
context.Context, tokenStr strin
if !ok {
return nil, rbac.ErrConvert
}
- exist, err := datasource.Instance().AccountExist(context.TODO(), n)
+ exist, err := datasource.Instance().AccountExist(ctx, n)
if err != nil {
return nil, err
}
diff --git a/server/service/rbac/dao/account_dao.go
b/server/service/rbac/dao/account_dao.go
index 2c6b8dc..fe7279b 100644
--- a/server/service/rbac/dao/account_dao.go
+++ b/server/service/rbac/dao/account_dao.go
@@ -21,9 +21,10 @@ package dao
import (
"context"
"errors"
-
"github.com/apache/servicecomb-service-center/datasource"
"github.com/apache/servicecomb-service-center/pkg/log"
+ "github.com/apache/servicecomb-service-center/pkg/util"
+ "github.com/apache/servicecomb-service-center/server/plugin/quota"
rbacmodel "github.com/go-chassis/cari/rbac"
)
@@ -31,6 +32,11 @@ import (
//CreateAccount save 2 kv
//1. account info
func CreateAccount(ctx context.Context, a *rbacmodel.Account) error {
+ err := quota.Apply(ctx, quota.NewApplyQuotaResource(quota.TypeAccount,
+ util.ParseDomainProject(ctx), "", 1))
+ if err != nil {
+ return err
+ }
return datasource.Instance().CreateAccount(ctx, a)
}
diff --git a/server/service/rbac/dao/role_dao.go
b/server/service/rbac/dao/role_dao.go
index 6964206..df8feef 100644
--- a/server/service/rbac/dao/role_dao.go
+++ b/server/service/rbac/dao/role_dao.go
@@ -21,6 +21,8 @@ import (
"context"
"errors"
errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
+ "github.com/apache/servicecomb-service-center/pkg/util"
+ "github.com/apache/servicecomb-service-center/server/plugin/quota"
"github.com/apache/servicecomb-service-center/server/service/validator"
"github.com/go-chassis/cari/discovery"
@@ -36,6 +38,11 @@ func CreateRole(ctx context.Context, r *rbac.Role)
(*discovery.Response, error)
log.Errorf(err, "create role [%s] failed", r.Name)
return discovery.CreateResponse(discovery.ErrInvalidParams,
err.Error()), nil
}
+ quotaErr := quota.Apply(ctx, quota.NewApplyQuotaResource(quota.TypeRole,
+ util.ParseDomainProject(ctx), "", 1))
+ if quotaErr != nil {
+ return discovery.CreateResponse(discovery.ErrNotEnoughQuota,
quotaErr.Error()), nil
+ }
err = datasource.Instance().CreateRole(ctx, r)
if err == nil {
log.Infof("create role [%s] success", r.Name)