enhance: [2.4] make the auth error message more suitable (#32298)

issue: #32252
pr: #32253
/kind improvement

Signed-off-by: SimFG <bang.fu@zilliz.com>
pull/32275/head
SimFG 2024-04-16 17:13:19 +08:00 committed by GitHub
parent d565d64941
commit 52cc1ed9d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 88 additions and 3 deletions

View File

@ -81,7 +81,7 @@ func AuthenticationInterceptor(ctx context.Context) (context.Context, error) {
return nil, status.Error(codes.Unauthenticated, "auth check failure, please check api key is correct")
}
metrics.UserRPCCounter.WithLabelValues(user).Inc()
userToken := fmt.Sprintf("%s%s%s", user, util.CredentialSeperator, "___")
userToken := fmt.Sprintf("%s%s%s", user, util.CredentialSeperator, util.PasswordHolder)
md[strings.ToLower(util.HeaderAuthorize)] = []string{crypto.Base64Encode(userToken)}
ctx = metadata.NewIncomingContext(ctx, md)
} else {

View File

@ -18,6 +18,7 @@ import (
"github.com/milvus-io/milvus-proto/go-api/v2/milvuspb"
"github.com/milvus-io/milvus/pkg/log"
"github.com/milvus-io/milvus/pkg/util"
"github.com/milvus-io/milvus/pkg/util/contextutil"
"github.com/milvus-io/milvus/pkg/util/funcutil"
)
@ -94,7 +95,7 @@ func PrivilegeInterceptor(ctx context.Context, req interface{}) (context.Context
log.RatedInfo(60, "GetPrivilegeExtObj err", zap.Error(err))
return ctx, nil
}
username, err := GetCurUserFromContext(ctx)
username, password, err := contextutil.GetAuthInfoFromContext(ctx)
if err != nil {
log.Warn("GetCurUserFromContext fail", zap.Error(err))
return ctx, err
@ -174,7 +175,12 @@ func PrivilegeInterceptor(ctx context.Context, req interface{}) (context.Context
}
log.Info("permission deny", zap.Strings("roles", roleNames))
return ctx, status.Error(codes.PermissionDenied, fmt.Sprintf("%s: permission deny to %s", objectPrivilege, username))
if password == util.PasswordHolder {
username = "apikey user"
}
return ctx, status.Error(codes.PermissionDenied,
fmt.Sprintf("%s: permission deny to %s in the `%s` database", objectPrivilege, username, dbName))
}
// isCurUserObject Determine whether it is an Object of type User that operates on its own user information,

View File

@ -2,6 +2,7 @@ package proxy
import (
"context"
"strings"
"sync"
"testing"
@ -11,6 +12,7 @@ import (
"github.com/milvus-io/milvus-proto/go-api/v2/milvuspb"
"github.com/milvus-io/milvus/internal/mocks"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/pkg/util"
"github.com/milvus-io/milvus/pkg/util/funcutil"
"github.com/milvus-io/milvus/pkg/util/merr"
"github.com/milvus-io/milvus/pkg/util/paramtable"
@ -106,6 +108,14 @@ func TestPrivilegeInterceptor(t *testing.T) {
CollectionName: "col1",
})
assert.Error(t, err)
{
_, err = PrivilegeInterceptor(GetContext(context.Background(), "foo:"+util.PasswordHolder), &milvuspb.LoadCollectionRequest{
DbName: "db_test",
CollectionName: "col1",
})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "apikey user"))
}
_, err = PrivilegeInterceptor(ctx, &milvuspb.InsertRequest{
DbName: "db_test",
CollectionName: "col1",

View File

@ -49,6 +49,7 @@ const (
CredentialSeperator = ":"
UserRoot = "root"
DefaultRootPassword = "Milvus"
PasswordHolder = "___"
DefaultTenant = ""
RoleAdmin = "admin"
RolePublic = "public"

View File

@ -19,8 +19,12 @@ package contextutil
import (
"context"
"fmt"
"strings"
"google.golang.org/grpc/metadata"
"github.com/milvus-io/milvus/pkg/util"
"github.com/milvus-io/milvus/pkg/util/crypto"
)
type ctxTenantKey struct{}
@ -58,3 +62,31 @@ func AppendToIncomingContext(ctx context.Context, kv ...string) context.Context
}
return metadata.NewIncomingContext(ctx, md)
}
func GetCurUserFromContext(ctx context.Context) (string, error) {
username, _, err := GetAuthInfoFromContext(ctx)
return username, err
}
func GetAuthInfoFromContext(ctx context.Context) (string, string, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return "", "", fmt.Errorf("fail to get md from the context")
}
authorization, ok := md[strings.ToLower(util.HeaderAuthorize)]
if !ok || len(authorization) < 1 {
return "", "", fmt.Errorf("fail to get authorization from the md, %s:[token]", strings.ToLower(util.HeaderAuthorize))
}
token := authorization[0]
rawToken, err := crypto.Base64Decode(token)
if err != nil {
return "", "", fmt.Errorf("fail to decode the token, token: %s", token)
}
secrets := strings.SplitN(rawToken, util.CredentialSeperator, 2)
if len(secrets) < 2 {
return "", "", fmt.Errorf("fail to get user info from the raw token, raw token: %s", rawToken)
}
// username: secrets[0]
// password: secrets[1]
return secrets[0], secrets[1], nil
}

View File

@ -20,10 +20,15 @@ package contextutil
import (
"context"
"fmt"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/metadata"
"github.com/milvus-io/milvus/pkg/util"
"github.com/milvus-io/milvus/pkg/util/crypto"
)
func TestAppendToIncomingContext(t *testing.T) {
@ -42,3 +47,34 @@ func TestAppendToIncomingContext(t *testing.T) {
assert.Equal(t, "bar", md.Get("foo")[0])
})
}
func TestGetCurUserFromContext(t *testing.T) {
_, err := GetCurUserFromContext(context.Background())
assert.Error(t, err)
_, err = GetCurUserFromContext(metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{})))
assert.Error(t, err)
_, err = GetCurUserFromContext(GetContext(context.Background(), "123456"))
assert.Error(t, err)
root := "root"
password := "123456"
username, err := GetCurUserFromContext(GetContext(context.Background(), fmt.Sprintf("%s%s%s", root, util.CredentialSeperator, password)))
assert.NoError(t, err)
assert.Equal(t, root, username)
{
u, p, e := GetAuthInfoFromContext(GetContext(context.Background(), fmt.Sprintf("%s%s%s", root, util.CredentialSeperator, password)))
assert.NoError(t, e)
assert.Equal(t, "root", u)
assert.Equal(t, password, p)
}
}
func GetContext(ctx context.Context, originValue string) context.Context {
authKey := strings.ToLower(util.HeaderAuthorize)
authValue := crypto.Base64Encode(originValue)
contextMap := map[string]string{
authKey: authValue,
}
md := metadata.New(contextMap)
return metadata.NewIncomingContext(ctx, md)
}