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 2d0f9c6  able to change password (#652)
2d0f9c6 is described below

commit 2d0f9c6dc758af85a5875bb027bd571e686c7325
Author: Shawn <[email protected]>
AuthorDate: Mon Jun 29 08:36:50 2020 +0800

    able to change password (#652)
---
 docs/user-guides/rbac.md                   |  37 ++++++--
 pkg/model/account.go                       |  12 ++-
 server/handler/auth/auth.go                |  20 +++--
 server/rest/controller/v4/auth_resource.go |  53 ++++++++++-
 server/service/rbac/authr_plugin.go        |   8 +-
 server/service/rbac/dao/account_dao.go     |  28 ++++++
 server/service/rbac/dao/secret_dao.go      |  53 -----------
 server/service/rbac/dao/secret_dao_test.go |  36 --------
 server/service/rbac/rbac.go                | 137 ++++++++++++++++++-----------
 server/service/rbac/rbca_test.go           |  28 ++++--
 server/service/util/common.go              |   4 +
 11 files changed, 245 insertions(+), 171 deletions(-)

diff --git a/docs/user-guides/rbac.md b/docs/user-guides/rbac.md
index aee26af..b8ed63a 100644
--- a/docs/user-guides/rbac.md
+++ b/docs/user-guides/rbac.md
@@ -13,23 +13,27 @@ openssl rsa -in private.key -pubout -out public.key
 ```
 
 2.edit app.conf
+
+can revoke private.key after each cluster restart,
 ```ini
 rbac_enabled = true
-rbac_rsa_pub_key_file = ./public.key
+rbac_rsa_public_key_file = ./public.key
+rbac_rsa_private_key_file = ./private.key
 ```
+3.root account
+before you start server, you need to set env to set your root account 
password.  
 
-before you start server, you need to set env to set your root account.  
-can revoke private.key after each cluster restart,can not revoke root name and 
password
 ```sh
-export SC_INIT_ROOT_USERNAME=root  
 export SC_INIT_ROOT_PASSWORD=rootpwd
-export SC_INIT_PRIVATE_KEY=`cat private.key`
 ```
-at the first time service center cluster init, it will use this env to setup 
rbac module.
+at the first time service center cluster init, it will use this env to setup 
rbac module. you can not revoke password after cluster start
+
+the root account name is "root"
 
 To securely distribute your root account and private key, 
 you can use kubernetes 
[secret](https://kubernetes.io/zh/docs/tasks/inject-data-application/distribute-credentials-secure/)
 ### Generate a token 
+token is the only credential to access rest API, before you access any API, 
you need to get a token
 ```shell script
 curl -X POST \
   http://127.0.0.1:30100/v4/token \
@@ -42,12 +46,27 @@ will return a token, token will expired after 30m
 ```
 
 ### Authentication
-in each request you must add token to  http header
+in each request you must add token to  http header:
+```
 Authorization: Bear {token}
-
+```
 for example:
 ```shell script
 curl -X GET \
   
'http://127.0.0.1:30100/v4/default/registry/microservices/{service-id}/instances'
 \
   -H 'Authorization: Bear 
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTI4OTQ1NTEsInVzZXIiOiJyb290In0.FfLOSvVmHT9qCZSe_6iPf4gNjbXLwCrkXxKHsdJoQ8w'
 
-```
\ No newline at end of file
+```
+
+### Change password
+You must supply current password and token to update to new password
+curl -X PUT \
+  http://127.0.0.1:30100/v4/account-password \
+  -H 'Authorization: Bear 
eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50Ijoicm9vdCIsImV4cCI6MTU5MzMyOTE3OSwicm9sZSI6IiJ9.OR_uruuLds1wz10_J4gDEA-L9Ma_1RrHiKEA6CS-Nilv6hHB5KyhZ9_4qqf_c0iia4uKryAGHKsXUvrjOE51tz4QCXlgCmddrkYuLQsnDezXhV3TIqzdl4R_cy8h2cZo8O_b_q7eU2Iemd6x7BJE49SLgNiP5LTXCVct5Qm_GiXYTaM4dbHIJ01V-EPmNQuBr1vKdfNa8cqWtASSp9IEkFx1YpzhFacQgmfoiSGHvxQYZldQXuAh60ZXLBDexGu6jGnG39MqVNRysvHTpZRqxZWBhmEn5DeXpgKu-zlakJMjeEma4zcN-H0MumE-nMlBT5kjKWVr1DOdtOyJI6i786ZpS0wWHV4VOxpSursoKsW_XuTZ
 [...]
+  -d '{
+       "currentPassword":"rootpwd",
+       "password":"123"
+}'
+### Roles TODO
+currently, you can not custom and manage any role and role policy. there is 
only 1 build in roles
+- admin: able to do anything, including manage account, even change other 
account password
+- service: able to call most of API except account management.
\ No newline at end of file
diff --git a/pkg/model/account.go b/pkg/model/account.go
index 4211772..b1da8dd 100644
--- a/pkg/model/account.go
+++ b/pkg/model/account.go
@@ -17,11 +17,17 @@
 
 package model
 
+const (
+       RoleAdmin   = "admin"
+       RoleAuditor = "auditor"
+)
+
 type Account struct {
-       Name     string `json:"name,omitempty"`
-       Password string `json:"password,omitempty"`
+       Name            string `json:"name,omitempty"`
+       Password        string `json:"password,omitempty"`
+       Role            string `json:"role,omitempty"`
+       CurrentPassword string `json:"currentPassword,omitempty"`
 }
-
 type Token struct {
        TokenStr string `json:"token,omitempty"`
 }
diff --git a/server/handler/auth/auth.go b/server/handler/auth/auth.go
index 9fbd5b3..7105ca8 100644
--- a/server/handler/auth/auth.go
+++ b/server/handler/auth/auth.go
@@ -17,6 +17,7 @@
 package auth
 
 import (
+       "context"
        "github.com/apache/servicecomb-service-center/pkg/chain"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rest"
@@ -63,15 +64,20 @@ func (h *Handler) Handle(i *chain.Invocation) {
        }
        to := s[1]
        //TODO rbac
-       _, err := authr.Authenticate(i.Context(), to)
-       if err == nil {
-               log.Info("user access")
-               i.Next()
+       claims, err := authr.Authenticate(i.Context(), to)
+       if err != nil {
+               log.Errorf(err, "authenticate request failed, %s %s", 
req.Method, req.RequestURI)
+               controller.WriteError(w, scerr.ErrUnauthorized, err.Error())
+               i.Fail(nil)
                return
        }
-       log.Errorf(err, "authenticate request failed, %s %s", req.Method, 
req.RequestURI)
-       controller.WriteError(w, scerr.ErrUnauthorized, err.Error())
-       i.Fail(nil)
+       log.Info("user access")
+       req2 := req.WithContext(context.WithValue(req.Context(), "accountInfo", 
claims))
+
+       *req = *req2
+       i.Next()
+       return
+
 }
 func mustAuth(req *http.Request) bool {
        if strings.Contains(req.URL.Path, "/v4/token") {
diff --git a/server/rest/controller/v4/auth_resource.go 
b/server/rest/controller/v4/auth_resource.go
index 5839e1f..8232452 100644
--- a/server/rest/controller/v4/auth_resource.go
+++ b/server/rest/controller/v4/auth_resource.go
@@ -19,12 +19,14 @@ package v4
 import (
        "context"
        "encoding/json"
+       "errors"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/model"
        "github.com/apache/servicecomb-service-center/pkg/rest"
        "github.com/apache/servicecomb-service-center/server/rest/controller"
        "github.com/apache/servicecomb-service-center/server/scerror"
        "github.com/apache/servicecomb-service-center/server/service/rbac"
+       "github.com/apache/servicecomb-service-center/server/service/util"
        "github.com/go-chassis/go-chassis/security/authr"
        "io/ioutil"
        "net/http"
@@ -37,9 +39,58 @@ type AuthResource struct {
 func (r *AuthResource) URLPatterns() []rest.Route {
        return []rest.Route{
                {http.MethodPost, "/v4/token", r.Login},
+               {http.MethodPut, "/v4/account-password", r.ChangePassword},
+       }
+}
+func (r *AuthResource) ChangePassword(w http.ResponseWriter, req 
*http.Request) {
+       body, err := ioutil.ReadAll(req.Body)
+       if err != nil {
+               log.Error("read body err", err)
+               controller.WriteError(w, scerror.ErrInternal, err.Error())
+               return
+       }
+       a := &model.Account{}
+       if err = json.Unmarshal(body, a); err != nil {
+               log.Error("json err", err)
+               controller.WriteError(w, scerror.ErrInvalidParams, err.Error())
+               return
+       }
+       if a.Password == "" {
+               controller.WriteError(w, scerror.ErrInvalidParams, "new 
password is empty")
+               return
+       }
+       claims := req.Context().Value("accountInfo")
+       m, ok := claims.(map[string]interface{})
+       if !ok {
+               log.Error("claims convert failed", 
errors.New(util.ErrMsgConvert))
+               controller.WriteError(w, scerror.ErrInvalidParams, 
util.ErrMsgConvert)
+               return
+       }
+       accountNameI := m[rbac.ClaimsUser]
+       changer, ok := accountNameI.(string)
+       if !ok {
+               log.Error("claims convert failed", 
errors.New(util.ErrMsgConvert))
+               controller.WriteError(w, scerror.ErrInternal, 
util.ErrMsgConvert)
+               return
+       }
+       roleI := m[rbac.ClaimsRole]
+       role, ok := roleI.(string)
+       if !ok {
+               log.Error("claims convert failed", 
errors.New(util.ErrMsgConvert))
+               controller.WriteError(w, scerror.ErrInternal, 
util.ErrMsgConvert)
+               return
+       }
+       if role == "" {
+               controller.WriteError(w, scerror.ErrInvalidParams, "role is 
empty")
+               return
+       }
+       err = rbac.ChangePassword(context.TODO(), role, changer, a)
+       if err != nil {
+               log.Error("change password failed", err)
+               controller.WriteError(w, scerror.ErrInternal, err.Error())
+               return
        }
 }
-
 func (r *AuthResource) Login(w http.ResponseWriter, req *http.Request) {
        body, err := ioutil.ReadAll(req.Body)
        if err != nil {
diff --git a/server/service/rbac/authr_plugin.go 
b/server/service/rbac/authr_plugin.go
index 6bba434..3d2ea24 100644
--- a/server/service/rbac/authr_plugin.go
+++ b/server/service/rbac/authr_plugin.go
@@ -31,7 +31,8 @@ import (
 var ErrUnauthorized = errors.New("wrong user name or password")
 
 const (
-       ClaimsUser = "user"
+       ClaimsUser = "account"
+       ClaimsRole = "role"
 )
 
 //EmbeddedAuthenticator is sc default auth plugin, RBAC data is persisted in 
etcd
@@ -57,12 +58,13 @@ func (a *EmbeddedAuthenticator) Login(ctx context.Context, 
user string, password
                return "", err
        }
        if user == account.Name && password == account.Password {
-               secret, err := GetPrivateKey(ctx)
+               secret, err := GetPrivateKey()
                if err != nil {
                        return "", err
                }
                tokenStr, err := token.Sign(map[string]interface{}{
-                       ClaimsUser: user, //TODO more claims for RBAC, for 
example role name
+                       ClaimsUser: user,
+                       ClaimsRole: account.Role, //TODO more claims for RBAC, 
for example rule config
                },
                        secret,
                        token.WithExpTime("30m"),
diff --git a/server/service/rbac/dao/account_dao.go 
b/server/service/rbac/dao/account_dao.go
index 07a81f2..0a0d076 100644
--- a/server/service/rbac/dao/account_dao.go
+++ b/server/service/rbac/dao/account_dao.go
@@ -30,6 +30,7 @@ import (
 )
 
 var ErrDuplicated = errors.New("account is duplicated")
+var ErrCanNotEdit = errors.New("account can not be edited")
 
 //CreateAccount save 2 kv
 //1. account info
@@ -86,3 +87,30 @@ func AccountExist(ctx context.Context, name string) (bool, 
error) {
        }
        return exist, nil
 }
+
+//CreateAccount save 2 kv
+//1. account info
+func EditAccount(ctx context.Context, a *model.Account) error {
+       key := core.GenerateAccountKey(a.Name)
+       exist, err := kv.Exist(ctx, key)
+       if err != nil {
+               log.Errorf(err, "can not edit account info")
+               return err
+       }
+       if !exist {
+               return ErrCanNotEdit
+       }
+
+       value, err := json.Marshal(a)
+       if err != nil {
+               log.Errorf(err, "account info is invalid")
+               return err
+       }
+       err = kv.PutBytes(ctx, key, value)
+       if err != nil {
+               log.Errorf(err, "can not edit account info")
+               return err
+       }
+
+       return nil
+}
diff --git a/server/service/rbac/dao/secret_dao.go 
b/server/service/rbac/dao/secret_dao.go
deleted file mode 100644
index b2cd837..0000000
--- a/server/service/rbac/dao/secret_dao.go
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dao
-
-import (
-       "context"
-       "github.com/apache/servicecomb-service-center/pkg/log"
-       "github.com/apache/servicecomb-service-center/server/core"
-       "github.com/apache/servicecomb-service-center/server/service/kv"
-)
-
-//OverrideSecret write secret to kv store
-func OverrideSecret(ctx context.Context, sk string) error {
-       key := core.GenerateRBACSecretKey()
-       err := kv.Put(context.Background(), key, sk)
-       if err != nil {
-               log.Errorf(err, "can not override secret")
-               return err
-       }
-       return nil
-}
-func GetSecret(ctx context.Context) ([]byte, error) {
-       key := core.GenerateRBACSecretKey()
-       r, err := kv.Get(ctx, key)
-       if err != nil {
-               log.Errorf(err, "can not get secret")
-               return nil, err
-       }
-       return r.Value, nil
-}
-func SecretExist(ctx context.Context) (bool, error) {
-       exist, err := kv.Exist(ctx, core.GenerateRBACSecretKey())
-       if err != nil {
-               log.Errorf(err, "can not get secret info")
-               return false, err
-       }
-       return exist, nil
-}
diff --git a/server/service/rbac/dao/secret_dao_test.go 
b/server/service/rbac/dao/secret_dao_test.go
deleted file mode 100644
index 8012788..0000000
--- a/server/service/rbac/dao/secret_dao_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dao_test
-
-import (
-       "context"
-       "github.com/apache/servicecomb-service-center/server/service/rbac/dao"
-       "github.com/stretchr/testify/assert"
-       "testing"
-)
-
-func TestOverrideSecret(t *testing.T) {
-       err := dao.OverrideSecret(context.Background(), "sk")
-       assert.NoError(t, err)
-       s, err := dao.GetSecret(context.Background())
-       assert.NoError(t, err)
-       assert.Equal(t, "sk", string(s))
-       b, err := dao.SecretExist(context.Background())
-       assert.NoError(t, err)
-       assert.True(t, b)
-}
diff --git a/server/service/rbac/rbac.go b/server/service/rbac/rbac.go
index 4840713..5cef488 100644
--- a/server/service/rbac/rbac.go
+++ b/server/service/rbac/rbac.go
@@ -20,6 +20,7 @@ package rbac
 import (
        "context"
        "crypto/rsa"
+       "errors"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/model"
        "github.com/apache/servicecomb-service-center/server/service/cipher"
@@ -28,14 +29,18 @@ import (
        "github.com/go-chassis/go-archaius"
        "github.com/go-chassis/go-chassis/security/authr"
        "github.com/go-chassis/go-chassis/security/secret"
-       "io"
-       "os"
+       "io/ioutil"
 )
 
 const (
-       InitRoot     = "SC_INIT_ROOT_USERNAME"
+       RootName     = "root"
        InitPassword = "SC_INIT_ROOT_PASSWORD"
-       InitPrivate  = "SC_INIT_PRIVATE_KEY"
+       PubFilePath  = "rbac_rsa_public_key_file"
+)
+
+var (
+       ErrInputCurrentPassword = errors.New("current password should not be 
empty")
+       ErrInputChangeAccount   = errors.New("can not change other account 
password")
 )
 
 //Init decide whether enable rbac function and save root account to db
@@ -49,43 +54,42 @@ func Init() {
        if err != nil {
                log.Fatal("can not enable auth module", err)
        }
-       admin := archaius.GetString(InitRoot, "")
-       if admin == "" {
-               log.Fatal("can not enable rbac, root is empty", nil)
-               return
-       }
-       accountExist, err := dao.AccountExist(context.Background(), admin)
+       accountExist, err := dao.AccountExist(context.Background(), RootName)
        if err != nil {
                log.Fatal("can not enable auth module", err)
        }
        if !accountExist {
-               initFirstTime(admin)
+               initFirstTime(RootName)
        }
-       overrideSecretKey()
+       readPrivateKey()
        readPublicKey()
        log.Info("rbac is enabled")
 }
 
 //readPublicKey read key to memory
-func readPublicKey() {
-       pf := beego.AppConfig.String("rbac_rsa_pub_key_file")
+func readPrivateKey() {
+       pf := beego.AppConfig.String("rbac_rsa_private_key_file")
        // 打开文件
-       fp, err := os.Open(pf)
+       data, err := ioutil.ReadFile(pf)
        if err != nil {
-               log.Fatal("can not find public key", err)
+               log.Fatal("can not read private key", err)
                return
        }
-       defer fp.Close()
-       buf := make([]byte, 1024)
-       for {
-               // 循环读取文件
-               _, err := fp.Read(buf)
-               if err == io.EOF { // io.EOF表示文件末尾
-                       break
-               }
+       archaius.Set("rbac_private_key", string(data))
+       log.Info("read private key success")
+}
 
+//readPublicKey read key to memory
+func readPublicKey() {
+       pf := beego.AppConfig.String(PubFilePath)
+       // 打开文件
+       content, err := ioutil.ReadFile(pf)
+       if err != nil {
+               log.Fatal("can not find public key", err)
+               return
        }
-       archaius.Set("rbac_public_key", string(buf))
+       archaius.Set("rbac_public_key", string(content))
+       log.Info("read public key success")
 }
 func initFirstTime(admin string) {
        //handle root account
@@ -93,13 +97,10 @@ func initFirstTime(admin string) {
        if pwd == "" {
                log.Fatal("can not enable rbac, password is empty", nil)
        }
-       pwd, err := cipher.Encrypt(pwd)
-       if err != nil {
-               log.Fatal("can not enable rbac, encryption failed", err)
-       }
        if err := dao.CreateAccount(context.Background(), &model.Account{
                Name:     admin,
                Password: pwd,
+               Role:     model.RoleAdmin,
        }); err != nil {
                if err == dao.ErrDuplicated {
                        log.Info("rbac is enabled")
@@ -110,18 +111,6 @@ func initFirstTime(admin string) {
        log.Info("root account init success")
 }
 
-//should override key on each start procedure,
-//so that a system such as kubernetes can use secret to distribute a new 
secret to revoke the old one
-func overrideSecretKey() {
-       secret := archaius.GetString(InitPrivate, "")
-       if secret == "" {
-               log.Fatal("can not enable rbac, secret is empty", nil)
-       }
-       if err := dao.OverrideSecret(context.Background(), secret); err != nil {
-               log.Fatal("can not save secret", err)
-       }
-
-}
 func Enabled() bool {
        return beego.AppConfig.DefaultBool("rbac_enabled", false)
 }
@@ -131,23 +120,19 @@ func PublicKey() string {
        return archaius.GetString("rbac_public_key", "")
 }
 
-//GetSecretStr return decrypted secret
-func GetSecretStr(ctx context.Context) (string, error) {
-       sk, err := dao.GetSecret(ctx)
+//privateKey get decrypted private key to verify a token
+func privateKey() (string, error) {
+       ep := archaius.GetString("rbac_private_key", "")
+       p, err := cipher.Decrypt(ep)
        if err != nil {
                return "", err
        }
-       skStr, err := cipher.Decrypt(string(sk))
-       if err != nil {
-               log.Error("can not decrypt:", err)
-               return "", err
-       }
-       return skStr, nil
+       return p, nil
 }
 
 //GetPrivateKey return rsa key instance
-func GetPrivateKey(ctx context.Context) (*rsa.PrivateKey, error) {
-       sk, err := GetSecretStr(ctx)
+func GetPrivateKey() (*rsa.PrivateKey, error) {
+       sk, err := privateKey()
        if err != nil {
                return nil, err
        }
@@ -158,3 +143,51 @@ func GetPrivateKey(ctx context.Context) (*rsa.PrivateKey, 
error) {
        }
        return p, nil
 }
+
+func ChangePassword(ctx context.Context, changerRole, changerName string, a 
*model.Account) error {
+       if a.Name != "" {
+               if changerRole != model.RoleAdmin { //need to check password 
mismatch. but admin role can change any user password without supply current 
password
+                       log.Error("can not change other account pwd", nil)
+                       return ErrInputChangeAccount
+               }
+               return changePasswordForcibly(ctx, a.Name, a.Password)
+       } else {
+               if a.CurrentPassword == "" {
+                       log.Error("current pwd is empty", nil)
+                       return ErrInputCurrentPassword
+               }
+               return changePassword(ctx, changerName, a.CurrentPassword, 
a.Password)
+       }
+}
+func changePasswordForcibly(ctx context.Context, name, pwd string) error {
+       old, err := dao.GetAccount(ctx, name)
+       if err != nil {
+               log.Error("can not change pwd", err)
+               return err
+       }
+       old.Password = pwd
+       err = dao.EditAccount(ctx, old)
+       if err != nil {
+               log.Error("can not change pwd", err)
+               return err
+       }
+       return nil
+}
+func changePassword(ctx context.Context, name, currentPassword, pwd string) 
error {
+       old, err := dao.GetAccount(ctx, name)
+       if err != nil {
+               log.Error("can not change pwd", err)
+               return err
+       }
+       if old.Password != currentPassword {
+               log.Error("current pwd is wrong", nil)
+               return errors.New("can not change pwd")
+       }
+       old.Password = pwd
+       err = dao.EditAccount(ctx, old)
+       if err != nil {
+               log.Error("can not change pwd", err)
+               return err
+       }
+       return nil
+}
diff --git a/server/service/rbac/rbca_test.go b/server/service/rbac/rbca_test.go
index a4db540..b01aa28 100644
--- a/server/service/rbac/rbca_test.go
+++ b/server/service/rbac/rbca_test.go
@@ -19,6 +19,7 @@ package rbac_test
 
 import (
        "context"
+       "github.com/apache/servicecomb-service-center/pkg/model"
        mgr "github.com/apache/servicecomb-service-center/server/plugin"
        
"github.com/apache/servicecomb-service-center/server/plugin/pkg/discovery/etcd"
        etcd2 
"github.com/apache/servicecomb-service-center/server/plugin/pkg/registry/etcd"
@@ -38,7 +39,8 @@ import (
 func init() {
        beego.AppConfig.Set("registry_plugin", "etcd")
        beego.AppConfig.Set("rbac_enabled", "true")
-       beego.AppConfig.Set("rbac_rsa_pub_key_file", "./rbac.pub")
+       beego.AppConfig.Set(rbac.PubFilePath, "./rbac.pub")
+       beego.AppConfig.Set("rbac_rsa_private_key_file", "./private.key")
        mgr.RegisterPlugin(mgr.Plugin{mgr.REGISTRY, "etcd", etcd2.NewRegistry})
        mgr.RegisterPlugin(mgr.Plugin{mgr.DISCOVERY, "buildin", 
etcd.NewRepository})
        mgr.RegisterPlugin(mgr.Plugin{mgr.DISCOVERY, "etcd", 
etcd.NewRepository})
@@ -55,22 +57,17 @@ func TestInitRBAC(t *testing.T) {
 
        b, err := secret.RSAPrivate2Bytes(pri)
        assert.NoError(t, err)
-       archaius.Set(rbac.InitPrivate, string(b))
-
+       ioutil.WriteFile("./private.key", b, 0600)
        b, err = secret.RSAPublicKey2Bytes(pub)
        err = ioutil.WriteFile("./rbac.pub", b, 0600)
        assert.NoError(t, err)
 
-       archaius.Set(rbac.InitRoot, "root")
        archaius.Set(rbac.InitPassword, "root")
 
        rbac.Init()
        a, err := dao.GetAccount(context.Background(), "root")
        assert.NoError(t, err)
        assert.Equal(t, "root", a.Name)
-       s, err := dao.GetSecret(context.Background())
-       assert.NoError(t, err)
-       assert.NotEmpty(t, s)
 
        t.Run("login and authenticate", func(t *testing.T) {
                token, err := authr.Login(context.Background(), "root", "root")
@@ -84,4 +81,21 @@ func TestInitRBAC(t *testing.T) {
        t.Run("second time init", func(t *testing.T) {
                rbac.Init()
        })
+
+       t.Run("change pwd,admin can change any one password", func(t 
*testing.T) {
+               dao.CreateAccount(context.Background(), &model.Account{Name: 
"a", Password: "123"})
+               err := rbac.ChangePassword(context.Background(), 
model.RoleAdmin, "admin", &model.Account{Name: "a", Password: "1234"})
+               assert.NoError(t, err)
+               a, err := dao.GetAccount(context.Background(), "a")
+               assert.NoError(t, err)
+               assert.Equal(t, "1234", a.Password)
+       })
+       t.Run("change own password", func(t *testing.T) {
+               dao.CreateAccount(context.Background(), &model.Account{Name: 
"b", Password: "123"})
+               err := rbac.ChangePassword(context.Background(), "", "b", 
&model.Account{CurrentPassword: "123", Password: "1234"})
+               assert.NoError(t, err)
+               a, err := dao.GetAccount(context.Background(), "b")
+               assert.NoError(t, err)
+               assert.Equal(t, "1234", a.Password)
+       })
 }
diff --git a/server/service/util/common.go b/server/service/util/common.go
index 88c5737..b34362d 100644
--- a/server/service/util/common.go
+++ b/server/service/util/common.go
@@ -24,3 +24,7 @@ const (
        CTX_REQUEST_REVISION  = "requestRev"
        CTX_RESPONSE_REVISION = "responseRev"
 )
+
+const (
+       ErrMsgConvert = "type convert error"
+)

Reply via email to