milvus-io / milvus

A cloud-native vector database, storage for next generation AI applications
https://milvus.io
Apache License 2.0
29.54k stars 2.83k forks source link

[Bug]: the error msg is misleading if a user has no permission to list roles or users #33831

Open yanliang567 opened 3 months ago

yanliang567 commented 3 months ago

Is there an existing issue for this?

Environment

- Milvus version: 2.4.4
- Deployment mode(standalone or cluster): standalone
- MQ type(rocksmq, pulsar or kafka):    
- SDK version(e.g. pymilvus v2.0.0rc2): pymilvus 2.4.3

Current Behavior

the error msg indicates that user_a has no permission to default database, actually it just has no permission to the list role privilege, and no matter with database at all. status = StatusCode.PERMISSION_DENIED details = "PrivilegeSelectOwnership: permission deny to user_a in the default database" debug_error_string = "UNKNOWN:Error received from peer ipv4:10.104.17.207:19530 {grpc_message:"PrivilegeSelectOwnership: permission deny to user_a in the default database", grpc_status:7, created_time:"2024-06-13T16:15:09.282649+08:00"}"

Expected Behavior

specify that which privilege should be granted

Steps To Reproduce

1. create role_a & role_b, user_a & user_b, and add users to roles
2. connect to milvus with role_a
3.list roles and list users

Milvus Log

No response

Anything else?

repro code:

def create_collection(name):
    print(f"create collection: {name}")
    id_field = FieldSchema(name="id", dtype=DataType.INT64, description="primary id")
    embedding_field = FieldSchema(name=f"embedding", dtype=DataType.FLOAT_VECTOR, dim=16)
    fields = [id_field, embedding_field]
    schema = CollectionSchema(fields=fields, primary_field=id_field.name, description=f"{name}")
    Collection(name=name, schema=schema)

# connect
connections.connect(host=_HOST, port=_PORT, user=_ROOT, password=_ROOT_PASSWORD)
print(f"databases: {db.list_database()}")
print(f"collections: {utility.list_collections()}")

# create databases
db_a = "database_a"
db_b = "database_b"
# db.create_database(db_name=db_a)
# db.create_database(db_name=db_b)
print(f"databases: {db.list_database()}")

# create collection_a in db_a
collection_a = "collection_a"
db.using_database(db_name=db_a)
print(f"collections in db_a: {utility.list_collections()}")
create_collection(name=collection_a)
print(f"collections in db_a: {utility.list_collections()}")

# check collections in db_b and default
db.using_database(db_name=db_b)
# connections.disconnect(alias='default')
# connections.connect(host=_HOST, port=_PORT, db_name=db_b)
print(f"collections in db_b: {utility.list_collections()}")
collection_b = "collection_b"
create_collection(name=collection_b)
db.using_database(db_name='default')
print(f"collections in default db: {utility.list_collections()}")

user_a = "user_a"
pw_user_a = "123456"
user_b = "user_b"
pw_user_b = "654321"
role_db_a = "role_for_db_a"
role_db_b = "role_for_db_b"

# create users
# utility.create_user(user=user_a, password=pw_user_a)
# utility.create_user(user=user_b, password=pw_user_b)

# create roles
role_a = Role(role_db_a)
# role_a.create()
role_b = Role(role_db_b)
# role_b.create()

# grant full privileges with all collections of db_a to user_a
db.using_database(db_name=db_a)
role_a.grant("Collection", "*", "*")
role_a.add_user(user_a)
print(f"roles in db_a: {utility.list_roles(True)}")

# grant full privileges with all collections of db_b to user_b
db.using_database(db_name=db_b)
role_b.grant("Collection", "*", "*")
role_b.add_user(user_b)
print(f"roles in db_b: {utility.list_roles(True)}")

# disconnect fisrt and then connect with user_a
connections.connect(host=_HOST, port=_PORT, user=user_a, password=pw_user_a)
print(f"databases: {db.list_database()}")
print(f"collections: {utility.list_collections()}")
# db.using_database(db_name=db_a)
print(f"roles: {utility.list_roles(True)}")
print(f"users: {utility.list_users(True)}")
yanliang567 commented 3 months ago

/assign @czs007 /unassign