Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This page describes how to move scripts that manage users, groups, service principals, group memberships, entitlements, and workspace assignments from the System for Cross-domain Identity Management (SCIM) APIs to the identity and access management (IAM) v2 APIs. It covers REST calls, the Databricks SDK for Python, the Databricks SDK for Go, the Databricks SDK for Java, and the Databricks CLI.
For Terraform configurations, see Migrate Terraform identity resources to IAM v2.
Requirements
- Databricks SDK for Python 0.159.0 and above.
- Databricks SDK for Go 0.192.0 and above.
- Databricks SDK for Java 0.173.0 and above.
- Databricks CLI 1.24.0 and above.
Key differences
- One API per resource: Each SCIM resource maps to a set of create, get, list, update, and delete methods. Group memberships and workspace entitlements are separate resources, so you don't send SCIM
PATCHoperations. - Workspace-level and account-level methods: Call the workspace-level methods on a workspace URL and the account-level methods on the account console URL. Users, groups, and service principals belong to the account. The workspace-level methods manage the account that contains the workspace you call.
- Workspace access is separate: Creating a user, group, or service principal adds it to the account only. To give it access to a workspace, create a workspace assignment.
- Account groups only: The workspace-level SCIM API creates workspace-local groups. IAM v2 creates and manages account groups, including from the workspace-level methods. The caller also gets the group manager role on each group it creates, on a best-effort basis.
- Resource names: Each object has a
name, such asusers/123at the workspace level oraccounts/<account-id>/users/123at the account level. Get, update, and delete take thename. - Parents: Group member methods take the group's
nameasparent, such asgroups/123. Account-level list and create methods takeaccounts/<account-id>asparent. Workspace-level list and create methods take an optionalparentthat defaults to your account. - Same IDs:
user_id,group_id,service_principal_id, andprincipal_idare the same IDs that SCIM returns inid. - Field names: Fields use
snake_case, for exampleusernameinstead ofuserNameandgroup_nameinstead ofdisplayName. A user's email is itsusername, and a user'sdisplayNameisfull_name.given_namefollowed byfull_name.family_name. - Updates: Update methods take an
update_maskthat lists the fields to change, for examplefull_name.given_name,account_user_status. - Filters and paging: List filters use
snake_casefield names witheq, for exampleusername eq "jane.doe@example.com". Users supportusername eqandexternal_id eq, and groups supportgroup_name eqandexternal_id eq. Results are paged withpage_size(1000 at most) andpage_token, notstartIndexandcount.
Endpoint mapping
The following table maps each current call to the workspace-level IAM v2 call. In the table, /scim/v2 stands for /api/2.0/preview/scim/v2 in a workspace and /api/2.0/accounts/{account-id}/scim/v2 in the account. The last two rows are calls to the account permission assignment API.
To get the account-level IAM v2 call:
- Add
accounts/<account-id>/after/api/2.0/identity/. For example,GET /api/2.0/identity/usersbecomesGET /api/2.0/identity/accounts/<account-id>/users. - For workspace assignments, add
accounts/<account-id>/workspaces/<workspace-id>/after/api/2.0/identity/instead.
For the request and response fields of each call, see the IAM v2 API reference:
- Workspace level: Workspace User API, Workspace Group API, Workspace Service Principal API, Workspace Direct Group Member API, and Workspace Assignment API.
- Account level: Account User API, Account Group API, Account Service Principal API, Account Direct Group Member API, and Account Workspace Assignment API.
| Current call | IAM v2 call |
|---|---|
POST /scim/v2/Users |
POST /api/2.0/identity/users |
GET /scim/v2/Users?filter=userName eq "..." |
GET /api/2.0/identity/users?filter=username eq "..." |
GET /scim/v2/Users/{id} |
GET /api/2.0/identity/users/{id} |
PATCH or PUT /scim/v2/Users/{id} |
PATCH /api/2.0/identity/users/{id}?update_mask=... |
DELETE /scim/v2/Users/{id} |
DELETE /api/2.0/identity/users/{id} |
/scim/v2/Groups... |
/api/2.0/identity/groups... |
/scim/v2/ServicePrincipals... |
/api/2.0/identity/service-principals... |
PATCH /scim/v2/Groups/{id} with add on members |
POST /api/2.0/identity/groups/{id}/direct-members |
PATCH /scim/v2/Groups/{id} with remove on members |
DELETE /api/2.0/identity/groups/{id}/direct-members/{member-id} |
GET /scim/v2/Groups/{id} to read members |
GET /api/2.0/identity/groups/{id}/direct-members |
GET /scim/v2/Users/{id} to read groups |
GET /api/2.0/identity/principals/{id}/transitive-parent-groups, which returns direct and nested parent groups |
PATCH on entitlements for a user, group, or service principal |
PATCH /api/2.0/identity/workspace-assignments/<principal-id> to update, or POST /api/2.0/identity/workspace-assignments to create |
PUT /api/2.0/accounts/{account-id}/workspaces/{workspace-id}/permissionassignments/principals/{id} |
POST /api/2.0/identity/accounts/{account-id}/workspaces/{workspace-id}/workspace-assignments |
DELETE on the same permission assignment |
DELETE /api/2.0/identity/accounts/{account-id}/workspaces/{workspace-id}/workspace-assignments/{id} |
Warning
Deleting a user, group, or service principal deletes it from the account and removes it from every workspace, even when you call the workspace-level method. To remove a principal from one workspace only, delete its workspace assignment.
The following table maps the SDK and Databricks CLI clients. Workspace-level IAM v2 methods end in _proxy or Proxy, such as create_user_proxy in Python and CreateUserProxy in Go.
| Client | SCIM clients | IAM v2 client |
|---|---|---|
| Databricks SDK for Python | users, groups, and service_principals, or users_v2, groups_v2, and service_principals_v2. workspace_assignment in the account client. |
workspace_iam_v2 in the workspace client, iam_v2 in the account |
| Databricks SDK for Go | Users, Groups, and ServicePrincipals, or UsersV2, GroupsV2, and ServicePrincipalsV2. WorkspaceAssignment in the account client. |
WorkspaceIamV2 in the workspace client, IamV2 in the account |
| Databricks SDK for Java | users(), groups(), and servicePrincipals(), or usersV2(), groupsV2(), and servicePrincipalsV2(). workspaceAssignment() in the account client. |
workspaceIamV2() in the workspace client, iamV2() in the account |
| Databricks CLI | databricks users, databricks groups, and databricks service-principals. databricks account workspace-assignment in the account. |
databricks workspace-iam-v2, databricks account iam-v2 |
Entitlement mapping
Entitlements move from the user, group, or service principal to its workspace assignment, which lists every entitlement granted directly to the principal in that workspace.
| SCIM entitlement or permission | IAM v2 entitlement |
|---|---|
workspace-access |
WORKSPACE_ACCESS |
Permission USER on a permission assignment |
An assignment with the entitlements the principal needs, such as WORKSPACE_ACCESS |
workspace-consume |
WORKSPACE_CONSUME |
databricks-sql-access |
DATABRICKS_SQL_ACCESS |
allow-cluster-create |
ALLOW_CLUSTER_CREATE |
allow-instance-pool-create |
ALLOW_INSTANCE_POOL_CREATE |
Permission ADMIN on a permission assignment |
WORKSPACE_ADMIN |
Membership in the workspace admins group |
No change. Membership in the admins group still grants WORKSPACE_ADMIN. |
Examples
The examples use the workspace-level methods. Replace <workspace-url> with your workspace URL, and authenticate as described in Authorize access to Azure Databricks resources.
Create a user
To create a user, run the following. IAM v2 requires username, full_name, and account_user_status on create, so a request that sends only username fails.
curl
curl -X POST "https://<workspace-url>/api/2.0/identity/users" \
-H "Authorization: Bearer $DATABRICKS_TOKEN" \
-d '{
"username": "jane.doe@example.com",
"full_name": {"given_name": "Jane", "family_name": "Doe"},
"account_user_status": "ACTIVE"
}'
Python
from databricks.sdk import WorkspaceClient
from databricks.sdk.service import iamv2
w = WorkspaceClient()
user = w.workspace_iam_v2.create_user_proxy(
user=iamv2.User(
username="jane.doe@example.com",
full_name=iamv2.UserFullName(given_name="Jane", family_name="Doe"),
account_user_status=iamv2.State.ACTIVE,
)
)
print(user.name) # users/<user-id>
Go
user, err := w.WorkspaceIamV2.CreateUserProxy(ctx, iamv2.CreateUserProxyRequest{
User: iamv2.User{
Username: "jane.doe@example.com",
FullName: iamv2.UserFullName{GivenName: "Jane", FamilyName: "Doe"},
AccountUserStatus: iamv2.StateActive,
},
})
Java
User user = w.workspaceIamV2().createUserProxy(
new CreateUserProxyRequest().setUser(
new User()
.setUsername("jane.doe@example.com")
.setFullName(new UserFullName().setGivenName("Jane").setFamilyName("Doe"))
.setAccountUserStatus(State.ACTIVE)));
CLI
databricks workspace-iam-v2 create-user-proxy --json '{
"username": "jane.doe@example.com",
"full_name": {"given_name": "Jane", "family_name": "Doe"},
"account_user_status": "ACTIVE"
}'
Find a user by username
To look up a user by username, run the following:
curl
curl -G "https://<workspace-url>/api/2.0/identity/users" \
-H "Authorization: Bearer $DATABRICKS_TOKEN" \
--data-urlencode 'filter=username eq "jane.doe@example.com"'
Python
for user in w.workspace_iam_v2.list_users_proxy(filter='username eq "jane.doe@example.com"'):
print(user.name, user.user_id)
Go
users, err := w.WorkspaceIamV2.ListUsersProxyAll(ctx, iamv2.ListUsersProxyRequest{
Filter: `username eq "jane.doe@example.com"`,
})
for _, user := range users {
fmt.Println(user.Name, user.UserId)
}
Java
for (User user : w.workspaceIamV2().listUsersProxy(
new ListUsersProxyRequest().setFilter("username eq \"jane.doe@example.com\""))) {
System.out.println(user.getName());
}
CLI
databricks workspace-iam-v2 list-users-proxy --filter 'username eq "jane.doe@example.com"'
The SDKs and the Databricks CLI fetch every page for you. In REST, repeat the call with page_token set to the previous next_page_token until it's empty.
Update a user
To change a user's name and deactivate the user in the account, run the following:
curl
curl -X PATCH "https://<workspace-url>/api/2.0/identity/users/<user-id>?update_mask=full_name.family_name,account_user_status" \
-H "Authorization: Bearer $DATABRICKS_TOKEN" \
-d '{"username": "jane.doe@example.com", "full_name": {"family_name": "Smith"}, "account_user_status": "INACTIVE"}'
Python
w.workspace_iam_v2.update_user_proxy(
name="users/<user-id>",
user=iamv2.User(
username="jane.doe@example.com",
full_name=iamv2.UserFullName(family_name="Smith"),
account_user_status=iamv2.State.INACTIVE,
),
update_mask="full_name.family_name,account_user_status",
)
Go
_, err := w.WorkspaceIamV2.UpdateUserProxy(ctx, iamv2.UpdateUserProxyRequest{
Name: "users/<user-id>",
User: iamv2.User{
Username: "jane.doe@example.com",
FullName: iamv2.UserFullName{FamilyName: "Smith"},
AccountUserStatus: iamv2.StateInactive,
},
UpdateMask: "full_name.family_name,account_user_status",
})
Java
w.workspaceIamV2().updateUserProxy(
new UpdateUserProxyRequest()
.setName("users/<user-id>")
.setUser(
new User()
.setUsername("jane.doe@example.com")
.setFullName(new UserFullName().setFamilyName("Smith"))
.setAccountUserStatus(State.INACTIVE))
.setUpdateMask("full_name.family_name,account_user_status"));
CLI
databricks workspace-iam-v2 update-user-proxy users/<user-id> full_name.family_name,account_user_status --json '{
"username": "jane.doe@example.com",
"full_name": {"family_name": "Smith"},
"account_user_status": "INACTIVE"
}'
Only the fields in update_mask change. The following rules also apply:
usernameis immutable, so a SCIMuserNamechange has no IAM v2 equivalent. An update that includesusernamein the mask fails withINVALID_PARAMETER_VALUE.- The account owner and hidden users can't have their status changed.
- You can't deactivate the user you're signed in as.
- The SDKs require
usernamein the request body even when the mask doesn't include it, so the examples include it.
Create a group and add a member
To create a group and add a user to it, run the following. Replace <user-id> with the user's ID from the create-a-user example, and use the group ID returned by the create call.
curl
curl -X POST "https://<workspace-url>/api/2.0/identity/groups" \
-H "Authorization: Bearer $DATABRICKS_TOKEN" \
-d '{"group_name": "data-engineers"}'
curl -X POST "https://<workspace-url>/api/2.0/identity/groups/<group-id>/direct-members" \
-H "Authorization: Bearer $DATABRICKS_TOKEN" \
-d '{"principal_id": <user-id>}'
Python
group = w.workspace_iam_v2.create_group_proxy(group=iamv2.Group(group_name="data-engineers"))
w.workspace_iam_v2.create_direct_group_member_proxy(
parent=group.name,
direct_group_member=iamv2.DirectGroupMember(principal_id=int(user.user_id)),
)
Go
group, err := w.WorkspaceIamV2.CreateGroupProxy(ctx, iamv2.CreateGroupProxyRequest{
Group: iamv2.Group{GroupName: "data-engineers"},
})
_, err = w.WorkspaceIamV2.CreateDirectGroupMemberProxy(ctx, iamv2.CreateDirectGroupMemberProxyRequest{
Parent: group.Name,
DirectGroupMember: iamv2.DirectGroupMember{PrincipalId: userId},
})
Java
Group group = w.workspaceIamV2().createGroupProxy(
new CreateGroupProxyRequest().setGroup(new Group().setGroupName("data-engineers")));
w.workspaceIamV2().createDirectGroupMemberProxy(
new CreateDirectGroupMemberProxyRequest()
.setParent(group.getName())
.setDirectGroupMember(new DirectGroupMember().setPrincipalId(userId)));
CLI
databricks workspace-iam-v2 create-group-proxy --group-name data-engineers
databricks workspace-iam-v2 create-direct-group-member-proxy groups/<group-id> <user-id>
To remove the member, delete groups/<group-id>/direct-members/<user-id>.
Grant entitlements in a workspace
To give a group workspace access and SQL access in this workspace, run the following:
curl
curl -X POST "https://<workspace-url>/api/2.0/identity/workspace-assignments" \
-H "Authorization: Bearer $DATABRICKS_TOKEN" \
-d '{"principal_id": <group-id>, "entitlements": ["WORKSPACE_ACCESS", "DATABRICKS_SQL_ACCESS"]}'
Python
w.workspace_iam_v2.create_workspace_assignment_proxy(
workspace_assignment=iamv2.WorkspaceAssignment(
principal_id=int(group.group_id),
entitlements=[iamv2.Entitlement.WORKSPACE_ACCESS, iamv2.Entitlement.DATABRICKS_SQL_ACCESS],
)
)
Go
_, err := w.WorkspaceIamV2.CreateWorkspaceAssignmentProxy(ctx, iamv2.CreateWorkspaceAssignmentProxyRequest{
WorkspaceAssignment: iamv2.WorkspaceAssignment{
PrincipalId: groupId,
Entitlements: []iamv2.Entitlement{iamv2.EntitlementWorkspaceAccess, iamv2.EntitlementDatabricksSqlAccess},
},
})
Java
w.workspaceIamV2().createWorkspaceAssignmentProxy(
new CreateWorkspaceAssignmentProxyRequest()
.setWorkspaceAssignment(
new WorkspaceAssignment()
.setPrincipalId(groupId)
.setEntitlements(
List.of(Entitlement.WORKSPACE_ACCESS, Entitlement.DATABRICKS_SQL_ACCESS))));
CLI
databricks workspace-iam-v2 create-workspace-assignment-proxy --json '{
"principal_id": <group-id>,
"entitlements": ["WORKSPACE_ACCESS", "DATABRICKS_SQL_ACCESS"]
}'
An assignment needs at least one entitlement. Use these calls to manage an existing assignment:
- To change its entitlements, update
workspace-assignments/<principal-id>withupdate_mask=entitlementsand the full list of entitlements to keep. - To remove the principal from the workspace, delete the assignment.
- To read every entitlement the principal holds, including through groups, get the assignment and read
effective_entitlements.
Deactivate a principal in one workspace
To deactivate a user or service principal in one workspace without changing its account status, update principals/<principal-id>/workspace-identity-detail with update_mask=workspace_identity_status and set workspace_identity_status to INACTIVE. You can't activate or deactivate the user you're signed in as, and group principals aren't supported. See the Workspace Identity Detail API.
Identities from Microsoft Entra ID
When automatic identity management is enabled, users, groups, and service principals from Microsoft Entra ID sync to Azure Databricks when they're first used. You can't create them with external_id set. Instead, get the external principal by its ID in Microsoft Entra ID. The call syncs the principal's details and group memberships and returns its Azure Databricks ID in internal_id:
| Principal | Workspace-level call |
|---|---|
| User | GET /api/2.0/identity/external-users/<external-id> |
| Group | GET /api/2.0/identity/external-groups/<external-id> |
| Service principal | GET /api/2.0/identity/external-service-principals/<external-id> |
Service principals sync only from Microsoft Entra ID.
To filter on the external ID of a principal that already exists, use external_id eq "<external-id>". See Automatic identity management.
For a principal that syncs from Microsoft Entra ID, you can update only external_id. Its other fields come from Microsoft Entra ID. You can't add or remove direct members of a group that syncs from Microsoft Entra ID.
What IAM v2 doesn't cover
Keep using the SCIM APIs for the following:
- Workspace-local groups. Migrate them to account groups first: Migrate workspace-local groups to account groups.
- Roles and instance profiles on users, groups, and service principals.
- The account admin role.
Additional resources
| Resource | Description |
|---|---|
| Migrate Terraform identity resources to IAM v2 | Move Terraform configurations from the SCIM-based identity resources to the IAM v2 resources. |
| Manage Azure Databricks users | Add, update, and remove users in Azure Databricks as an account or workspace admin. |