From d20349ad68551486c3e5b14b7649900925afb487 Mon Sep 17 00:00:00 2001 From: Ooo0oO0o0oO <907709476@qq.com> Date: Wed, 15 Jan 2020 19:27:39 +0800 Subject: [PATCH] add junit test --- common/constant/key.go | 7 +- common/extension/auth.go | 8 +- filter/accesskey.go | 8 +- filter/auth_spi.go | 1 - filter/filter_impl/auth/accesskey_storage.go | 10 +- .../auth/accesskey_storage_test.go | 25 ++++ filter/filter_impl/auth/authenticator.go | 5 +- filter/filter_impl/auth/authenticator_test.go | 128 ++++++++++++++++++ filter/filter_impl/auth/consumer_sign_test.go | 34 +++++ filter/filter_impl/auth/provider_auth_test.go | 53 ++++++++ filter/filter_impl/auth/sign_util.go | 17 +-- filter/filter_impl/auth/sign_util_test.go | 72 ++++------ 12 files changed, 296 insertions(+), 72 deletions(-) create mode 100644 filter/filter_impl/auth/accesskey_storage_test.go create mode 100644 filter/filter_impl/auth/authenticator_test.go create mode 100644 filter/filter_impl/auth/consumer_sign_test.go create mode 100644 filter/filter_impl/auth/provider_auth_test.go diff --git a/common/constant/key.go b/common/constant/key.go index 45f79d39e..eff704371 100644 --- a/common/constant/key.go +++ b/common/constant/key.go @@ -145,16 +145,17 @@ const ( const ( CONSUMER_SIGN_FILTER = "sign" PROVIDER_AUTH_FILTER = "auth" - SERVICE_AUTH_KEY = "auth" - AUTHENTICATOR_KEY = "authenticator" + SERVICE_AUTH_KEY = "auth" + AUTHENTICATOR_KEY = "authenticator" DEFAULT_AUTHENTICATOR = "accesskeys" DEFAULT_ACCESS_KEY_STORAGE = "urlstorage" ACCESS_KEY_STORAGE_KEY = "accessKey.storage" - SECRET_ACCESS_KEY_KEY = "secretAccessKey" REQUEST_TIMESTAMP_KEY = "timestamp" REQUEST_SIGNATURE_KEY = "signature" AK_KEY = "ak" SIGNATURE_STRING_FORMAT = "%s#%s#%s#%s" PARAMTER_SIGNATURE_ENABLE_KEY = "param.sign" CONSUMER = "consumer" + ACCESS_KEY_ID_KEY = "accessKeyId" + SECRET_ACCESS_KEY_KEY = "secretAccessKey" ) diff --git a/common/extension/auth.go b/common/extension/auth.go index 39c215660..f8d1cbeb4 100644 --- a/common/extension/auth.go +++ b/common/extension/auth.go @@ -15,8 +15,8 @@ func SetAuthenticator(name string, fcn func() filter.Authenticator) { } func GetAuthenticator(name string) filter.Authenticator { - if clusters[name] == nil { - panic("cluster for " + name + " is not existing, make sure you have import the package.") + if authenticators[name] == nil { + panic("authenticator for " + name + " is not existing, make sure you have import the package.") } return authenticators[name]() } @@ -26,8 +26,8 @@ func SetAccesskeyStorages(name string, fcn func() filter.AccesskeyStorage) { } func GetAccesskeyStorages(name string) filter.AccesskeyStorage { - if clusters[name] == nil { - panic("cluster for " + name + " is not existing, make sure you have import the package.") + if accesskeyStorages[name] == nil { + panic("accesskeyStorages for " + name + " is not existing, make sure you have import the package.") } return accesskeyStorages[name]() } \ No newline at end of file diff --git a/filter/accesskey.go b/filter/accesskey.go index 682e2b190..0ec97b739 100644 --- a/filter/accesskey.go +++ b/filter/accesskey.go @@ -1,10 +1,10 @@ package filter type AccessKeyPair struct { - AccessKey string - SecretKey string + AccessKey string + SecretKey string ConsumerSide string ProviderSide string - Creator string - Options string + Creator string + Options string } diff --git a/filter/auth_spi.go b/filter/auth_spi.go index edbea66e0..4a9c17c52 100644 --- a/filter/auth_spi.go +++ b/filter/auth_spi.go @@ -13,4 +13,3 @@ type Authenticator interface { type AccesskeyStorage interface { GetAccesskeyPair(protocol.Invocation, *common.URL) *AccessKeyPair } - diff --git a/filter/filter_impl/auth/accesskey_storage.go b/filter/filter_impl/auth/accesskey_storage.go index 82c393b7c..c957cae6d 100644 --- a/filter/filter_impl/auth/accesskey_storage.go +++ b/filter/filter_impl/auth/accesskey_storage.go @@ -8,19 +8,13 @@ import ( "github.com/apache/dubbo-go/protocol" ) -const ( - ACCESS_KEY_ID_KEY = "accessKeyId" - - SECRET_ACCESS_KEY_KEY = "secretAccessKey" -) - type DefaultAccesskeyStorage struct { } func (storage *DefaultAccesskeyStorage) GetAccesskeyPair(invocation protocol.Invocation, url *common.URL) *filter.AccessKeyPair { return &filter.AccessKeyPair{ - AccessKey: url.GetParam(ACCESS_KEY_ID_KEY, ""), - SecretKey: url.GetParam(SECRET_ACCESS_KEY_KEY, ""), + AccessKey: url.GetParam(constant.ACCESS_KEY_ID_KEY, ""), + SecretKey: url.GetParam(constant.SECRET_ACCESS_KEY_KEY, ""), } } diff --git a/filter/filter_impl/auth/accesskey_storage_test.go b/filter/filter_impl/auth/accesskey_storage_test.go new file mode 100644 index 000000000..ab734bfb6 --- /dev/null +++ b/filter/filter_impl/auth/accesskey_storage_test.go @@ -0,0 +1,25 @@ +package auth + +import ( + "net/url" + "testing" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + invocation2 "github.com/apache/dubbo-go/protocol/invocation" + "github.com/stretchr/testify/assert" +) + +func TestDefaultAccesskeyStorage_GetAccesskeyPair(t *testing.T) { + url := common.NewURLWithOptions( + common.WithParams(url.Values{}), + common.WithParamsValue(constant.SECRET_ACCESS_KEY_KEY, "skey"), + common.WithParamsValue(constant.ACCESS_KEY_ID_KEY, "akey")) + invocation := &invocation2.RPCInvocation{} + storage := GetDefaultAccesskeyStorage() + accesskeyPair := storage.GetAccesskeyPair(invocation, url) + assert.Equal(t, "skey", accesskeyPair.SecretKey) + assert.Equal(t, "akey", accesskeyPair.AccessKey) +} diff --git a/filter/filter_impl/auth/authenticator.go b/filter/filter_impl/auth/authenticator.go index 31589a52c..a3e20c9e3 100644 --- a/filter/filter_impl/auth/authenticator.go +++ b/filter/filter_impl/auth/authenticator.go @@ -24,7 +24,7 @@ type DefaultAuthenticator struct { } func (authenticator *DefaultAuthenticator) Sign(invocation protocol.Invocation, url *common.URL) error { - currentTimeMillis := strconv.Itoa(time.Now().Second() * 1000) + currentTimeMillis := strconv.Itoa(int(time.Now().Unix() * 1000)) consumer := url.GetParam(constant.APPLICATION_KEY, "") accessKeyPair, err := getAccessKeyPair(invocation, url) @@ -67,7 +67,8 @@ func (authenticator *DefaultAuthenticator) Authenticate(invocation protocol.Invo requestTimestamp := invocation.AttachmentsByKey(constant.REQUEST_TIMESTAMP_KEY, "") originSignature := invocation.AttachmentsByKey(constant.REQUEST_SIGNATURE_KEY, "") consumer := invocation.AttachmentsByKey(constant.CONSUMER, "") - if IsEmpty(accessKeyId, false) || IsEmpty(consumer, false) || IsEmpty(requestTimestamp, false) || IsEmpty(originSignature, false) { + if IsEmpty(accessKeyId, false) || IsEmpty(consumer, false) || + IsEmpty(requestTimestamp, false) || IsEmpty(originSignature, false) { return errors.New("failed to authenticate, maybe consumer not enable the auth") } diff --git a/filter/filter_impl/auth/authenticator_test.go b/filter/filter_impl/auth/authenticator_test.go new file mode 100644 index 000000000..6aba4fe76 --- /dev/null +++ b/filter/filter_impl/auth/authenticator_test.go @@ -0,0 +1,128 @@ +package auth + +import ( + "context" + "fmt" + "net/url" + "strconv" + "testing" + "time" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/stretchr/testify/assert" +) + +func TestDefaultAuthenticator_Authenticate(t *testing.T) { + secret := "dubbo-sk" + access := "dubbo-ak" + testurl, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=gg&version=2.6.0") + testurl.SetParam(constant.PARAMTER_SIGNATURE_ENABLE_KEY, "true") + testurl.SetParam(constant.ACCESS_KEY_ID_KEY, access) + testurl.SetParam(constant.SECRET_ACCESS_KEY_KEY, secret) + parmas := []interface{}{"OK", struct { + Name string + Id int64 + }{"YUYU", 1}} + inv := invocation.NewRPCInvocation("test", parmas, nil) + requestTime := strconv.Itoa(int(time.Now().Unix() * 1000)) + signature, _ := getSignature(&testurl, inv, secret, requestTime) + + var authenticator = &DefaultAuthenticator{} + + invcation := invocation.NewRPCInvocation("test", parmas, map[string]string{ + constant.REQUEST_SIGNATURE_KEY: signature, + constant.CONSUMER: "test", + constant.REQUEST_TIMESTAMP_KEY: requestTime, + constant.AK_KEY: access, + }) + err := authenticator.Authenticate(invcation, &testurl) + assert.Nil(t, err) + // modify the params + invcation = invocation.NewRPCInvocation("test", parmas[:1], map[string]string{ + constant.REQUEST_SIGNATURE_KEY: signature, + constant.CONSUMER: "test", + constant.REQUEST_TIMESTAMP_KEY: requestTime, + constant.AK_KEY: access, + }) + err = authenticator.Authenticate(invcation, &testurl) + assert.NotNil(t, err) + +} + +func TestDefaultAuthenticator_Sign(t *testing.T) { + authenticator := &DefaultAuthenticator{} + testurl, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?application=test&interface=com.ikurento.user.UserProvider&group=gg&version=2.6.0") + testurl.SetParam(constant.ACCESS_KEY_ID_KEY, "akey") + testurl.SetParam(constant.SECRET_ACCESS_KEY_KEY, "skey") + testurl.SetParam(constant.PARAMTER_SIGNATURE_ENABLE_KEY, "false") + inv := invocation.NewRPCInvocation("test", []interface{}{"OK"}, nil) + _ = authenticator.Sign(inv, &testurl) + assert.NotEqual(t, inv.AttachmentsByKey(constant.REQUEST_SIGNATURE_KEY, ""), "") + assert.NotEqual(t, inv.AttachmentsByKey(constant.CONSUMER, ""), "") + assert.NotEqual(t, inv.AttachmentsByKey(constant.REQUEST_TIMESTAMP_KEY, ""), "") + assert.Equal(t, inv.AttachmentsByKey(constant.AK_KEY, ""), "akey") + +} + +func Test_getAccessKeyPairSuccess(t *testing.T) { + testurl := common.NewURLWithOptions( + common.WithParams(url.Values{}), + common.WithParamsValue(constant.SECRET_ACCESS_KEY_KEY, "skey"), + common.WithParamsValue(constant.ACCESS_KEY_ID_KEY, "akey")) + invcation := invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, nil) + _, e := getAccessKeyPair(invcation, testurl) + assert.Nil(t, e) +} + +func Test_getAccessKeyPairFailed(t *testing.T) { + defer func() { + e := recover() + assert.NotNil(t, e) + }() + testurl := common.NewURLWithOptions( + common.WithParams(url.Values{}), + common.WithParamsValue(constant.ACCESS_KEY_ID_KEY, "akey")) + invcation := invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, nil) + _, e := getAccessKeyPair(invcation, testurl) + assert.NotNil(t, e) + testurl = common.NewURLWithOptions( + common.WithParams(url.Values{}), + common.WithParamsValue(constant.SECRET_ACCESS_KEY_KEY, "skey"), + common.WithParamsValue(constant.ACCESS_KEY_ID_KEY, "akey"), common.WithParamsValue(constant.ACCESS_KEY_STORAGE_KEY, "dubbo")) + _, e = getAccessKeyPair(invcation, testurl) + +} + +func Test_getSignatureWithinParams(t *testing.T) { + testurl, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=gg&version=2.6.0") + testurl.SetParam(constant.PARAMTER_SIGNATURE_ENABLE_KEY, "true") + inv := invocation.NewRPCInvocation("test", []interface{}{"OK"}, map[string]string{ + "": "", + }) + secret := "dubbo" + current := strconv.Itoa(int(time.Now().Unix() * 1000)) + signature, _ := getSignature(&testurl, inv, secret, current) + requestString := fmt.Sprintf(constant.SIGNATURE_STRING_FORMAT, + testurl.ColonSeparatedKey(), inv.MethodName(), secret, current) + s, _ := SignWithParams(inv.Arguments(), requestString, secret) + assert.False(t, IsEmpty(signature, false)) + assert.Equal(t, s, signature) +} + +func Test_getSignature(t *testing.T) { + testurl, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=gg&version=2.6.0") + testurl.SetParam(constant.PARAMTER_SIGNATURE_ENABLE_KEY, "false") + inv := invocation.NewRPCInvocation("test", []interface{}{"OK"}, nil) + secret := "dubbo" + current := strconv.Itoa(int(time.Now().Unix() * 1000)) + signature, _ := getSignature(&testurl, inv, secret, current) + requestString := fmt.Sprintf(constant.SIGNATURE_STRING_FORMAT, + testurl.ColonSeparatedKey(), inv.MethodName(), secret, current) + s := Sign(requestString, secret) + assert.False(t, IsEmpty(signature, false)) + assert.Equal(t, s, signature) +} diff --git a/filter/filter_impl/auth/consumer_sign_test.go b/filter/filter_impl/auth/consumer_sign_test.go new file mode 100644 index 000000000..64a104540 --- /dev/null +++ b/filter/filter_impl/auth/consumer_sign_test.go @@ -0,0 +1,34 @@ +package auth + +import ( + "context" + "testing" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/protocol/mock" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func TestConsumerSignFilter_Invoke(t *testing.T) { + url, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=gg&version=2.6.0") + url.SetParam(constant.SECRET_ACCESS_KEY_KEY, "sk") + url.SetParam(constant.ACCESS_KEY_ID_KEY, "ak") + inv := invocation.NewRPCInvocation("test", []interface{}{"OK"}, nil) + filter := &ConsumerSignFilter{} + ctrl := gomock.NewController(t) + defer ctrl.Finish() + invoker := mock.NewMockInvoker(ctrl) + result := &protocol.RPCResult{} + invoker.EXPECT().Invoke(inv).Return(result).Times(2) + invoker.EXPECT().GetUrl().Return(url).Times(2) + assert.Equal(t, result, filter.Invoke(invoker, inv)) + + url.SetParam(constant.SERVICE_AUTH_KEY, "true") + assert.Equal(t, result, filter.Invoke(invoker, inv)) +} diff --git a/filter/filter_impl/auth/provider_auth_test.go b/filter/filter_impl/auth/provider_auth_test.go new file mode 100644 index 000000000..b75b6b744 --- /dev/null +++ b/filter/filter_impl/auth/provider_auth_test.go @@ -0,0 +1,53 @@ +package auth + +import ( + "context" + "strconv" + "testing" + "time" +) +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/protocol/mock" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func TestProviderAuthFilter_Invoke(t *testing.T) { + secret := "dubbo-sk" + access := "dubbo-ak" + url, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?interface=com.ikurento.user.UserProvider&group=gg&version=2.6.0") + url.SetParam(constant.ACCESS_KEY_ID_KEY, access) + url.SetParam(constant.SECRET_ACCESS_KEY_KEY, secret) + parmas := []interface{}{ + "OK", + struct { + Name string + Id int64 + }{"YUYU", 1}, + } + inv := invocation.NewRPCInvocation("test", parmas, nil) + requestTime := strconv.Itoa(int(time.Now().Unix() * 1000)) + signature, _ := getSignature(&url, inv, secret, requestTime) + + inv = invocation.NewRPCInvocation("test", []interface{}{"OK"}, map[string]string{ + constant.REQUEST_SIGNATURE_KEY: signature, + constant.CONSUMER: "test", + constant.REQUEST_TIMESTAMP_KEY: requestTime, + constant.AK_KEY: access, + }) + ctrl := gomock.NewController(t) + filter := &ProviderAuthFilter{} + defer ctrl.Finish() + invoker := mock.NewMockInvoker(ctrl) + result := &protocol.RPCResult{} + invoker.EXPECT().Invoke(inv).Return(result).Times(2) + invoker.EXPECT().GetUrl().Return(url).Times(2) + assert.Equal(t, result, filter.Invoke(invoker, inv)) + url.SetParam(constant.SERVICE_AUTH_KEY, "true") + assert.Equal(t, result, filter.Invoke(invoker, inv)) + +} diff --git a/filter/filter_impl/auth/sign_util.go b/filter/filter_impl/auth/sign_util.go index 086c5293f..5312ec2c0 100644 --- a/filter/filter_impl/auth/sign_util.go +++ b/filter/filter_impl/auth/sign_util.go @@ -1,10 +1,10 @@ package auth import ( - "bytes" + "crypto/hmac" "crypto/sha256" "encoding/base64" - "encoding/gob" + "encoding/json" "errors" "strings" ) @@ -28,17 +28,18 @@ func SignWithParams(params []interface{}, metadata, key string) (string, error) } func toBytes(data []interface{}) ([]byte, error) { - var b bytes.Buffer - enc := gob.NewEncoder(&b) - if err := enc.Encode(data); err != nil { + if bytes, err := json.Marshal(data); err != nil { return nil, errors.New("") + } else { + return bytes, nil } - return b.Bytes(), nil } func doSign(bytes []byte, key string) string { - sum256 := sha256.Sum256(bytes) - return base64.URLEncoding.EncodeToString(sum256[:]) + mac := hmac.New(sha256.New, []byte(key)) + mac.Write(bytes) + signature := mac.Sum(nil) + return base64.URLEncoding.EncodeToString(signature) } func IsEmpty(s string, allowSpace bool) bool { diff --git a/filter/filter_impl/auth/sign_util_test.go b/filter/filter_impl/auth/sign_util_test.go index d32121341..01185f534 100644 --- a/filter/filter_impl/auth/sign_util_test.go +++ b/filter/filter_impl/auth/sign_util_test.go @@ -1,7 +1,6 @@ package auth import ( - "reflect" "testing" ) import ( @@ -35,7 +34,6 @@ func TestIsEmpty(t *testing.T) { } func TestSign(t *testing.T) { - metadata := "com.ikurento.user.UserProvider::sayHi" key := "key" signature := Sign(metadata, key) @@ -44,52 +42,42 @@ func TestSign(t *testing.T) { } func TestSignWithParams(t *testing.T) { - + metadata := "com.ikurento.user.UserProvider::sayHi" + key := "key" + params := []interface{}{ + "a", 1, struct { + Name string + Id int64 + }{"YuYu", 1}, + } + signature, _ := SignWithParams(params, metadata, key) + assert.False(t, IsEmpty(signature, false)) } func Test_doSign(t *testing.T) { - type args struct { - bytes []byte - key string - } - tests := []struct { - name string - args args - want string - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := doSign(tt.args.bytes, tt.args.key); got != tt.want { - t.Errorf("doSign() = %v, want %v", got, tt.want) - } - }) - } + sign := doSign([]byte("DubboGo"), "key") + sign1 := doSign([]byte("DubboGo"), "key") + sign2 := doSign([]byte("DubboGo"), "key2") + assert.NotNil(t, sign) + assert.Equal(t, sign1, sign) + assert.NotEqual(t, sign1, sign2) } func Test_toBytes(t *testing.T) { - type args struct { - data []interface{} - } - tests := []struct { - name string - args args - want []byte - wantErr bool - }{ - // TODO: Add test cases. + params := []interface{}{ + "a", 1, struct { + Name string + Id int64 + }{"YuYu", 1}, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := toBytes(tt.args.data) - if (err != nil) != tt.wantErr { - t.Errorf("toBytes() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("toBytes() got = %v, want %v", got, tt.want) - } - }) + params2 := []interface{}{ + "a", 1, struct { + Name string + Id int64 + }{"YuYu", 1}, } + jsonBytes, _ := toBytes(params) + jsonBytes2, _ := toBytes(params2) + assert.NotNil(t, jsonBytes) + assert.Equal(t, jsonBytes, jsonBytes2) } -- GitLab