Manage Cluster Roles (SDK)
A cluster role defines the privileges that a user has within the cluster. More specifically, the cluster role controls a cluster user's privileges on the cluster, database, and collection level.
This guide walks you through how to create a role, grant built-in privilege groups to a role, revoke privilege groups from a role, and finally drop a role. For details about built-in privilege groups, refer to Privileges.
This feature is exclusively available to Dedicated clusters.
Create a role
The following example demonstrates how to create a role named role_a.
The role name must start with a letter and can only include uppercase or lowercase letters, numbers, and underscores.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
from pymilvus import MilvusClient
client.create_role(role_name="role_a", description="a cluster read only role")
import io.milvus.v2.service.rbac.request.CreateRoleReq;
CreateRoleReq createRoleReq = CreateRoleReq.builder()
.roleName("role_a")
.description("a cluster read only role")
.build();
client.createRole(createRoleReq);
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
err = client.CreateRole(ctx, milvusclient.NewCreateRoleOption("role_a").WithDescription("a cluster read only role"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
client
.create_role(
CreateRoleRequest::builder()
.role_name("role_a")
.description("a cluster read only role")
.build()?,
)
.await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto status = client->CreateRole(milvus::CreateRoleRequest()
.WithRoleName("role_a")
.WithDescription("a cluster read only role"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({
address: 'YOUR_CLUSTER_ENDPOINT',
token: 'YOUR_CLUSTER_TOKEN',
});
await client.createRole({
roleName: 'role_a',
description: 'a cluster read only role',
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/roles/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"roleName": "role_a",
"description": "a cluster read only role"
}'
List roles
After creating several roles, you can list and view all existing roles.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
from pymilvus import MilvusClient
client.list_roles()
import java.util.List;
List<String> roles = client.listRoles();
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
roles, err := client.ListRoles(ctx, milvusclient.NewListRoleOption())
if err != nil {
fmt.Println(err.Error())
// handle error
}
fmt.Println(roles)
use milvus::v2::prelude::*;
let roles = client
.list_roles(ListRolesRequest::builder().build()?)
.await?;
println!("{:?}", roles.role_names());
#include <iostream>
#include "milvus/MilvusClientV2.h"
milvus::ListRolesResponse resp;
auto status = client->ListRoles(milvus::ListRolesRequest(), resp);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({
address: 'YOUR_CLUSTER_ENDPOINT',
token: 'YOUR_CLUSTER_TOKEN',
});
const roles = await client.listRoles();
console.log(roles);
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/roles/list" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{}'
Below is an example output. role_a is the new role that is just created.
['role_a']
Grant a privilege group to a role
In Zilliz Cloud, you can grant the followings to a role:
-
Built-in privilege groups: Zilliz Cloud offers 9 built-in privilege groups. For details about the specific privileges included in each built-in privilege group, refer to Built-in privilege groups.
-
Custom privilege groups: If the built-in privileges do not meet your needs, you can combine different privileges to create your own custom privilege groups. For details, refer to Custom privilege groups.
-
If you need to grant custom privilege groups to a role, please create a support ticket so that we can enable this feature for you.
-
For clusters running Milvus 2.5.x or later, individual privileges are no longer supported.
The following example demonstrates how to grant a custom privilege group named privilege_group_1 and a built-in privilege group ClusterReadOnly to the role role_a.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
from pymilvus import MilvusClient
client.grant_privilege_v2(
role_name="role_a",
privilege="privilege_group_1",
collection_name='collection_01',
db_name='default',
)
client.grant_privilege_v2(
role_name="role_a",
privilege="ClusterReadOnly",
collection_name='*',
db_name='*',
)
import io.milvus.v2.service.rbac.request.GrantPrivilegeReqV2;
client.grantPrivilegeV2(GrantPrivilegeReqV2.builder()
.roleName("role_a")
.privilege("privilege_group_1")
.collectionName("collection_01")
.dbName("default")
.build());
client.grantPrivilegeV2(GrantPrivilegeReqV2.builder()
.roleName("role_a")
.privilege("ClusterReadOnly")
.collectionName("*")
.dbName("*")
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
err = client.GrantV2(ctx, milvusclient.NewGrantV2Option("role_a", "privilege_group_1", "default", "collection_01"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
err = client.GrantV2(ctx, milvusclient.NewGrantV2Option("role_a", "ClusterReadOnly", "*", "*"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
client
.grant_privilege(
GrantPrivilegeRequest::builder()
.role_name("role_a")
.privilege("privilege_group_1")
.database_name("default")
.collection_name("collection_01")
.build()?,
)
.await?;
client
.grant_privilege(
GrantPrivilegeRequest::builder()
.role_name("role_a")
.privilege("ClusterReadOnly")
.database_name("*")
.collection_name("*")
.build()?,
)
.await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
milvus::GrantPrivilegeV2Request grant_req;
grant_req.WithRoleName("role_a")
.WithPrivilege("privilege_group_1")
.WithDatabaseName("default")
.WithCollectionName("collection_01");
auto status = client->GrantPrivilegeV2(grant_req);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({
address: 'YOUR_CLUSTER_ENDPOINT',
token: 'YOUR_CLUSTER_TOKEN',
});
await client.grantPrivilegeV2({
role: 'role_a',
privilege: 'privilege_group_1',
collection_name: 'collection_01',
db_name: 'default',
});
await client.grantPrivilegeV2({
role: 'role_a',
privilege: 'ClusterReadOnly',
collection_name: '*',
db_name: '*',
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/roles/grant_privilege_v2" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"roleName": "role_a",
"privilege": "privilege_group_1",
"collectionName": "collection_01",
"dbName":"default"
}'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/roles/grant_privilege_v2" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"roleName": "role_a",
"privilege": "ClusterReadOnly",
"collectionName": "*",
"dbName":"*"
}'
The following are the parameters and corresponding explanations.
-
role_name: The name of the target role to which privilege group(s) need to be granted.
-
privilege: The privilege group to grant to the role. For the available options, see Privileges & Privilege Groups
-
Resource: The target resource of a privilege group, which can be a specific cluster, database, or collection.
The following table explains how to specify the resource.
Level
Resource
Grant Method
Notes
Collection
A specific collection
client.grant_privilege_v2( role_name="roleA", privilege="CollectionAdmin", collection_name="col1", db_name="db1" )Input the name of your target collection and the name of the database to which the target collection belongs.
All collections under a specific database
client.grant_privilege_v2( role_name="roleA", privilege="CollectionAdmin", collection_name="*", db_name="db1" )Input the name of your target database and a wildcard
*as the collection name.Database
A specific database
client.grant_privilege_v2( role_name="roleA", privilege="DatabaseAdmin", collection_name="*", db_name="db1" )Input the name of your target database and a wildcard
*as the collection name.All databases under the current instance
client.grant_privilege_v2( role_name="roleA", privilege="DatabaseAdmin", collection_name="*", db_name="*" )Input
*as the database name and*as the collection name.Instance
The current instance
client.grant_privilege_v2( role_name="roleA", privilege="ClusterAdmin", collection_name="*", db_name="*" )Input
*as the database name and*as the collection name.
Describe a role
The following example demonstrates how to view the privileges granted to the role role_a using the describe_role method.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
from pymilvus import MilvusClient
client.describe_role(role_name="role_a")
import io.milvus.v2.service.rbac.request.DescribeRoleReq;
import io.milvus.v2.service.rbac.response.DescribeRoleResp;
import java.util.List;
DescribeRoleReq describeRoleReq = DescribeRoleReq.builder()
.roleName("role_a")
.build();
DescribeRoleResp resp = client.describeRole(describeRoleReq);
List<DescribeRoleResp.GrantInfo> infos = resp.getGrantInfos();
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
role, err := client.DescribeRole(ctx, milvusclient.NewDescribeRoleOption("role_a"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
fmt.Println(role)
use milvus::v2::prelude::*;
let role = client
.describe_role(
DescribeRoleRequest::builder()
.role_name("role_a")
.build()?,
)
.await?;
println!("{:?}", role.description().get_role_name());
#include <iostream>
#include "milvus/MilvusClientV2.h"
milvus::DescribeRoleResponse resp;
auto status = client->DescribeRole(milvus::DescribeRoleRequest().WithRoleName("role_a"), resp);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({
address: 'YOUR_CLUSTER_ENDPOINT',
token: 'YOUR_CLUSTER_TOKEN',
});
const role = await client.describeRole({ roleName: 'role_a' });
console.log(role);
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/roles/describe" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"roleName": "role_a"
}'
Below is an example output.
{
"role": "role_a",
"descripton": "a cluster read only role",
"privilege": "ClusterReadOnly"
}
Revoke a privilege group from a role
The following example demonstrates how to revoke the customprivilege group privilege_group_1 and the built-in privilege group ClusterReadOnly that have been granted to the role role_a.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
client.revoke_privilege_v2(
role_name="role_a",
privilege="privilege_group_1",
collection_name='collection_01',
db_name='default',
)
client.revoke_privilege_v2(
role_name="role_a",
privilege="ClusterReadOnly",
collection_name='*',
db_name='*',
)
import io.milvus.v2.service.rbac.request.RevokePrivilegeReqV2;
client.revokePrivilegeV2(RevokePrivilegeReqV2.builder()
.roleName("role_a")
.privilege("privilege_group_1")
.collectionName("collection_01")
.dbName("default")
.build());
client.revokePrivilegeV2(RevokePrivilegeReqV2.builder()
.roleName("role_a")
.privilege("ClusterReadOnly")
.collectionName("*")
.dbName("*")
.build());
import (
"fmt"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
err = client.RevokePrivilegeV2(ctx, milvusclient.NewRevokePrivilegeV2Option("role_a", "privilege_group_1", "collection_01").
WithDbName("default"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
err = client.RevokePrivilegeV2(ctx, milvusclient.NewRevokePrivilegeV2Option("role_a", "ClusterReadOnly", "*").
WithDbName("*"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
client
.revoke_privilege(
RevokePrivilegeRequest::builder()
.role_name("role_a")
.privilege("privilege_group_1")
.database_name("default")
.collection_name("collection_01")
.build()?,
)
.await?;
client
.revoke_privilege(
RevokePrivilegeRequest::builder()
.role_name("role_a")
.privilege("ClusterReadOnly")
.database_name("*")
.collection_name("*")
.build()?,
)
.await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
milvus::RevokePrivilegeV2Request revoke_req;
revoke_req.WithRoleName("role_a")
.WithPrivilege("privilege_group_1")
.WithDatabaseName("default")
.WithCollectionName("collection_01");
auto status = client->RevokePrivilegeV2(revoke_req);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({
address: 'YOUR_CLUSTER_ENDPOINT',
token: 'YOUR_CLUSTER_TOKEN',
});
await client.revokePrivilegeV2({
role: 'role_a',
privilege: 'privilege_group_1',
collection_name: 'collection_01',
db_name: 'default',
});
await client.revokePrivilegeV2({
role: 'role_a',
privilege: 'ClusterReadOnly',
collection_name: '*',
db_name: '*',
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/roles/revoke_privilege_v2" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"roleName": "role_a",
"privilege": "privilege_group_1",
"collectionName": "collection_01",
"dbName":"default"
}'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/roles/revoke_privilege_v2" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"roleName": "role_a",
"privilege": "ClusterReadOnly",
"collectionName": "*",
"dbName":"*"
}'
Drop a role
The following example demonstrates how to drop the role role_a.
The built-in role admin cannot be dropped.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
from pymilvus import MilvusClient
client.drop_role(role_name="role_a")
import io.milvus.v2.service.rbac.request.DropRoleReq;
DropRoleReq dropRoleReq = DropRoleReq.builder()
.roleName("role_a")
.build();
client.dropRole(dropRoleReq);
import (
"fmt"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
err = client.DropRole(ctx, milvusclient.NewDropRoleOption("role_a"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
client
.drop_role(
DropRoleRequest::builder()
.role_name("role_a")
.build()?,
)
.await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto status = client->DropRole(milvus::DropRoleRequest().WithRoleName("role_a"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({
address: 'YOUR_CLUSTER_ENDPOINT',
token: 'YOUR_CLUSTER_TOKEN',
});
await client.dropRole({ roleName: 'role_a' });
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/roles/drop" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"roleName": "role_a"
}'
Once the role is dropped, you can list all existing roles to check if the drop operation is successful.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
from pymilvus import MilvusClient
client.list_roles()
import java.util.List;
List<String> resp = client.listRoles();
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
roles, err := client.ListRoles(ctx, milvusclient.NewListRoleOption())
if err != nil {
fmt.Println(err.Error())
// handle error
}
fmt.Println(roles)
use milvus::v2::prelude::*;
let roles = client
.list_roles(ListRolesRequest::builder().build()?)
.await?;
println!("{:?}", roles.role_names());
#include <iostream>
#include "milvus/MilvusClientV2.h"
milvus::ListRolesResponse resp;
auto status = client->ListRoles(milvus::ListRolesRequest(), resp);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({
address: 'YOUR_CLUSTER_ENDPOINT',
token: 'YOUR_CLUSTER_TOKEN',
});
const roles = await client.listRoles();
console.log(roles);
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/roles/list" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{}'
Below is an example output. There is no role_a in the list. The drop operation is successful.
['admin']