milvus/internal/proxy/authentication_interceptor_test.go
congqixia a592cfc8b4
enhance: [2.6] extract shard client logic into dedicated package (#45018) (#45031)
Cherry-pick from master
pr: #45018 #45030
Related to #44761

Refactor proxy shard client management by creating a new
internal/proxy/shardclient package. This improves code organization and
modularity by:

- Moving load balancing logic (LookAsideBalancer, RoundRobinBalancer) to
shardclient package
- Extracting shard client manager and related interfaces into separate
package
- Relocating shard leader management and client lifecycle code
- Adding package documentation (README.md, OWNERS)
- Updating proxy code to use the new shardclient package interfaces

This change makes the shard client functionality more maintainable and
better encapsulated, reducing coupling in the proxy layer.

Also consolidates the proxy package's mockery generation to use a
centralized `.mockery.yaml` configuration file, aligning with the
pattern used by other packages like querycoordv2.

Changes
- **Makefile**: Replace multiple individual mockery commands with a
single config-based invocation for `generate-mockery-proxy` target
- **internal/proxy/.mockery.yaml**: Add mockery configuration defining
all mock interfaces for proxy and proxy/shardclient packages
- **Mock files**: Regenerate mocks using the new configuration:
  - `mock_cache.go`: Clean up by removing unused interface methods
  (credential, shard cache, policy methods)
  - `shardclient/mock_lb_balancer.go`: Update type comments
  (nodeInfo → NodeInfo)
  - `shardclient/mock_lb_policy.go`: Update formatting
  - `shardclient/mock_shardclient_manager.go`: Fix parameter naming
  consistency (nodeInfo1 → nodeInfo)
- **task_search_test.go**: Remove obsolete mock expectations for
deprecated cache methods

Benefits
- Centralized mockery configuration for easier maintenance
- Consistent with other packages (querycoordv2, etc.)
- Cleaner mock interfaces by removing unused methods
- Better type consistency in generated mocks

---------

Signed-off-by: Congqi Xia <congqi.xia@zilliz.com>
2025-10-22 16:06:06 +08:00

142 lines
4.2 KiB
Go

package proxy
import (
"context"
"strings"
"testing"
"github.com/cockroachdb/errors"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/metadata"
"github.com/milvus-io/milvus/internal/proxy/privilege"
"github.com/milvus-io/milvus/internal/util/hookutil"
"github.com/milvus-io/milvus/pkg/v2/util"
"github.com/milvus-io/milvus/pkg/v2/util/crypto"
"github.com/milvus-io/milvus/pkg/v2/util/paramtable"
)
// validAuth validates the authentication
func TestValidAuth(t *testing.T) {
validAuth := func(ctx context.Context, authorization []string) bool {
if len(authorization) < 1 {
return false
}
token := authorization[0]
rawToken, _ := crypto.Base64Decode(token)
username, password := parseMD(rawToken)
if username == "" || password == "" {
return false
}
return passwordVerify(ctx, username, password, privilege.GetPrivilegeCache())
}
ctx := context.Background()
// no metadata
res := validAuth(ctx, nil)
assert.False(t, res)
// illegal metadata
res = validAuth(ctx, []string{"xxx"})
assert.False(t, res)
// normal metadata
mix := &MockMixCoordClientInterface{}
err := InitMetaCache(ctx, mix)
assert.NoError(t, err)
res = validAuth(ctx, []string{crypto.Base64Encode("mockUser:mockPass")})
assert.True(t, res)
res = validAuth(ctx, []string{crypto.Base64Encode("mock")})
assert.False(t, res)
}
func TestValidSourceID(t *testing.T) {
ctx := context.Background()
// no metadata
res := validSourceID(ctx, nil)
assert.False(t, res)
// illegal metadata
res = validSourceID(ctx, []string{"invalid_sourceid"})
assert.False(t, res)
// normal sourceId
res = validSourceID(ctx, []string{crypto.Base64Encode(util.MemberCredID)})
assert.True(t, res)
}
func TestAuthenticationInterceptor(t *testing.T) {
ctx := context.Background()
paramtable.Get().Save(Params.CommonCfg.AuthorizationEnabled.Key, "true") // mock authorization is turned on
defer paramtable.Get().Reset(Params.CommonCfg.AuthorizationEnabled.Key) // mock authorization is turned on
// no metadata
_, err := AuthenticationInterceptor(ctx)
assert.Error(t, err)
// mock metacache
queryCoord := &MockMixCoordClientInterface{}
err = InitMetaCache(ctx, queryCoord)
assert.NoError(t, err)
// with invalid metadata
md := metadata.Pairs("xxx", "yyy")
ctx = metadata.NewIncomingContext(ctx, md)
_, err = AuthenticationInterceptor(ctx)
assert.Error(t, err)
// with valid username/password
md = metadata.Pairs(util.HeaderAuthorize, crypto.Base64Encode("mockUser:mockPass"))
ctx = metadata.NewIncomingContext(ctx, md)
_, err = AuthenticationInterceptor(ctx)
assert.NoError(t, err)
// with valid sourceId
md = metadata.Pairs("sourceid", crypto.Base64Encode(util.MemberCredID))
ctx = metadata.NewIncomingContext(ctx, md)
_, err = AuthenticationInterceptor(ctx)
assert.NoError(t, err)
{
// wrong authorization style
md = metadata.Pairs(util.HeaderAuthorize, "123456")
ctx = metadata.NewIncomingContext(ctx, md)
_, err = AuthenticationInterceptor(ctx)
assert.Error(t, err)
}
{
// invalid user
md = metadata.Pairs(util.HeaderAuthorize, crypto.Base64Encode("mockUser2:mockPass"))
ctx = metadata.NewIncomingContext(ctx, md)
_, err = AuthenticationInterceptor(ctx)
assert.Error(t, err)
}
{
// default hook
md = metadata.Pairs(util.HeaderAuthorize, crypto.Base64Encode("mockapikey"))
ctx = metadata.NewIncomingContext(ctx, md)
_, err = AuthenticationInterceptor(ctx)
assert.Error(t, err)
}
{
// verify apikey error
hookutil.SetMockAPIHook("", errors.New("err"))
md = metadata.Pairs(util.HeaderAuthorize, crypto.Base64Encode("mockapikey"))
ctx = metadata.NewIncomingContext(ctx, md)
_, err = AuthenticationInterceptor(ctx)
assert.Error(t, err)
}
{
hookutil.SetMockAPIHook("mockUser", nil)
md = metadata.Pairs(util.HeaderAuthorize, crypto.Base64Encode("mockapikey"))
ctx = metadata.NewIncomingContext(ctx, md)
authCtx, err := AuthenticationInterceptor(ctx)
assert.NoError(t, err)
md, ok := metadata.FromIncomingContext(authCtx)
assert.True(t, ok)
authStrArr := md[strings.ToLower(util.HeaderAuthorize)]
token := authStrArr[0]
rawToken, err := crypto.Base64Decode(token)
assert.NoError(t, err)
user, _ := parseMD(rawToken)
assert.Equal(t, "mockUser", user)
}
hookutil.SetTestHook(hookutil.DefaultHook{})
}