Files
zenml/venv/lib/python3.9/site-packages/databricks/sdk/service/iam.py
Christian Mantha 2ca0b9ef7c star
2026-03-02 19:10:52 -05:00

6397 lines
246 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
from __future__ import annotations
import logging
from dataclasses import dataclass
from enum import Enum
from typing import Any, Dict, Iterator, List, Optional
from databricks.sdk.client_types import HostType
from databricks.sdk.service._internal import (_enum, _from_dict,
_repeated_dict, _repeated_enum)
_LOG = logging.getLogger("databricks.sdk")
# all definitions in this file are in alphabetical order
@dataclass
class AccessControlRequest:
group_name: Optional[str] = None
"""name of the group"""
permission_level: Optional[PermissionLevel] = None
service_principal_name: Optional[str] = None
"""application ID of a service principal"""
user_name: Optional[str] = None
"""name of the user"""
def as_dict(self) -> dict:
"""Serializes the AccessControlRequest into a dictionary suitable for use as a JSON request body."""
body = {}
if self.group_name is not None:
body["group_name"] = self.group_name
if self.permission_level is not None:
body["permission_level"] = self.permission_level.value
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the AccessControlRequest into a shallow dictionary of its immediate attributes."""
body = {}
if self.group_name is not None:
body["group_name"] = self.group_name
if self.permission_level is not None:
body["permission_level"] = self.permission_level
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> AccessControlRequest:
"""Deserializes the AccessControlRequest from a dictionary."""
return cls(
group_name=d.get("group_name", None),
permission_level=_enum(d, "permission_level", PermissionLevel),
service_principal_name=d.get("service_principal_name", None),
user_name=d.get("user_name", None),
)
@dataclass
class AccessControlResponse:
all_permissions: Optional[List[Permission]] = None
"""All permissions."""
display_name: Optional[str] = None
"""Display name of the user or service principal."""
group_name: Optional[str] = None
"""name of the group"""
service_principal_name: Optional[str] = None
"""Name of the service principal."""
user_name: Optional[str] = None
"""name of the user"""
def as_dict(self) -> dict:
"""Serializes the AccessControlResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.all_permissions:
body["all_permissions"] = [v.as_dict() for v in self.all_permissions]
if self.display_name is not None:
body["display_name"] = self.display_name
if self.group_name is not None:
body["group_name"] = self.group_name
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the AccessControlResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.all_permissions:
body["all_permissions"] = self.all_permissions
if self.display_name is not None:
body["display_name"] = self.display_name
if self.group_name is not None:
body["group_name"] = self.group_name
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> AccessControlResponse:
"""Deserializes the AccessControlResponse from a dictionary."""
return cls(
all_permissions=_repeated_dict(d, "all_permissions", Permission),
display_name=d.get("display_name", None),
group_name=d.get("group_name", None),
service_principal_name=d.get("service_principal_name", None),
user_name=d.get("user_name", None),
)
@dataclass
class AccountGroup:
account_id: Optional[str] = None
"""Databricks account ID"""
display_name: Optional[str] = None
"""String that represents a human-readable group name"""
external_id: Optional[str] = None
"""external_id should be unique for identifying groups"""
id: Optional[str] = None
"""Databricks group ID"""
members: Optional[List[ComplexValue]] = None
meta: Optional[ResourceMeta] = None
"""Container for the group identifier. Workspace local versus account."""
roles: Optional[List[ComplexValue]] = None
"""Indicates if the group has the admin role."""
def as_dict(self) -> dict:
"""Serializes the AccountGroup into a dictionary suitable for use as a JSON request body."""
body = {}
if self.account_id is not None:
body["account_id"] = self.account_id
if self.display_name is not None:
body["displayName"] = self.display_name
if self.external_id is not None:
body["externalId"] = self.external_id
if self.id is not None:
body["id"] = self.id
if self.members:
body["members"] = [v.as_dict() for v in self.members]
if self.meta:
body["meta"] = self.meta.as_dict()
if self.roles:
body["roles"] = [v.as_dict() for v in self.roles]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the AccountGroup into a shallow dictionary of its immediate attributes."""
body = {}
if self.account_id is not None:
body["account_id"] = self.account_id
if self.display_name is not None:
body["displayName"] = self.display_name
if self.external_id is not None:
body["externalId"] = self.external_id
if self.id is not None:
body["id"] = self.id
if self.members:
body["members"] = self.members
if self.meta:
body["meta"] = self.meta
if self.roles:
body["roles"] = self.roles
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> AccountGroup:
"""Deserializes the AccountGroup from a dictionary."""
return cls(
account_id=d.get("account_id", None),
display_name=d.get("displayName", None),
external_id=d.get("externalId", None),
id=d.get("id", None),
members=_repeated_dict(d, "members", ComplexValue),
meta=_from_dict(d, "meta", ResourceMeta),
roles=_repeated_dict(d, "roles", ComplexValue),
)
@dataclass
class AccountServicePrincipal:
account_id: Optional[str] = None
"""Databricks account ID"""
active: Optional[bool] = None
"""If this user is active"""
application_id: Optional[str] = None
"""UUID relating to the service principal"""
display_name: Optional[str] = None
"""String that represents a concatenation of given and family names."""
external_id: Optional[str] = None
id: Optional[str] = None
"""Databricks service principal ID."""
roles: Optional[List[ComplexValue]] = None
"""Indicates if the group has the admin role."""
def as_dict(self) -> dict:
"""Serializes the AccountServicePrincipal into a dictionary suitable for use as a JSON request body."""
body = {}
if self.account_id is not None:
body["account_id"] = self.account_id
if self.active is not None:
body["active"] = self.active
if self.application_id is not None:
body["applicationId"] = self.application_id
if self.display_name is not None:
body["displayName"] = self.display_name
if self.external_id is not None:
body["externalId"] = self.external_id
if self.id is not None:
body["id"] = self.id
if self.roles:
body["roles"] = [v.as_dict() for v in self.roles]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the AccountServicePrincipal into a shallow dictionary of its immediate attributes."""
body = {}
if self.account_id is not None:
body["account_id"] = self.account_id
if self.active is not None:
body["active"] = self.active
if self.application_id is not None:
body["applicationId"] = self.application_id
if self.display_name is not None:
body["displayName"] = self.display_name
if self.external_id is not None:
body["externalId"] = self.external_id
if self.id is not None:
body["id"] = self.id
if self.roles:
body["roles"] = self.roles
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> AccountServicePrincipal:
"""Deserializes the AccountServicePrincipal from a dictionary."""
return cls(
account_id=d.get("account_id", None),
active=d.get("active", None),
application_id=d.get("applicationId", None),
display_name=d.get("displayName", None),
external_id=d.get("externalId", None),
id=d.get("id", None),
roles=_repeated_dict(d, "roles", ComplexValue),
)
@dataclass
class AccountUser:
account_id: Optional[str] = None
"""Databricks account ID"""
active: Optional[bool] = None
"""If this user is active"""
display_name: Optional[str] = None
"""String that represents a concatenation of given and family names. For example `John Smith`."""
emails: Optional[List[ComplexValue]] = None
"""All the emails associated with the Databricks user."""
external_id: Optional[str] = None
"""External ID is not currently supported. It is reserved for future use."""
id: Optional[str] = None
"""Databricks user ID."""
name: Optional[Name] = None
roles: Optional[List[ComplexValue]] = None
"""Indicates if the group has the admin role."""
user_name: Optional[str] = None
"""Email address of the Databricks user."""
def as_dict(self) -> dict:
"""Serializes the AccountUser into a dictionary suitable for use as a JSON request body."""
body = {}
if self.account_id is not None:
body["account_id"] = self.account_id
if self.active is not None:
body["active"] = self.active
if self.display_name is not None:
body["displayName"] = self.display_name
if self.emails:
body["emails"] = [v.as_dict() for v in self.emails]
if self.external_id is not None:
body["externalId"] = self.external_id
if self.id is not None:
body["id"] = self.id
if self.name:
body["name"] = self.name.as_dict()
if self.roles:
body["roles"] = [v.as_dict() for v in self.roles]
if self.user_name is not None:
body["userName"] = self.user_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the AccountUser into a shallow dictionary of its immediate attributes."""
body = {}
if self.account_id is not None:
body["account_id"] = self.account_id
if self.active is not None:
body["active"] = self.active
if self.display_name is not None:
body["displayName"] = self.display_name
if self.emails:
body["emails"] = self.emails
if self.external_id is not None:
body["externalId"] = self.external_id
if self.id is not None:
body["id"] = self.id
if self.name:
body["name"] = self.name
if self.roles:
body["roles"] = self.roles
if self.user_name is not None:
body["userName"] = self.user_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> AccountUser:
"""Deserializes the AccountUser from a dictionary."""
return cls(
account_id=d.get("account_id", None),
active=d.get("active", None),
display_name=d.get("displayName", None),
emails=_repeated_dict(d, "emails", ComplexValue),
external_id=d.get("externalId", None),
id=d.get("id", None),
name=_from_dict(d, "name", Name),
roles=_repeated_dict(d, "roles", ComplexValue),
user_name=d.get("userName", None),
)
@dataclass
class Actor:
"""represents an identity trying to access a resource - user or a service principal group can be a
principal of a permission set assignment but an actor is always a user or a service principal"""
actor_id: Optional[int] = None
def as_dict(self) -> dict:
"""Serializes the Actor into a dictionary suitable for use as a JSON request body."""
body = {}
if self.actor_id is not None:
body["actor_id"] = self.actor_id
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Actor into a shallow dictionary of its immediate attributes."""
body = {}
if self.actor_id is not None:
body["actor_id"] = self.actor_id
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Actor:
"""Deserializes the Actor from a dictionary."""
return cls(actor_id=d.get("actor_id", None))
@dataclass
class CheckPolicyResponse:
consistency_token: ConsistencyToken
is_permitted: Optional[bool] = None
def as_dict(self) -> dict:
"""Serializes the CheckPolicyResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.consistency_token:
body["consistency_token"] = self.consistency_token.as_dict()
if self.is_permitted is not None:
body["is_permitted"] = self.is_permitted
return body
def as_shallow_dict(self) -> dict:
"""Serializes the CheckPolicyResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.consistency_token:
body["consistency_token"] = self.consistency_token
if self.is_permitted is not None:
body["is_permitted"] = self.is_permitted
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> CheckPolicyResponse:
"""Deserializes the CheckPolicyResponse from a dictionary."""
return cls(
consistency_token=_from_dict(d, "consistency_token", ConsistencyToken),
is_permitted=d.get("is_permitted", None),
)
@dataclass
class ComplexValue:
display: Optional[str] = None
primary: Optional[bool] = None
ref: Optional[str] = None
type: Optional[str] = None
value: Optional[str] = None
def as_dict(self) -> dict:
"""Serializes the ComplexValue into a dictionary suitable for use as a JSON request body."""
body = {}
if self.display is not None:
body["display"] = self.display
if self.primary is not None:
body["primary"] = self.primary
if self.ref is not None:
body["$ref"] = self.ref
if self.type is not None:
body["type"] = self.type
if self.value is not None:
body["value"] = self.value
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ComplexValue into a shallow dictionary of its immediate attributes."""
body = {}
if self.display is not None:
body["display"] = self.display
if self.primary is not None:
body["primary"] = self.primary
if self.ref is not None:
body["$ref"] = self.ref
if self.type is not None:
body["type"] = self.type
if self.value is not None:
body["value"] = self.value
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ComplexValue:
"""Deserializes the ComplexValue from a dictionary."""
return cls(
display=d.get("display", None),
primary=d.get("primary", None),
ref=d.get("$ref", None),
type=d.get("type", None),
value=d.get("value", None),
)
@dataclass
class ConsistencyToken:
value: str
def as_dict(self) -> dict:
"""Serializes the ConsistencyToken into a dictionary suitable for use as a JSON request body."""
body = {}
if self.value is not None:
body["value"] = self.value
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ConsistencyToken into a shallow dictionary of its immediate attributes."""
body = {}
if self.value is not None:
body["value"] = self.value
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ConsistencyToken:
"""Deserializes the ConsistencyToken from a dictionary."""
return cls(value=d.get("value", None))
@dataclass
class DeleteWorkspacePermissionAssignmentResponse:
def as_dict(self) -> dict:
"""Serializes the DeleteWorkspacePermissionAssignmentResponse into a dictionary suitable for use as a JSON request body."""
body = {}
return body
def as_shallow_dict(self) -> dict:
"""Serializes the DeleteWorkspacePermissionAssignmentResponse into a shallow dictionary of its immediate attributes."""
body = {}
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> DeleteWorkspacePermissionAssignmentResponse:
"""Deserializes the DeleteWorkspacePermissionAssignmentResponse from a dictionary."""
return cls()
@dataclass
class GetAssignableRolesForResourceResponse:
roles: Optional[List[Role]] = None
def as_dict(self) -> dict:
"""Serializes the GetAssignableRolesForResourceResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.roles:
body["roles"] = [v.as_dict() for v in self.roles]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the GetAssignableRolesForResourceResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.roles:
body["roles"] = self.roles
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> GetAssignableRolesForResourceResponse:
"""Deserializes the GetAssignableRolesForResourceResponse from a dictionary."""
return cls(roles=_repeated_dict(d, "roles", Role))
@dataclass
class GetPasswordPermissionLevelsResponse:
permission_levels: Optional[List[PasswordPermissionsDescription]] = None
"""Specific permission levels"""
def as_dict(self) -> dict:
"""Serializes the GetPasswordPermissionLevelsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.permission_levels:
body["permission_levels"] = [v.as_dict() for v in self.permission_levels]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the GetPasswordPermissionLevelsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.permission_levels:
body["permission_levels"] = self.permission_levels
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> GetPasswordPermissionLevelsResponse:
"""Deserializes the GetPasswordPermissionLevelsResponse from a dictionary."""
return cls(permission_levels=_repeated_dict(d, "permission_levels", PasswordPermissionsDescription))
@dataclass
class GetPermissionLevelsResponse:
permission_levels: Optional[List[PermissionsDescription]] = None
"""Specific permission levels"""
def as_dict(self) -> dict:
"""Serializes the GetPermissionLevelsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.permission_levels:
body["permission_levels"] = [v.as_dict() for v in self.permission_levels]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the GetPermissionLevelsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.permission_levels:
body["permission_levels"] = self.permission_levels
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> GetPermissionLevelsResponse:
"""Deserializes the GetPermissionLevelsResponse from a dictionary."""
return cls(permission_levels=_repeated_dict(d, "permission_levels", PermissionsDescription))
class GetSortOrder(Enum):
ASCENDING = "ascending"
DESCENDING = "descending"
@dataclass
class GrantRule:
role: str
"""Role that is assigned to the list of principals."""
principals: Optional[List[str]] = None
"""Principals this grant rule applies to. A principal can be a user (for end users), a service
principal (for applications and compute workloads), or an account group. Each principal has its
own identifier format: * users/<USERNAME> * groups/<GROUP_NAME> *
servicePrincipals/<SERVICE_PRINCIPAL_APPLICATION_ID>"""
def as_dict(self) -> dict:
"""Serializes the GrantRule into a dictionary suitable for use as a JSON request body."""
body = {}
if self.principals:
body["principals"] = [v for v in self.principals]
if self.role is not None:
body["role"] = self.role
return body
def as_shallow_dict(self) -> dict:
"""Serializes the GrantRule into a shallow dictionary of its immediate attributes."""
body = {}
if self.principals:
body["principals"] = self.principals
if self.role is not None:
body["role"] = self.role
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> GrantRule:
"""Deserializes the GrantRule from a dictionary."""
return cls(principals=d.get("principals", None), role=d.get("role", None))
@dataclass
class Group:
display_name: Optional[str] = None
"""String that represents a human-readable group name"""
entitlements: Optional[List[ComplexValue]] = None
"""Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements"""
external_id: Optional[str] = None
"""external_id should be unique for identifying groups"""
groups: Optional[List[ComplexValue]] = None
id: Optional[str] = None
"""Databricks group ID"""
members: Optional[List[ComplexValue]] = None
meta: Optional[ResourceMeta] = None
"""Container for the group identifier. Workspace local versus account."""
roles: Optional[List[ComplexValue]] = None
"""Corresponds to AWS instance profile/arn role."""
schemas: Optional[List[GroupSchema]] = None
"""The schema of the group."""
def as_dict(self) -> dict:
"""Serializes the Group into a dictionary suitable for use as a JSON request body."""
body = {}
if self.display_name is not None:
body["displayName"] = self.display_name
if self.entitlements:
body["entitlements"] = [v.as_dict() for v in self.entitlements]
if self.external_id is not None:
body["externalId"] = self.external_id
if self.groups:
body["groups"] = [v.as_dict() for v in self.groups]
if self.id is not None:
body["id"] = self.id
if self.members:
body["members"] = [v.as_dict() for v in self.members]
if self.meta:
body["meta"] = self.meta.as_dict()
if self.roles:
body["roles"] = [v.as_dict() for v in self.roles]
if self.schemas:
body["schemas"] = [v.value for v in self.schemas]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Group into a shallow dictionary of its immediate attributes."""
body = {}
if self.display_name is not None:
body["displayName"] = self.display_name
if self.entitlements:
body["entitlements"] = self.entitlements
if self.external_id is not None:
body["externalId"] = self.external_id
if self.groups:
body["groups"] = self.groups
if self.id is not None:
body["id"] = self.id
if self.members:
body["members"] = self.members
if self.meta:
body["meta"] = self.meta
if self.roles:
body["roles"] = self.roles
if self.schemas:
body["schemas"] = self.schemas
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Group:
"""Deserializes the Group from a dictionary."""
return cls(
display_name=d.get("displayName", None),
entitlements=_repeated_dict(d, "entitlements", ComplexValue),
external_id=d.get("externalId", None),
groups=_repeated_dict(d, "groups", ComplexValue),
id=d.get("id", None),
members=_repeated_dict(d, "members", ComplexValue),
meta=_from_dict(d, "meta", ResourceMeta),
roles=_repeated_dict(d, "roles", ComplexValue),
schemas=_repeated_enum(d, "schemas", GroupSchema),
)
class GroupSchema(Enum):
URN_IETF_PARAMS_SCIM_SCHEMAS_CORE_2_0_GROUP = "urn:ietf:params:scim:schemas:core:2.0:Group"
@dataclass
class ListAccountGroupsResponse:
items_per_page: Optional[int] = None
"""Total results returned in the response."""
resources: Optional[List[AccountGroup]] = None
"""User objects returned in the response."""
start_index: Optional[int] = None
"""Starting index of all the results that matched the request filters. First item is number 1."""
total_results: Optional[int] = None
"""Total results that match the request filters."""
def as_dict(self) -> dict:
"""Serializes the ListAccountGroupsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = [v.as_dict() for v in self.resources]
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListAccountGroupsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = self.resources
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListAccountGroupsResponse:
"""Deserializes the ListAccountGroupsResponse from a dictionary."""
return cls(
items_per_page=d.get("itemsPerPage", None),
resources=_repeated_dict(d, "Resources", AccountGroup),
start_index=d.get("startIndex", None),
total_results=d.get("totalResults", None),
)
@dataclass
class ListAccountServicePrincipalsResponse:
items_per_page: Optional[int] = None
"""Total results returned in the response."""
resources: Optional[List[AccountServicePrincipal]] = None
"""User objects returned in the response."""
start_index: Optional[int] = None
"""Starting index of all the results that matched the request filters. First item is number 1."""
total_results: Optional[int] = None
"""Total results that match the request filters."""
def as_dict(self) -> dict:
"""Serializes the ListAccountServicePrincipalsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = [v.as_dict() for v in self.resources]
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListAccountServicePrincipalsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = self.resources
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListAccountServicePrincipalsResponse:
"""Deserializes the ListAccountServicePrincipalsResponse from a dictionary."""
return cls(
items_per_page=d.get("itemsPerPage", None),
resources=_repeated_dict(d, "Resources", AccountServicePrincipal),
start_index=d.get("startIndex", None),
total_results=d.get("totalResults", None),
)
@dataclass
class ListAccountUsersResponse:
items_per_page: Optional[int] = None
"""Total results returned in the response."""
resources: Optional[List[AccountUser]] = None
"""User objects returned in the response."""
start_index: Optional[int] = None
"""Starting index of all the results that matched the request filters. First item is number 1."""
total_results: Optional[int] = None
"""Total results that match the request filters."""
def as_dict(self) -> dict:
"""Serializes the ListAccountUsersResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = [v.as_dict() for v in self.resources]
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListAccountUsersResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = self.resources
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListAccountUsersResponse:
"""Deserializes the ListAccountUsersResponse from a dictionary."""
return cls(
items_per_page=d.get("itemsPerPage", None),
resources=_repeated_dict(d, "Resources", AccountUser),
start_index=d.get("startIndex", None),
total_results=d.get("totalResults", None),
)
@dataclass
class ListGroupsResponse:
items_per_page: Optional[int] = None
"""Total results returned in the response."""
resources: Optional[List[Group]] = None
"""User objects returned in the response."""
schemas: Optional[List[ListResponseSchema]] = None
"""The schema of the service principal."""
start_index: Optional[int] = None
"""Starting index of all the results that matched the request filters. First item is number 1."""
total_results: Optional[int] = None
"""Total results that match the request filters."""
def as_dict(self) -> dict:
"""Serializes the ListGroupsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = [v.as_dict() for v in self.resources]
if self.schemas:
body["schemas"] = [v.value for v in self.schemas]
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListGroupsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = self.resources
if self.schemas:
body["schemas"] = self.schemas
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListGroupsResponse:
"""Deserializes the ListGroupsResponse from a dictionary."""
return cls(
items_per_page=d.get("itemsPerPage", None),
resources=_repeated_dict(d, "Resources", Group),
schemas=_repeated_enum(d, "schemas", ListResponseSchema),
start_index=d.get("startIndex", None),
total_results=d.get("totalResults", None),
)
class ListResponseSchema(Enum):
URN_IETF_PARAMS_SCIM_API_MESSAGES_2_0_LIST_RESPONSE = "urn:ietf:params:scim:api:messages:2.0:ListResponse"
@dataclass
class ListServicePrincipalResponse:
items_per_page: Optional[int] = None
"""Total results returned in the response."""
resources: Optional[List[ServicePrincipal]] = None
"""User objects returned in the response."""
schemas: Optional[List[ListResponseSchema]] = None
"""The schema of the List response."""
start_index: Optional[int] = None
"""Starting index of all the results that matched the request filters. First item is number 1."""
total_results: Optional[int] = None
"""Total results that match the request filters."""
def as_dict(self) -> dict:
"""Serializes the ListServicePrincipalResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = [v.as_dict() for v in self.resources]
if self.schemas:
body["schemas"] = [v.value for v in self.schemas]
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListServicePrincipalResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = self.resources
if self.schemas:
body["schemas"] = self.schemas
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListServicePrincipalResponse:
"""Deserializes the ListServicePrincipalResponse from a dictionary."""
return cls(
items_per_page=d.get("itemsPerPage", None),
resources=_repeated_dict(d, "Resources", ServicePrincipal),
schemas=_repeated_enum(d, "schemas", ListResponseSchema),
start_index=d.get("startIndex", None),
total_results=d.get("totalResults", None),
)
class ListSortOrder(Enum):
ASCENDING = "ascending"
DESCENDING = "descending"
@dataclass
class ListUsersResponse:
items_per_page: Optional[int] = None
"""Total results returned in the response."""
resources: Optional[List[User]] = None
"""User objects returned in the response."""
schemas: Optional[List[ListResponseSchema]] = None
"""The schema of the List response."""
start_index: Optional[int] = None
"""Starting index of all the results that matched the request filters. First item is number 1."""
total_results: Optional[int] = None
"""Total results that match the request filters."""
def as_dict(self) -> dict:
"""Serializes the ListUsersResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = [v.as_dict() for v in self.resources]
if self.schemas:
body["schemas"] = [v.value for v in self.schemas]
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ListUsersResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.items_per_page is not None:
body["itemsPerPage"] = self.items_per_page
if self.resources:
body["Resources"] = self.resources
if self.schemas:
body["schemas"] = self.schemas
if self.start_index is not None:
body["startIndex"] = self.start_index
if self.total_results is not None:
body["totalResults"] = self.total_results
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ListUsersResponse:
"""Deserializes the ListUsersResponse from a dictionary."""
return cls(
items_per_page=d.get("itemsPerPage", None),
resources=_repeated_dict(d, "Resources", User),
schemas=_repeated_enum(d, "schemas", ListResponseSchema),
start_index=d.get("startIndex", None),
total_results=d.get("totalResults", None),
)
@dataclass
class MigratePermissionsResponse:
permissions_migrated: Optional[int] = None
"""Number of permissions migrated."""
def as_dict(self) -> dict:
"""Serializes the MigratePermissionsResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.permissions_migrated is not None:
body["permissions_migrated"] = self.permissions_migrated
return body
def as_shallow_dict(self) -> dict:
"""Serializes the MigratePermissionsResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.permissions_migrated is not None:
body["permissions_migrated"] = self.permissions_migrated
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> MigratePermissionsResponse:
"""Deserializes the MigratePermissionsResponse from a dictionary."""
return cls(permissions_migrated=d.get("permissions_migrated", None))
@dataclass
class Name:
family_name: Optional[str] = None
"""Family name of the Databricks user."""
given_name: Optional[str] = None
"""Given name of the Databricks user."""
def as_dict(self) -> dict:
"""Serializes the Name into a dictionary suitable for use as a JSON request body."""
body = {}
if self.family_name is not None:
body["familyName"] = self.family_name
if self.given_name is not None:
body["givenName"] = self.given_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Name into a shallow dictionary of its immediate attributes."""
body = {}
if self.family_name is not None:
body["familyName"] = self.family_name
if self.given_name is not None:
body["givenName"] = self.given_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Name:
"""Deserializes the Name from a dictionary."""
return cls(family_name=d.get("familyName", None), given_name=d.get("givenName", None))
@dataclass
class ObjectPermissions:
access_control_list: Optional[List[AccessControlResponse]] = None
object_id: Optional[str] = None
object_type: Optional[str] = None
def as_dict(self) -> dict:
"""Serializes the ObjectPermissions into a dictionary suitable for use as a JSON request body."""
body = {}
if self.access_control_list:
body["access_control_list"] = [v.as_dict() for v in self.access_control_list]
if self.object_id is not None:
body["object_id"] = self.object_id
if self.object_type is not None:
body["object_type"] = self.object_type
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ObjectPermissions into a shallow dictionary of its immediate attributes."""
body = {}
if self.access_control_list:
body["access_control_list"] = self.access_control_list
if self.object_id is not None:
body["object_id"] = self.object_id
if self.object_type is not None:
body["object_type"] = self.object_type
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ObjectPermissions:
"""Deserializes the ObjectPermissions from a dictionary."""
return cls(
access_control_list=_repeated_dict(d, "access_control_list", AccessControlResponse),
object_id=d.get("object_id", None),
object_type=d.get("object_type", None),
)
@dataclass
class PasswordAccessControlRequest:
group_name: Optional[str] = None
"""name of the group"""
permission_level: Optional[PasswordPermissionLevel] = None
"""Permission level"""
service_principal_name: Optional[str] = None
"""application ID of a service principal"""
user_name: Optional[str] = None
"""name of the user"""
def as_dict(self) -> dict:
"""Serializes the PasswordAccessControlRequest into a dictionary suitable for use as a JSON request body."""
body = {}
if self.group_name is not None:
body["group_name"] = self.group_name
if self.permission_level is not None:
body["permission_level"] = self.permission_level.value
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PasswordAccessControlRequest into a shallow dictionary of its immediate attributes."""
body = {}
if self.group_name is not None:
body["group_name"] = self.group_name
if self.permission_level is not None:
body["permission_level"] = self.permission_level
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PasswordAccessControlRequest:
"""Deserializes the PasswordAccessControlRequest from a dictionary."""
return cls(
group_name=d.get("group_name", None),
permission_level=_enum(d, "permission_level", PasswordPermissionLevel),
service_principal_name=d.get("service_principal_name", None),
user_name=d.get("user_name", None),
)
@dataclass
class PasswordAccessControlResponse:
all_permissions: Optional[List[PasswordPermission]] = None
"""All permissions."""
display_name: Optional[str] = None
"""Display name of the user or service principal."""
group_name: Optional[str] = None
"""name of the group"""
service_principal_name: Optional[str] = None
"""Name of the service principal."""
user_name: Optional[str] = None
"""name of the user"""
def as_dict(self) -> dict:
"""Serializes the PasswordAccessControlResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.all_permissions:
body["all_permissions"] = [v.as_dict() for v in self.all_permissions]
if self.display_name is not None:
body["display_name"] = self.display_name
if self.group_name is not None:
body["group_name"] = self.group_name
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PasswordAccessControlResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.all_permissions:
body["all_permissions"] = self.all_permissions
if self.display_name is not None:
body["display_name"] = self.display_name
if self.group_name is not None:
body["group_name"] = self.group_name
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PasswordAccessControlResponse:
"""Deserializes the PasswordAccessControlResponse from a dictionary."""
return cls(
all_permissions=_repeated_dict(d, "all_permissions", PasswordPermission),
display_name=d.get("display_name", None),
group_name=d.get("group_name", None),
service_principal_name=d.get("service_principal_name", None),
user_name=d.get("user_name", None),
)
@dataclass
class PasswordPermission:
inherited: Optional[bool] = None
inherited_from_object: Optional[List[str]] = None
permission_level: Optional[PasswordPermissionLevel] = None
"""Permission level"""
def as_dict(self) -> dict:
"""Serializes the PasswordPermission into a dictionary suitable for use as a JSON request body."""
body = {}
if self.inherited is not None:
body["inherited"] = self.inherited
if self.inherited_from_object:
body["inherited_from_object"] = [v for v in self.inherited_from_object]
if self.permission_level is not None:
body["permission_level"] = self.permission_level.value
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PasswordPermission into a shallow dictionary of its immediate attributes."""
body = {}
if self.inherited is not None:
body["inherited"] = self.inherited
if self.inherited_from_object:
body["inherited_from_object"] = self.inherited_from_object
if self.permission_level is not None:
body["permission_level"] = self.permission_level
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PasswordPermission:
"""Deserializes the PasswordPermission from a dictionary."""
return cls(
inherited=d.get("inherited", None),
inherited_from_object=d.get("inherited_from_object", None),
permission_level=_enum(d, "permission_level", PasswordPermissionLevel),
)
class PasswordPermissionLevel(Enum):
"""Permission level"""
CAN_USE = "CAN_USE"
@dataclass
class PasswordPermissions:
access_control_list: Optional[List[PasswordAccessControlResponse]] = None
object_id: Optional[str] = None
object_type: Optional[str] = None
def as_dict(self) -> dict:
"""Serializes the PasswordPermissions into a dictionary suitable for use as a JSON request body."""
body = {}
if self.access_control_list:
body["access_control_list"] = [v.as_dict() for v in self.access_control_list]
if self.object_id is not None:
body["object_id"] = self.object_id
if self.object_type is not None:
body["object_type"] = self.object_type
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PasswordPermissions into a shallow dictionary of its immediate attributes."""
body = {}
if self.access_control_list:
body["access_control_list"] = self.access_control_list
if self.object_id is not None:
body["object_id"] = self.object_id
if self.object_type is not None:
body["object_type"] = self.object_type
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PasswordPermissions:
"""Deserializes the PasswordPermissions from a dictionary."""
return cls(
access_control_list=_repeated_dict(d, "access_control_list", PasswordAccessControlResponse),
object_id=d.get("object_id", None),
object_type=d.get("object_type", None),
)
@dataclass
class PasswordPermissionsDescription:
description: Optional[str] = None
permission_level: Optional[PasswordPermissionLevel] = None
"""Permission level"""
def as_dict(self) -> dict:
"""Serializes the PasswordPermissionsDescription into a dictionary suitable for use as a JSON request body."""
body = {}
if self.description is not None:
body["description"] = self.description
if self.permission_level is not None:
body["permission_level"] = self.permission_level.value
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PasswordPermissionsDescription into a shallow dictionary of its immediate attributes."""
body = {}
if self.description is not None:
body["description"] = self.description
if self.permission_level is not None:
body["permission_level"] = self.permission_level
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PasswordPermissionsDescription:
"""Deserializes the PasswordPermissionsDescription from a dictionary."""
return cls(
description=d.get("description", None),
permission_level=_enum(d, "permission_level", PasswordPermissionLevel),
)
@dataclass
class Patch:
op: Optional[PatchOp] = None
"""Type of patch operation."""
path: Optional[str] = None
"""Selection of patch operation"""
value: Optional[Any] = None
"""Value to modify"""
def as_dict(self) -> dict:
"""Serializes the Patch into a dictionary suitable for use as a JSON request body."""
body = {}
if self.op is not None:
body["op"] = self.op.value
if self.path is not None:
body["path"] = self.path
if self.value:
body["value"] = self.value
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Patch into a shallow dictionary of its immediate attributes."""
body = {}
if self.op is not None:
body["op"] = self.op
if self.path is not None:
body["path"] = self.path
if self.value:
body["value"] = self.value
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Patch:
"""Deserializes the Patch from a dictionary."""
return cls(op=_enum(d, "op", PatchOp), path=d.get("path", None), value=d.get("value", None))
class PatchOp(Enum):
"""Type of patch operation."""
ADD = "add"
REMOVE = "remove"
REPLACE = "replace"
class PatchSchema(Enum):
URN_IETF_PARAMS_SCIM_API_MESSAGES_2_0_PATCH_OP = "urn:ietf:params:scim:api:messages:2.0:PatchOp"
@dataclass
class Permission:
inherited: Optional[bool] = None
inherited_from_object: Optional[List[str]] = None
permission_level: Optional[PermissionLevel] = None
def as_dict(self) -> dict:
"""Serializes the Permission into a dictionary suitable for use as a JSON request body."""
body = {}
if self.inherited is not None:
body["inherited"] = self.inherited
if self.inherited_from_object:
body["inherited_from_object"] = [v for v in self.inherited_from_object]
if self.permission_level is not None:
body["permission_level"] = self.permission_level.value
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Permission into a shallow dictionary of its immediate attributes."""
body = {}
if self.inherited is not None:
body["inherited"] = self.inherited
if self.inherited_from_object:
body["inherited_from_object"] = self.inherited_from_object
if self.permission_level is not None:
body["permission_level"] = self.permission_level
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Permission:
"""Deserializes the Permission from a dictionary."""
return cls(
inherited=d.get("inherited", None),
inherited_from_object=d.get("inherited_from_object", None),
permission_level=_enum(d, "permission_level", PermissionLevel),
)
@dataclass
class PermissionAssignment:
"""The output format for existing workspace PermissionAssignment records, which contains some info
for user consumption."""
error: Optional[str] = None
"""Error response associated with a workspace permission assignment, if any."""
permissions: Optional[List[WorkspacePermission]] = None
"""The permissions level of the principal."""
principal: Optional[PrincipalOutput] = None
"""Information about the principal assigned to the workspace."""
def as_dict(self) -> dict:
"""Serializes the PermissionAssignment into a dictionary suitable for use as a JSON request body."""
body = {}
if self.error is not None:
body["error"] = self.error
if self.permissions:
body["permissions"] = [v.value for v in self.permissions]
if self.principal:
body["principal"] = self.principal.as_dict()
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PermissionAssignment into a shallow dictionary of its immediate attributes."""
body = {}
if self.error is not None:
body["error"] = self.error
if self.permissions:
body["permissions"] = self.permissions
if self.principal:
body["principal"] = self.principal
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PermissionAssignment:
"""Deserializes the PermissionAssignment from a dictionary."""
return cls(
error=d.get("error", None),
permissions=_repeated_enum(d, "permissions", WorkspacePermission),
principal=_from_dict(d, "principal", PrincipalOutput),
)
@dataclass
class PermissionAssignments:
permission_assignments: Optional[List[PermissionAssignment]] = None
"""Array of permissions assignments defined for a workspace."""
def as_dict(self) -> dict:
"""Serializes the PermissionAssignments into a dictionary suitable for use as a JSON request body."""
body = {}
if self.permission_assignments:
body["permission_assignments"] = [v.as_dict() for v in self.permission_assignments]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PermissionAssignments into a shallow dictionary of its immediate attributes."""
body = {}
if self.permission_assignments:
body["permission_assignments"] = self.permission_assignments
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PermissionAssignments:
"""Deserializes the PermissionAssignments from a dictionary."""
return cls(permission_assignments=_repeated_dict(d, "permission_assignments", PermissionAssignment))
class PermissionLevel(Enum):
"""Permission level"""
CAN_ATTACH_TO = "CAN_ATTACH_TO"
CAN_BIND = "CAN_BIND"
CAN_CREATE = "CAN_CREATE"
CAN_EDIT = "CAN_EDIT"
CAN_EDIT_METADATA = "CAN_EDIT_METADATA"
CAN_MANAGE = "CAN_MANAGE"
CAN_MANAGE_PRODUCTION_VERSIONS = "CAN_MANAGE_PRODUCTION_VERSIONS"
CAN_MANAGE_RUN = "CAN_MANAGE_RUN"
CAN_MANAGE_STAGING_VERSIONS = "CAN_MANAGE_STAGING_VERSIONS"
CAN_MONITOR = "CAN_MONITOR"
CAN_MONITOR_ONLY = "CAN_MONITOR_ONLY"
CAN_QUERY = "CAN_QUERY"
CAN_READ = "CAN_READ"
CAN_RESTART = "CAN_RESTART"
CAN_RUN = "CAN_RUN"
CAN_USE = "CAN_USE"
CAN_VIEW = "CAN_VIEW"
CAN_VIEW_METADATA = "CAN_VIEW_METADATA"
IS_OWNER = "IS_OWNER"
@dataclass
class PermissionOutput:
description: Optional[str] = None
"""The results of a permissions query."""
permission_level: Optional[WorkspacePermission] = None
def as_dict(self) -> dict:
"""Serializes the PermissionOutput into a dictionary suitable for use as a JSON request body."""
body = {}
if self.description is not None:
body["description"] = self.description
if self.permission_level is not None:
body["permission_level"] = self.permission_level.value
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PermissionOutput into a shallow dictionary of its immediate attributes."""
body = {}
if self.description is not None:
body["description"] = self.description
if self.permission_level is not None:
body["permission_level"] = self.permission_level
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PermissionOutput:
"""Deserializes the PermissionOutput from a dictionary."""
return cls(
description=d.get("description", None), permission_level=_enum(d, "permission_level", WorkspacePermission)
)
@dataclass
class PermissionsDescription:
description: Optional[str] = None
permission_level: Optional[PermissionLevel] = None
def as_dict(self) -> dict:
"""Serializes the PermissionsDescription into a dictionary suitable for use as a JSON request body."""
body = {}
if self.description is not None:
body["description"] = self.description
if self.permission_level is not None:
body["permission_level"] = self.permission_level.value
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PermissionsDescription into a shallow dictionary of its immediate attributes."""
body = {}
if self.description is not None:
body["description"] = self.description
if self.permission_level is not None:
body["permission_level"] = self.permission_level
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PermissionsDescription:
"""Deserializes the PermissionsDescription from a dictionary."""
return cls(
description=d.get("description", None), permission_level=_enum(d, "permission_level", PermissionLevel)
)
@dataclass
class PrincipalOutput:
"""Information about the principal assigned to the workspace."""
display_name: Optional[str] = None
"""The display name of the principal."""
group_name: Optional[str] = None
"""The group name of the group. Present only if the principal is a group."""
principal_id: Optional[int] = None
"""The unique, opaque id of the principal."""
service_principal_name: Optional[str] = None
"""The name of the service principal. Present only if the principal is a service principal."""
user_name: Optional[str] = None
"""The username of the user. Present only if the principal is a user."""
def as_dict(self) -> dict:
"""Serializes the PrincipalOutput into a dictionary suitable for use as a JSON request body."""
body = {}
if self.display_name is not None:
body["display_name"] = self.display_name
if self.group_name is not None:
body["group_name"] = self.group_name
if self.principal_id is not None:
body["principal_id"] = self.principal_id
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the PrincipalOutput into a shallow dictionary of its immediate attributes."""
body = {}
if self.display_name is not None:
body["display_name"] = self.display_name
if self.group_name is not None:
body["group_name"] = self.group_name
if self.principal_id is not None:
body["principal_id"] = self.principal_id
if self.service_principal_name is not None:
body["service_principal_name"] = self.service_principal_name
if self.user_name is not None:
body["user_name"] = self.user_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> PrincipalOutput:
"""Deserializes the PrincipalOutput from a dictionary."""
return cls(
display_name=d.get("display_name", None),
group_name=d.get("group_name", None),
principal_id=d.get("principal_id", None),
service_principal_name=d.get("service_principal_name", None),
user_name=d.get("user_name", None),
)
class RequestAuthzIdentity(Enum):
"""Defines the identity to be used for authZ of the request on the server side. See one pager for
for more information: http://go/acl/service-identity"""
REQUEST_AUTHZ_IDENTITY_SERVICE_IDENTITY = "REQUEST_AUTHZ_IDENTITY_SERVICE_IDENTITY"
REQUEST_AUTHZ_IDENTITY_USER_CONTEXT = "REQUEST_AUTHZ_IDENTITY_USER_CONTEXT"
@dataclass
class ResourceInfo:
id: str
"""Id of the current resource."""
legacy_acl_path: Optional[str] = None
"""The legacy acl path of the current resource."""
parent_resource_info: Optional[ResourceInfo] = None
"""Parent resource info for the current resource. The parent may have another parent."""
def as_dict(self) -> dict:
"""Serializes the ResourceInfo into a dictionary suitable for use as a JSON request body."""
body = {}
if self.id is not None:
body["id"] = self.id
if self.legacy_acl_path is not None:
body["legacy_acl_path"] = self.legacy_acl_path
if self.parent_resource_info:
body["parent_resource_info"] = self.parent_resource_info.as_dict()
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ResourceInfo into a shallow dictionary of its immediate attributes."""
body = {}
if self.id is not None:
body["id"] = self.id
if self.legacy_acl_path is not None:
body["legacy_acl_path"] = self.legacy_acl_path
if self.parent_resource_info:
body["parent_resource_info"] = self.parent_resource_info
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ResourceInfo:
"""Deserializes the ResourceInfo from a dictionary."""
return cls(
id=d.get("id", None),
legacy_acl_path=d.get("legacy_acl_path", None),
parent_resource_info=_from_dict(d, "parent_resource_info", ResourceInfo),
)
@dataclass
class ResourceMeta:
resource_type: Optional[str] = None
"""Identifier for group type. Can be local workspace group (`WorkspaceGroup`) or account group
(`Group`)."""
def as_dict(self) -> dict:
"""Serializes the ResourceMeta into a dictionary suitable for use as a JSON request body."""
body = {}
if self.resource_type is not None:
body["resourceType"] = self.resource_type
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ResourceMeta into a shallow dictionary of its immediate attributes."""
body = {}
if self.resource_type is not None:
body["resourceType"] = self.resource_type
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ResourceMeta:
"""Deserializes the ResourceMeta from a dictionary."""
return cls(resource_type=d.get("resourceType", None))
@dataclass
class Role:
name: str
"""Role to assign to a principal or a list of principals on a resource."""
def as_dict(self) -> dict:
"""Serializes the Role into a dictionary suitable for use as a JSON request body."""
body = {}
if self.name is not None:
body["name"] = self.name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the Role into a shallow dictionary of its immediate attributes."""
body = {}
if self.name is not None:
body["name"] = self.name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> Role:
"""Deserializes the Role from a dictionary."""
return cls(name=d.get("name", None))
@dataclass
class RuleSetResponse:
name: str
"""Name of the rule set."""
etag: str
"""Identifies the version of the rule set returned. Etag used for versioning. The response is at
least as fresh as the eTag provided. Etag is used for optimistic concurrency control as a way to
help prevent simultaneous updates of a rule set from overwriting each other. It is strongly
suggested that systems make use of the etag in the read -> modify -> write pattern to perform
rule set updates in order to avoid race conditions that is get an etag from a GET rule set
request, and pass it with the PUT update request to identify the rule set version you are
updating."""
grant_rules: Optional[List[GrantRule]] = None
def as_dict(self) -> dict:
"""Serializes the RuleSetResponse into a dictionary suitable for use as a JSON request body."""
body = {}
if self.etag is not None:
body["etag"] = self.etag
if self.grant_rules:
body["grant_rules"] = [v.as_dict() for v in self.grant_rules]
if self.name is not None:
body["name"] = self.name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the RuleSetResponse into a shallow dictionary of its immediate attributes."""
body = {}
if self.etag is not None:
body["etag"] = self.etag
if self.grant_rules:
body["grant_rules"] = self.grant_rules
if self.name is not None:
body["name"] = self.name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> RuleSetResponse:
"""Deserializes the RuleSetResponse from a dictionary."""
return cls(
etag=d.get("etag", None), grant_rules=_repeated_dict(d, "grant_rules", GrantRule), name=d.get("name", None)
)
@dataclass
class RuleSetUpdateRequest:
name: str
"""Name of the rule set."""
etag: str
"""Identifies the version of the rule set returned. Etag used for versioning. The response is at
least as fresh as the eTag provided. Etag is used for optimistic concurrency control as a way to
help prevent simultaneous updates of a rule set from overwriting each other. It is strongly
suggested that systems make use of the etag in the read -> modify -> write pattern to perform
rule set updates in order to avoid race conditions that is get an etag from a GET rule set
request, and pass it with the PUT update request to identify the rule set version you are
updating."""
grant_rules: Optional[List[GrantRule]] = None
def as_dict(self) -> dict:
"""Serializes the RuleSetUpdateRequest into a dictionary suitable for use as a JSON request body."""
body = {}
if self.etag is not None:
body["etag"] = self.etag
if self.grant_rules:
body["grant_rules"] = [v.as_dict() for v in self.grant_rules]
if self.name is not None:
body["name"] = self.name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the RuleSetUpdateRequest into a shallow dictionary of its immediate attributes."""
body = {}
if self.etag is not None:
body["etag"] = self.etag
if self.grant_rules:
body["grant_rules"] = self.grant_rules
if self.name is not None:
body["name"] = self.name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> RuleSetUpdateRequest:
"""Deserializes the RuleSetUpdateRequest from a dictionary."""
return cls(
etag=d.get("etag", None), grant_rules=_repeated_dict(d, "grant_rules", GrantRule), name=d.get("name", None)
)
@dataclass
class ServicePrincipal:
active: Optional[bool] = None
"""If this user is active"""
application_id: Optional[str] = None
"""UUID relating to the service principal"""
display_name: Optional[str] = None
"""String that represents a concatenation of given and family names."""
entitlements: Optional[List[ComplexValue]] = None
"""Entitlements assigned to the service principal. See [assigning entitlements] for a full list of
supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements"""
external_id: Optional[str] = None
groups: Optional[List[ComplexValue]] = None
id: Optional[str] = None
"""Databricks service principal ID."""
roles: Optional[List[ComplexValue]] = None
"""Corresponds to AWS instance profile/arn role."""
schemas: Optional[List[ServicePrincipalSchema]] = None
"""The schema of the List response."""
def as_dict(self) -> dict:
"""Serializes the ServicePrincipal into a dictionary suitable for use as a JSON request body."""
body = {}
if self.active is not None:
body["active"] = self.active
if self.application_id is not None:
body["applicationId"] = self.application_id
if self.display_name is not None:
body["displayName"] = self.display_name
if self.entitlements:
body["entitlements"] = [v.as_dict() for v in self.entitlements]
if self.external_id is not None:
body["externalId"] = self.external_id
if self.groups:
body["groups"] = [v.as_dict() for v in self.groups]
if self.id is not None:
body["id"] = self.id
if self.roles:
body["roles"] = [v.as_dict() for v in self.roles]
if self.schemas:
body["schemas"] = [v.value for v in self.schemas]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the ServicePrincipal into a shallow dictionary of its immediate attributes."""
body = {}
if self.active is not None:
body["active"] = self.active
if self.application_id is not None:
body["applicationId"] = self.application_id
if self.display_name is not None:
body["displayName"] = self.display_name
if self.entitlements:
body["entitlements"] = self.entitlements
if self.external_id is not None:
body["externalId"] = self.external_id
if self.groups:
body["groups"] = self.groups
if self.id is not None:
body["id"] = self.id
if self.roles:
body["roles"] = self.roles
if self.schemas:
body["schemas"] = self.schemas
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> ServicePrincipal:
"""Deserializes the ServicePrincipal from a dictionary."""
return cls(
active=d.get("active", None),
application_id=d.get("applicationId", None),
display_name=d.get("displayName", None),
entitlements=_repeated_dict(d, "entitlements", ComplexValue),
external_id=d.get("externalId", None),
groups=_repeated_dict(d, "groups", ComplexValue),
id=d.get("id", None),
roles=_repeated_dict(d, "roles", ComplexValue),
schemas=_repeated_enum(d, "schemas", ServicePrincipalSchema),
)
class ServicePrincipalSchema(Enum):
URN_IETF_PARAMS_SCIM_SCHEMAS_CORE_2_0_SERVICE_PRINCIPAL = "urn:ietf:params:scim:schemas:core:2.0:ServicePrincipal"
@dataclass
class User:
active: Optional[bool] = None
"""If this user is active"""
display_name: Optional[str] = None
"""String that represents a concatenation of given and family names. For example `John Smith`. This
field cannot be updated through the Workspace SCIM APIs when [identity federation is enabled].
Use Account SCIM APIs to update `displayName`.
[identity federation is enabled]: https://docs.databricks.com/administration-guide/users-groups/best-practices.html#enable-identity-federation"""
emails: Optional[List[ComplexValue]] = None
"""All the emails associated with the Databricks user."""
entitlements: Optional[List[ComplexValue]] = None
"""Entitlements assigned to the user. See [assigning entitlements] for a full list of supported
values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements"""
external_id: Optional[str] = None
"""External ID is not currently supported. It is reserved for future use."""
groups: Optional[List[ComplexValue]] = None
id: Optional[str] = None
"""Databricks user ID."""
name: Optional[Name] = None
roles: Optional[List[ComplexValue]] = None
"""Corresponds to AWS instance profile/arn role."""
schemas: Optional[List[UserSchema]] = None
"""The schema of the user."""
user_name: Optional[str] = None
"""Email address of the Databricks user."""
def as_dict(self) -> dict:
"""Serializes the User into a dictionary suitable for use as a JSON request body."""
body = {}
if self.active is not None:
body["active"] = self.active
if self.display_name is not None:
body["displayName"] = self.display_name
if self.emails:
body["emails"] = [v.as_dict() for v in self.emails]
if self.entitlements:
body["entitlements"] = [v.as_dict() for v in self.entitlements]
if self.external_id is not None:
body["externalId"] = self.external_id
if self.groups:
body["groups"] = [v.as_dict() for v in self.groups]
if self.id is not None:
body["id"] = self.id
if self.name:
body["name"] = self.name.as_dict()
if self.roles:
body["roles"] = [v.as_dict() for v in self.roles]
if self.schemas:
body["schemas"] = [v.value for v in self.schemas]
if self.user_name is not None:
body["userName"] = self.user_name
return body
def as_shallow_dict(self) -> dict:
"""Serializes the User into a shallow dictionary of its immediate attributes."""
body = {}
if self.active is not None:
body["active"] = self.active
if self.display_name is not None:
body["displayName"] = self.display_name
if self.emails:
body["emails"] = self.emails
if self.entitlements:
body["entitlements"] = self.entitlements
if self.external_id is not None:
body["externalId"] = self.external_id
if self.groups:
body["groups"] = self.groups
if self.id is not None:
body["id"] = self.id
if self.name:
body["name"] = self.name
if self.roles:
body["roles"] = self.roles
if self.schemas:
body["schemas"] = self.schemas
if self.user_name is not None:
body["userName"] = self.user_name
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> User:
"""Deserializes the User from a dictionary."""
return cls(
active=d.get("active", None),
display_name=d.get("displayName", None),
emails=_repeated_dict(d, "emails", ComplexValue),
entitlements=_repeated_dict(d, "entitlements", ComplexValue),
external_id=d.get("externalId", None),
groups=_repeated_dict(d, "groups", ComplexValue),
id=d.get("id", None),
name=_from_dict(d, "name", Name),
roles=_repeated_dict(d, "roles", ComplexValue),
schemas=_repeated_enum(d, "schemas", UserSchema),
user_name=d.get("userName", None),
)
class UserSchema(Enum):
URN_IETF_PARAMS_SCIM_SCHEMAS_CORE_2_0_USER = "urn:ietf:params:scim:schemas:core:2.0:User"
URN_IETF_PARAMS_SCIM_SCHEMAS_EXTENSION_WORKSPACE_2_0_USER = (
"urn:ietf:params:scim:schemas:extension:workspace:2.0:User"
)
class WorkspacePermission(Enum):
ADMIN = "ADMIN"
UNKNOWN = "UNKNOWN"
USER = "USER"
@dataclass
class WorkspacePermissions:
permissions: Optional[List[PermissionOutput]] = None
"""Array of permissions defined for a workspace."""
def as_dict(self) -> dict:
"""Serializes the WorkspacePermissions into a dictionary suitable for use as a JSON request body."""
body = {}
if self.permissions:
body["permissions"] = [v.as_dict() for v in self.permissions]
return body
def as_shallow_dict(self) -> dict:
"""Serializes the WorkspacePermissions into a shallow dictionary of its immediate attributes."""
body = {}
if self.permissions:
body["permissions"] = self.permissions
return body
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> WorkspacePermissions:
"""Deserializes the WorkspacePermissions from a dictionary."""
return cls(permissions=_repeated_dict(d, "permissions", PermissionOutput))
class AccessControlAPI:
"""Rule based Access Control for Databricks Resources."""
def __init__(self, api_client):
self._api = api_client
def check_policy(
self,
actor: Actor,
permission: str,
resource: str,
consistency_token: ConsistencyToken,
authz_identity: RequestAuthzIdentity,
*,
resource_info: Optional[ResourceInfo] = None,
) -> CheckPolicyResponse:
"""Check access policy to a resource.
:param actor: :class:`Actor`
:param permission: str
:param resource: str
Ex: (servicePrincipal/use, accounts/<account-id>/servicePrincipals/<sp-id>) Ex:
(servicePrincipal.ruleSet/update, accounts/<account-id>/servicePrincipals/<sp-id>/ruleSets/default)
:param consistency_token: :class:`ConsistencyToken`
:param authz_identity: :class:`RequestAuthzIdentity`
:param resource_info: :class:`ResourceInfo` (optional)
:returns: :class:`CheckPolicyResponse`
"""
query = {}
if actor is not None:
query["actor"] = actor.as_dict()
if authz_identity is not None:
query["authz_identity"] = authz_identity.value
if consistency_token is not None:
query["consistency_token"] = consistency_token.as_dict()
if permission is not None:
query["permission"] = permission
if resource is not None:
query["resource"] = resource
if resource_info is not None:
query["resource_info"] = resource_info.as_dict()
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", "/api/2.0/access-control/check-policy-v2", query=query, headers=headers)
return CheckPolicyResponse.from_dict(res)
class AccountAccessControlAPI:
"""These APIs manage access rules on resources in an account. Currently, only grant rules are supported. A
grant rule specifies a role assigned to a set of principals. A list of rules attached to a resource is
called a rule set."""
def __init__(self, api_client):
self._api = api_client
def get_assignable_roles_for_resource(self, resource: str) -> GetAssignableRolesForResourceResponse:
"""Gets all the roles that can be granted on an account level resource. A role is grantable if the rule
set on the resource can contain an access rule of the role.
:param resource: str
The resource name for which assignable roles will be listed.
Examples | Summary :--- | :--- `resource=accounts/<ACCOUNT_ID>` | A resource name for the account.
`resource=accounts/<ACCOUNT_ID>/groups/<GROUP_ID>` | A resource name for the group.
`resource=accounts/<ACCOUNT_ID>/servicePrincipals/<SP_ID>` | A resource name for the service
principal. `resource=accounts/<ACCOUNT_ID>/tagPolicies/<TAG_POLICY_ID>` | A resource name for the
tag policy.
:returns: :class:`GetAssignableRolesForResourceResponse`
"""
query = {}
if resource is not None:
query["resource"] = resource
headers = {
"Accept": "application/json",
}
res = self._api.do(
"GET",
f"/api/2.0/preview/accounts/{self._api.account_id}/access-control/assignable-roles",
query=query,
headers=headers,
)
return GetAssignableRolesForResourceResponse.from_dict(res)
def get_rule_set(self, name: str, etag: str) -> RuleSetResponse:
"""Get a rule set by its name. A rule set is always attached to a resource and contains a list of access
rules on the said resource. Currently only a default rule set for each resource is supported.
:param name: str
The ruleset name associated with the request.
Examples | Summary :--- | :--- `name=accounts/<ACCOUNT_ID>/ruleSets/default` | A name for a rule set
on the account. `name=accounts/<ACCOUNT_ID>/groups/<GROUP_ID>/ruleSets/default` | A name for a rule
set on the group.
`name=accounts/<ACCOUNT_ID>/servicePrincipals/<SERVICE_PRINCIPAL_APPLICATION_ID>/ruleSets/default` |
A name for a rule set on the service principal.
`name=accounts/<ACCOUNT_ID>/tagPolicies/<TAG_POLICY_ID>/ruleSets/default` | A name for a rule set on
the tag policy.
:param etag: str
Etag used for versioning. The response is at least as fresh as the eTag provided. Etag is used for
optimistic concurrency control as a way to help prevent simultaneous updates of a rule set from
overwriting each other. It is strongly suggested that systems make use of the etag in the read ->
modify -> write pattern to perform rule set updates in order to avoid race conditions that is get an
etag from a GET rule set request, and pass it with the PUT update request to identify the rule set
version you are updating.
Examples | Summary :--- | :--- `etag=` | An empty etag can only be used in GET to indicate no
freshness requirements. `etag=RENUAAABhSweA4NvVmmUYdiU717H3Tgy0UJdor3gE4a+mq/oj9NjAf8ZsQ==` | An
etag encoded a specific version of the rule set to get or to be updated.
:returns: :class:`RuleSetResponse`
"""
query = {}
if etag is not None:
query["etag"] = etag
if name is not None:
query["name"] = name
headers = {
"Accept": "application/json",
}
res = self._api.do(
"GET",
f"/api/2.0/preview/accounts/{self._api.account_id}/access-control/rule-sets",
query=query,
headers=headers,
)
return RuleSetResponse.from_dict(res)
def update_rule_set(self, name: str, rule_set: RuleSetUpdateRequest) -> RuleSetResponse:
"""Replace the rules of a rule set. First, use get to read the current version of the rule set before
modifying it. This pattern helps prevent conflicts between concurrent updates.
:param name: str
Name of the rule set.
:param rule_set: :class:`RuleSetUpdateRequest`
:returns: :class:`RuleSetResponse`
"""
body = {}
if name is not None:
body["name"] = name
if rule_set is not None:
body["rule_set"] = rule_set.as_dict()
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do(
"PUT",
f"/api/2.0/preview/accounts/{self._api.account_id}/access-control/rule-sets",
body=body,
headers=headers,
)
return RuleSetResponse.from_dict(res)
class AccountAccessControlProxyAPI:
"""These APIs manage access rules on resources in an account. Currently, only grant rules are supported. A
grant rule specifies a role assigned to a set of principals. A list of rules attached to a resource is
called a rule set. A workspace must belong to an account for these APIs to work"""
def __init__(self, api_client):
self._api = api_client
def get_assignable_roles_for_resource(self, resource: str) -> GetAssignableRolesForResourceResponse:
"""Gets all the roles that can be granted on an account level resource. A role is grantable if the rule
set on the resource can contain an access rule of the role.
:param resource: str
The resource name for which assignable roles will be listed.
Examples | Summary :--- | :--- `resource=accounts/<ACCOUNT_ID>` | A resource name for the account.
`resource=accounts/<ACCOUNT_ID>/groups/<GROUP_ID>` | A resource name for the group.
`resource=accounts/<ACCOUNT_ID>/servicePrincipals/<SP_ID>` | A resource name for the service
principal. `resource=accounts/<ACCOUNT_ID>/tagPolicies/<TAG_POLICY_ID>` | A resource name for the
tag policy.
:returns: :class:`GetAssignableRolesForResourceResponse`
"""
query = {}
if resource is not None:
query["resource"] = resource
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do(
"GET", "/api/2.0/preview/accounts/access-control/assignable-roles", query=query, headers=headers
)
return GetAssignableRolesForResourceResponse.from_dict(res)
def get_rule_set(self, name: str, etag: str) -> RuleSetResponse:
"""Get a rule set by its name. A rule set is always attached to a resource and contains a list of access
rules on the said resource. Currently only a default rule set for each resource is supported.
:param name: str
The ruleset name associated with the request.
Examples | Summary :--- | :--- `name=accounts/<ACCOUNT_ID>/ruleSets/default` | A name for a rule set
on the account. `name=accounts/<ACCOUNT_ID>/groups/<GROUP_ID>/ruleSets/default` | A name for a rule
set on the group.
`name=accounts/<ACCOUNT_ID>/servicePrincipals/<SERVICE_PRINCIPAL_APPLICATION_ID>/ruleSets/default` |
A name for a rule set on the service principal.
`name=accounts/<ACCOUNT_ID>/tagPolicies/<TAG_POLICY_ID>/ruleSets/default` | A name for a rule set on
the tag policy.
:param etag: str
Etag used for versioning. The response is at least as fresh as the eTag provided. Etag is used for
optimistic concurrency control as a way to help prevent simultaneous updates of a rule set from
overwriting each other. It is strongly suggested that systems make use of the etag in the read ->
modify -> write pattern to perform rule set updates in order to avoid race conditions that is get an
etag from a GET rule set request, and pass it with the PUT update request to identify the rule set
version you are updating.
Examples | Summary :--- | :--- `etag=` | An empty etag can only be used in GET to indicate no
freshness requirements. `etag=RENUAAABhSweA4NvVmmUYdiU717H3Tgy0UJdor3gE4a+mq/oj9NjAf8ZsQ==` | An
etag encoded a specific version of the rule set to get or to be updated.
:returns: :class:`RuleSetResponse`
"""
query = {}
if etag is not None:
query["etag"] = etag
if name is not None:
query["name"] = name
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", "/api/2.0/preview/accounts/access-control/rule-sets", query=query, headers=headers)
return RuleSetResponse.from_dict(res)
def update_rule_set(self, name: str, rule_set: RuleSetUpdateRequest) -> RuleSetResponse:
"""Replace the rules of a rule set. First, use get to read the current version of the rule set before
modifying it. This pattern helps prevent conflicts between concurrent updates.
:param name: str
Name of the rule set.
:param rule_set: :class:`RuleSetUpdateRequest`
:returns: :class:`RuleSetResponse`
"""
body = {}
if name is not None:
body["name"] = name
if rule_set is not None:
body["rule_set"] = rule_set.as_dict()
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("PUT", "/api/2.0/preview/accounts/access-control/rule-sets", body=body, headers=headers)
return RuleSetResponse.from_dict(res)
class AccountGroupsV2API:
"""Groups simplify identity management, making it easier to assign access to Databricks account, data, and
other securable objects.
It is best practice to assign access to workspaces and access-control policies in Unity Catalog to groups,
instead of to users individually. All Databricks account identities can be assigned as members of groups,
and members inherit permissions that are assigned to their group."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
display_name: Optional[str] = None,
external_id: Optional[str] = None,
id: Optional[str] = None,
members: Optional[List[ComplexValue]] = None,
meta: Optional[ResourceMeta] = None,
roles: Optional[List[ComplexValue]] = None,
) -> AccountGroup:
"""Creates a group in the Databricks account with a unique name, using the supplied group details.
:param display_name: str (optional)
String that represents a human-readable group name
:param external_id: str (optional)
:param id: str (optional)
Databricks group ID
:param members: List[:class:`ComplexValue`] (optional)
:param meta: :class:`ResourceMeta` (optional)
Container for the group identifier. Workspace local versus account.
:param roles: List[:class:`ComplexValue`] (optional)
Indicates if the group has the admin role.
:returns: :class:`AccountGroup`
"""
body = {}
if display_name is not None:
body["displayName"] = display_name
if external_id is not None:
body["externalId"] = external_id
if id is not None:
body["id"] = id
if members is not None:
body["members"] = [v.as_dict() for v in members]
if meta is not None:
body["meta"] = meta.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do(
"POST", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups", body=body, headers=headers
)
return AccountGroup.from_dict(res)
def delete(self, id: str):
"""Deletes a group from the Databricks account.
:param id: str
Unique ID for a group in the Databricks account.
"""
headers = {}
self._api.do("DELETE", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", headers=headers)
def get(self, id: str) -> AccountGroup:
"""Gets the information for a specific group in the Databricks account.
:param id: str
Unique ID for a group in the Databricks account.
:returns: :class:`AccountGroup`
"""
headers = {
"Accept": "application/json",
}
res = self._api.do("GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", headers=headers)
return AccountGroup.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[AccountGroup]:
"""Gets all details of the groups associated with the Databricks account. As of 08/22/2025, this endpoint
will no longer return members. Instead, members should be retrieved by iterating through `Get group
details`. Existing accounts that rely on this attribute will not be impacted and will continue
receiving member data as before.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page. Default is 10000.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`AccountGroup`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do(
"GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups", query=query, headers=headers
)
if "Resources" in json:
for v in json["Resources"]:
yield AccountGroup.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates the details of a group.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do(
"PATCH", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", body=body, headers=headers
)
def update(
self,
id: str,
*,
display_name: Optional[str] = None,
external_id: Optional[str] = None,
members: Optional[List[ComplexValue]] = None,
meta: Optional[ResourceMeta] = None,
roles: Optional[List[ComplexValue]] = None,
):
"""Updates the details of a group by replacing the entire group entity.
:param id: str
Databricks group ID
:param display_name: str (optional)
String that represents a human-readable group name
:param external_id: str (optional)
:param members: List[:class:`ComplexValue`] (optional)
:param meta: :class:`ResourceMeta` (optional)
Container for the group identifier. Workspace local versus account.
:param roles: List[:class:`ComplexValue`] (optional)
Indicates if the group has the admin role.
"""
body = {}
if display_name is not None:
body["displayName"] = display_name
if external_id is not None:
body["externalId"] = external_id
if members is not None:
body["members"] = [v.as_dict() for v in members]
if meta is not None:
body["meta"] = meta.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
self._api.do("PUT", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", body=body, headers=headers)
class AccountServicePrincipalsV2API:
"""Identities for use with jobs, automated tools, and systems such as scripts, apps, and CI/CD platforms.
Databricks recommends creating service principals to run production jobs or modify production data. If all
processes that act on production data run with service principals, interactive users do not need any
write, delete, or modify privileges in production. This eliminates the risk of a user overwriting
production data by accident."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
active: Optional[bool] = None,
application_id: Optional[str] = None,
display_name: Optional[str] = None,
external_id: Optional[str] = None,
id: Optional[str] = None,
roles: Optional[List[ComplexValue]] = None,
) -> AccountServicePrincipal:
"""Creates a new service principal in the Databricks account.
:param active: bool (optional)
If this user is active
:param application_id: str (optional)
UUID relating to the service principal
:param display_name: str (optional)
String that represents a concatenation of given and family names.
:param external_id: str (optional)
:param id: str (optional)
Databricks service principal ID.
:param roles: List[:class:`ComplexValue`] (optional)
Indicates if the group has the admin role.
:returns: :class:`AccountServicePrincipal`
"""
body = {}
if active is not None:
body["active"] = active
if application_id is not None:
body["applicationId"] = application_id
if display_name is not None:
body["displayName"] = display_name
if external_id is not None:
body["externalId"] = external_id
if id is not None:
body["id"] = id
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do(
"POST", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals", body=body, headers=headers
)
return AccountServicePrincipal.from_dict(res)
def delete(self, id: str):
"""Delete a single service principal in the Databricks account.
:param id: str
Unique ID for a service principal in the Databricks account.
"""
headers = {}
self._api.do(
"DELETE", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}", headers=headers
)
def get(self, id: str) -> AccountServicePrincipal:
"""Gets the details for a single service principal define in the Databricks account.
:param id: str
Unique ID for a service principal in the Databricks account.
:returns: :class:`AccountServicePrincipal`
"""
headers = {
"Accept": "application/json",
}
res = self._api.do(
"GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}", headers=headers
)
return AccountServicePrincipal.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[AccountServicePrincipal]:
"""Gets the set of service principals associated with a Databricks account.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page. Default is 10000.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`AccountServicePrincipal`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do(
"GET",
f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals",
query=query,
headers=headers,
)
if "Resources" in json:
for v in json["Resources"]:
yield AccountServicePrincipal.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates the details of a single service principal in the Databricks account.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
self._api.do(
"PATCH",
f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}",
body=body,
headers=headers,
)
def update(
self,
id: str,
*,
active: Optional[bool] = None,
application_id: Optional[str] = None,
display_name: Optional[str] = None,
external_id: Optional[str] = None,
roles: Optional[List[ComplexValue]] = None,
):
"""Updates the details of a single service principal.
This action replaces the existing service principal with the same name.
:param id: str
Databricks service principal ID.
:param active: bool (optional)
If this user is active
:param application_id: str (optional)
UUID relating to the service principal
:param display_name: str (optional)
String that represents a concatenation of given and family names.
:param external_id: str (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Indicates if the group has the admin role.
"""
body = {}
if active is not None:
body["active"] = active
if application_id is not None:
body["applicationId"] = application_id
if display_name is not None:
body["displayName"] = display_name
if external_id is not None:
body["externalId"] = external_id
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
self._api.do(
"PUT",
f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}",
body=body,
headers=headers,
)
class AccountUsersV2API:
"""User identities recognized by Databricks and represented by email addresses.
Databricks recommends using SCIM provisioning to sync users and groups automatically from your identity
provider to your Databricks account. SCIM streamlines onboarding a new employee or team by using your
identity provider to create users and groups in Databricks account and give them the proper level of
access. When a user leaves your organization or no longer needs access to Databricks account, admins can
terminate the user in your identity provider and that users account will also be removed from
Databricks account. This ensures a consistent offboarding process and prevents unauthorized users from
accessing sensitive data."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
active: Optional[bool] = None,
display_name: Optional[str] = None,
emails: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
id: Optional[str] = None,
name: Optional[Name] = None,
roles: Optional[List[ComplexValue]] = None,
user_name: Optional[str] = None,
) -> AccountUser:
"""Creates a new user in the Databricks account. This new user will also be added to the Databricks
account.
:param active: bool (optional)
If this user is active
:param display_name: str (optional)
String that represents a concatenation of given and family names. For example `John Smith`.
:param emails: List[:class:`ComplexValue`] (optional)
All the emails associated with the Databricks user.
:param external_id: str (optional)
External ID is not currently supported. It is reserved for future use.
:param id: str (optional)
Databricks user ID.
:param name: :class:`Name` (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Indicates if the group has the admin role.
:param user_name: str (optional)
Email address of the Databricks user.
:returns: :class:`AccountUser`
"""
body = {}
if active is not None:
body["active"] = active
if display_name is not None:
body["displayName"] = display_name
if emails is not None:
body["emails"] = [v.as_dict() for v in emails]
if external_id is not None:
body["externalId"] = external_id
if id is not None:
body["id"] = id
if name is not None:
body["name"] = name.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if user_name is not None:
body["userName"] = user_name
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do(
"POST", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users", body=body, headers=headers
)
return AccountUser.from_dict(res)
def delete(self, id: str):
"""Deletes a user. Deleting a user from a Databricks account also removes objects associated with the
user.
:param id: str
Unique ID for a user in the Databricks account.
"""
headers = {}
self._api.do("DELETE", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", headers=headers)
def get(
self,
id: str,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[GetSortOrder] = None,
start_index: Optional[int] = None,
) -> AccountUser:
"""Gets information for a specific user in Databricks account.
:param id: str
Unique ID for a user in the Databricks account.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page. Default is 10000.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
`name.givenName`, and `emails`.
:param sort_order: :class:`GetSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: :class:`AccountUser`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
res = self._api.do(
"GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", query=query, headers=headers
)
return AccountUser.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[AccountUser]:
"""Gets details for all the users associated with a Databricks account.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page. Default is 10000.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
`name.givenName`, and `emails`.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`AccountUser`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do(
"GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users", query=query, headers=headers
)
if "Resources" in json:
for v in json["Resources"]:
yield AccountUser.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates a user resource by applying the supplied operations on specific user attributes.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
self._api.do(
"PATCH", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", body=body, headers=headers
)
def update(
self,
id: str,
*,
active: Optional[bool] = None,
display_name: Optional[str] = None,
emails: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
name: Optional[Name] = None,
roles: Optional[List[ComplexValue]] = None,
user_name: Optional[str] = None,
):
"""Replaces a user's information with the data supplied in request.
:param id: str
Databricks user ID.
:param active: bool (optional)
If this user is active
:param display_name: str (optional)
String that represents a concatenation of given and family names. For example `John Smith`.
:param emails: List[:class:`ComplexValue`] (optional)
All the emails associated with the Databricks user.
:param external_id: str (optional)
External ID is not currently supported. It is reserved for future use.
:param name: :class:`Name` (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Indicates if the group has the admin role.
:param user_name: str (optional)
Email address of the Databricks user.
"""
body = {}
if active is not None:
body["active"] = active
if display_name is not None:
body["displayName"] = display_name
if emails is not None:
body["emails"] = [v.as_dict() for v in emails]
if external_id is not None:
body["externalId"] = external_id
if name is not None:
body["name"] = name.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if user_name is not None:
body["userName"] = user_name
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
self._api.do("PUT", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", body=body, headers=headers)
class CurrentUserAPI:
"""This API allows retrieving information about currently authenticated user or service principal."""
def __init__(self, api_client):
self._api = api_client
def me(self) -> User:
"""Get details about the current method caller's identity.
:returns: :class:`User`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", "/api/2.0/preview/scim/v2/Me", headers=headers)
return User.from_dict(res)
class GroupsV2API:
"""Groups simplify identity management, making it easier to assign access to Databricks workspace, data, and
other securable objects.
It is best practice to assign access to workspaces and access-control policies in Unity Catalog to groups,
instead of to users individually. All Databricks workspace identities can be assigned as members of
groups, and members inherit permissions that are assigned to their group."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
id: Optional[str] = None,
members: Optional[List[ComplexValue]] = None,
meta: Optional[ResourceMeta] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[GroupSchema]] = None,
) -> Group:
"""Creates a group in the Databricks workspace with a unique name, using the supplied group details.
:param display_name: str (optional)
String that represents a human-readable group name
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param id: str (optional)
Databricks group ID
:param members: List[:class:`ComplexValue`] (optional)
:param meta: :class:`ResourceMeta` (optional)
Container for the group identifier. Workspace local versus account.
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`GroupSchema`] (optional)
The schema of the group.
:returns: :class:`Group`
"""
body = {}
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if id is not None:
body["id"] = id
if members is not None:
body["members"] = [v.as_dict() for v in members]
if meta is not None:
body["meta"] = meta.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("POST", "/api/2.0/preview/scim/v2/Groups", body=body, headers=headers)
return Group.from_dict(res)
def delete(self, id: str):
"""Deletes a group from the Databricks workspace.
:param id: str
Unique ID for a group in the Databricks workspace.
"""
headers = {}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("DELETE", f"/api/2.0/preview/scim/v2/Groups/{id}", headers=headers)
def get(self, id: str) -> Group:
"""Gets the information for a specific group in the Databricks workspace.
:param id: str
Unique ID for a group in the Databricks workspace.
:returns: :class:`Group`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", f"/api/2.0/preview/scim/v2/Groups/{id}", headers=headers)
return Group.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[Group]:
"""Gets all details of the groups associated with the Databricks workspace.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`Group`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do("GET", "/api/2.0/preview/scim/v2/Groups", query=query, headers=headers)
if "Resources" in json:
for v in json["Resources"]:
yield Group.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates the details of a group.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("PATCH", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
def update(
self,
id: str,
*,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
members: Optional[List[ComplexValue]] = None,
meta: Optional[ResourceMeta] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[GroupSchema]] = None,
):
"""Updates the details of a group by replacing the entire group entity.
:param id: str
Databricks group ID
:param display_name: str (optional)
String that represents a human-readable group name
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param members: List[:class:`ComplexValue`] (optional)
:param meta: :class:`ResourceMeta` (optional)
Container for the group identifier. Workspace local versus account.
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`GroupSchema`] (optional)
The schema of the group.
"""
body = {}
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if members is not None:
body["members"] = [v.as_dict() for v in members]
if meta is not None:
body["meta"] = meta.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("PUT", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
class PermissionMigrationAPI:
"""APIs for migrating acl permissions, used only by the ucx tool: https://github.com/databrickslabs/ucx"""
def __init__(self, api_client):
self._api = api_client
def migrate_permissions(
self,
workspace_id: int,
from_workspace_group_name: str,
to_account_group_name: str,
*,
size: Optional[int] = None,
) -> MigratePermissionsResponse:
"""Migrate Permissions.
:param workspace_id: int
WorkspaceId of the associated workspace where the permission migration will occur.
:param from_workspace_group_name: str
The name of the workspace group that permissions will be migrated from.
:param to_account_group_name: str
The name of the account group that permissions will be migrated to.
:param size: int (optional)
The maximum number of permissions that will be migrated.
:returns: :class:`MigratePermissionsResponse`
"""
body = {}
if from_workspace_group_name is not None:
body["from_workspace_group_name"] = from_workspace_group_name
if size is not None:
body["size"] = size
if to_account_group_name is not None:
body["to_account_group_name"] = to_account_group_name
if workspace_id is not None:
body["workspace_id"] = workspace_id
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("POST", "/api/2.0/permissionmigration", body=body, headers=headers)
return MigratePermissionsResponse.from_dict(res)
class PermissionsAPI:
"""Permissions API are used to create read, write, edit, update and manage access for various users on
different objects and endpoints. * **[Apps permissions](:service:apps)** — Manage which users can manage
or use apps. * **[Cluster permissions](:service:clusters)** — Manage which users can manage, restart, or
attach to clusters. * **[Cluster policy permissions](:service:clusterpolicies)** — Manage which users
can use cluster policies. * **[Delta Live Tables pipeline permissions](:service:pipelines)** — Manage
which users can view, manage, run, cancel, or own a Delta Live Tables pipeline. * **[Job
permissions](:service:jobs)** — Manage which users can view, manage, trigger, cancel, or own a job. *
**[MLflow experiment permissions](:service:experiments)** — Manage which users can read, edit, or manage
MLflow experiments. * **[MLflow registered model permissions](:service:modelregistry)** — Manage which
users can read, edit, or manage MLflow registered models. * **[Instance Pool
permissions](:service:instancepools)** — Manage which users can manage or attach to pools. * **[Repo
permissions](repos)** — Manage which users can read, run, edit, or manage a repo. * **[Serving endpoint
permissions](:service:servingendpoints)** — Manage which users can view, query, or manage a serving
endpoint. * **[SQL warehouse permissions](:service:warehouses)** — Manage which users can use or manage
SQL warehouses. * **[Token permissions](:service:tokenmanagement)** — Manage which users can create or
use tokens. * **[Workspace object permissions](:service:workspace)** — Manage which users can read, run,
edit, or manage alerts, dbsql-dashboards, directories, files, notebooks and queries. For the mapping of
the required permissions for specific actions or abilities and other important information, see [Access
Control]. Note that to manage access control on service principals, use **[Account Access Control
Proxy](:service:accountaccesscontrolproxy)**.
[Access Control]: https://docs.databricks.com/security/auth-authz/access-control/index.html"""
def __init__(self, api_client):
self._api = api_client
def get(self, request_object_type: str, request_object_id: str) -> ObjectPermissions:
"""Gets the permissions of an object. Objects can inherit permissions from their parent objects or root
object.
:param request_object_type: str
The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files, genie,
instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
warehouses.
:param request_object_id: str
The id of the request object.
:returns: :class:`ObjectPermissions`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", f"/api/2.0/permissions/{request_object_type}/{request_object_id}", headers=headers)
return ObjectPermissions.from_dict(res)
def get_permission_levels(self, request_object_type: str, request_object_id: str) -> GetPermissionLevelsResponse:
"""Gets the permission levels that a user can have on an object.
:param request_object_type: str
The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files, genie,
instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
warehouses.
:param request_object_id: str
:returns: :class:`GetPermissionLevelsResponse`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do(
"GET", f"/api/2.0/permissions/{request_object_type}/{request_object_id}/permissionLevels", headers=headers
)
return GetPermissionLevelsResponse.from_dict(res)
def set(
self,
request_object_type: str,
request_object_id: str,
*,
access_control_list: Optional[List[AccessControlRequest]] = None,
) -> ObjectPermissions:
"""Sets permissions on an object, replacing existing permissions if they exist. Deletes all direct
permissions if none are specified. Objects can inherit permissions from their parent objects or root
object.
:param request_object_type: str
The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files, genie,
instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
warehouses.
:param request_object_id: str
The id of the request object.
:param access_control_list: List[:class:`AccessControlRequest`] (optional)
:returns: :class:`ObjectPermissions`
"""
body = {}
if access_control_list is not None:
body["access_control_list"] = [v.as_dict() for v in access_control_list]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do(
"PUT", f"/api/2.0/permissions/{request_object_type}/{request_object_id}", body=body, headers=headers
)
return ObjectPermissions.from_dict(res)
def update(
self,
request_object_type: str,
request_object_id: str,
*,
access_control_list: Optional[List[AccessControlRequest]] = None,
) -> ObjectPermissions:
"""Updates the permissions on an object. Objects can inherit permissions from their parent objects or
root object.
:param request_object_type: str
The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files, genie,
instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
warehouses.
:param request_object_id: str
The id of the request object.
:param access_control_list: List[:class:`AccessControlRequest`] (optional)
:returns: :class:`ObjectPermissions`
"""
body = {}
if access_control_list is not None:
body["access_control_list"] = [v.as_dict() for v in access_control_list]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do(
"PATCH", f"/api/2.0/permissions/{request_object_type}/{request_object_id}", body=body, headers=headers
)
return ObjectPermissions.from_dict(res)
class ServicePrincipalsV2API:
"""Identities for use with jobs, automated tools, and systems such as scripts, apps, and CI/CD platforms.
Databricks recommends creating service principals to run production jobs or modify production data. If all
processes that act on production data run with service principals, interactive users do not need any
write, delete, or modify privileges in production. This eliminates the risk of a user overwriting
production data by accident."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
active: Optional[bool] = None,
application_id: Optional[str] = None,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
id: Optional[str] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[ServicePrincipalSchema]] = None,
) -> ServicePrincipal:
"""Creates a new service principal in the Databricks workspace.
:param active: bool (optional)
If this user is active
:param application_id: str (optional)
UUID relating to the service principal
:param display_name: str (optional)
String that represents a concatenation of given and family names.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the service principal. See [assigning entitlements] for a full list of
supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param id: str (optional)
Databricks service principal ID.
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`ServicePrincipalSchema`] (optional)
The schema of the List response.
:returns: :class:`ServicePrincipal`
"""
body = {}
if active is not None:
body["active"] = active
if application_id is not None:
body["applicationId"] = application_id
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if id is not None:
body["id"] = id
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("POST", "/api/2.0/preview/scim/v2/ServicePrincipals", body=body, headers=headers)
return ServicePrincipal.from_dict(res)
def delete(self, id: str):
"""Delete a single service principal in the Databricks workspace.
:param id: str
Unique ID for a service principal in the Databricks workspace.
"""
headers = {}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("DELETE", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", headers=headers)
def get(self, id: str) -> ServicePrincipal:
"""Gets the details for a single service principal define in the Databricks workspace.
:param id: str
Unique ID for a service principal in the Databricks workspace.
:returns: :class:`ServicePrincipal`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", headers=headers)
return ServicePrincipal.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[ServicePrincipal]:
"""Gets the set of service principals associated with a Databricks workspace.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`ServicePrincipal`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do("GET", "/api/2.0/preview/scim/v2/ServicePrincipals", query=query, headers=headers)
if "Resources" in json:
for v in json["Resources"]:
yield ServicePrincipal.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates the details of a single service principal in the Databricks workspace.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("PATCH", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", body=body, headers=headers)
def update(
self,
id: str,
*,
active: Optional[bool] = None,
application_id: Optional[str] = None,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[ServicePrincipalSchema]] = None,
):
"""Updates the details of a single service principal.
This action replaces the existing service principal with the same name.
:param id: str
Databricks service principal ID.
:param active: bool (optional)
If this user is active
:param application_id: str (optional)
UUID relating to the service principal
:param display_name: str (optional)
String that represents a concatenation of given and family names.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the service principal. See [assigning entitlements] for a full list of
supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`ServicePrincipalSchema`] (optional)
The schema of the List response.
"""
body = {}
if active is not None:
body["active"] = active
if application_id is not None:
body["applicationId"] = application_id
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("PUT", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", body=body, headers=headers)
class UsersV2API:
"""User identities recognized by Databricks and represented by email addresses.
Databricks recommends using SCIM provisioning to sync users and groups automatically from your identity
provider to your Databricks workspace. SCIM streamlines onboarding a new employee or team by using your
identity provider to create users and groups in Databricks workspace and give them the proper level of
access. When a user leaves your organization or no longer needs access to Databricks workspace, admins can
terminate the user in your identity provider and that users account will also be removed from
Databricks workspace. This ensures a consistent offboarding process and prevents unauthorized users from
accessing sensitive data."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
active: Optional[bool] = None,
display_name: Optional[str] = None,
emails: Optional[List[ComplexValue]] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
id: Optional[str] = None,
name: Optional[Name] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[UserSchema]] = None,
user_name: Optional[str] = None,
) -> User:
"""Creates a new user in the Databricks workspace. This new user will also be added to the Databricks
account.
:param active: bool (optional)
If this user is active
:param display_name: str (optional)
String that represents a concatenation of given and family names. For example `John Smith`. This
field cannot be updated through the Workspace SCIM APIs when [identity federation is enabled]. Use
Account SCIM APIs to update `displayName`.
[identity federation is enabled]: https://docs.databricks.com/administration-guide/users-groups/best-practices.html#enable-identity-federation
:param emails: List[:class:`ComplexValue`] (optional)
All the emails associated with the Databricks user.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the user. See [assigning entitlements] for a full list of supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
External ID is not currently supported. It is reserved for future use.
:param groups: List[:class:`ComplexValue`] (optional)
:param id: str (optional)
Databricks user ID.
:param name: :class:`Name` (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`UserSchema`] (optional)
The schema of the user.
:param user_name: str (optional)
Email address of the Databricks user.
:returns: :class:`User`
"""
body = {}
if active is not None:
body["active"] = active
if display_name is not None:
body["displayName"] = display_name
if emails is not None:
body["emails"] = [v.as_dict() for v in emails]
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if id is not None:
body["id"] = id
if name is not None:
body["name"] = name.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
if user_name is not None:
body["userName"] = user_name
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("POST", "/api/2.0/preview/scim/v2/Users", body=body, headers=headers)
return User.from_dict(res)
def delete(self, id: str):
"""Deletes a user. Deleting a user from a Databricks workspace also removes objects associated with the
user.
:param id: str
Unique ID for a user in the Databricks workspace.
"""
headers = {}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("DELETE", f"/api/2.0/preview/scim/v2/Users/{id}", headers=headers)
def get(
self,
id: str,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[GetSortOrder] = None,
start_index: Optional[int] = None,
) -> User:
"""Gets information for a specific user in Databricks workspace.
:param id: str
Unique ID for a user in the Databricks workspace.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
`name.givenName`, and `emails`.
:param sort_order: :class:`GetSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: :class:`User`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", f"/api/2.0/preview/scim/v2/Users/{id}", query=query, headers=headers)
return User.from_dict(res)
def get_permission_levels(self) -> GetPasswordPermissionLevelsResponse:
"""Gets the permission levels that a user can have on an object.
:returns: :class:`GetPasswordPermissionLevelsResponse`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", "/api/2.0/permissions/authorization/passwords/permissionLevels", headers=headers)
return GetPasswordPermissionLevelsResponse.from_dict(res)
def get_permissions(self) -> PasswordPermissions:
"""Gets the permissions of all passwords. Passwords can inherit permissions from their root object.
:returns: :class:`PasswordPermissions`
"""
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("GET", "/api/2.0/permissions/authorization/passwords", headers=headers)
return PasswordPermissions.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[User]:
"""Gets details for all the users associated with a Databricks workspace.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
`name.givenName`, and `emails`.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`User`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do("GET", "/api/2.0/preview/scim/v2/Users", query=query, headers=headers)
if "Resources" in json:
for v in json["Resources"]:
yield User.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates a user resource by applying the supplied operations on specific user attributes.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("PATCH", f"/api/2.0/preview/scim/v2/Users/{id}", body=body, headers=headers)
def set_permissions(
self, *, access_control_list: Optional[List[PasswordAccessControlRequest]] = None
) -> PasswordPermissions:
"""Sets permissions on an object, replacing existing permissions if they exist. Deletes all direct
permissions if none are specified. Objects can inherit permissions from their root object.
:param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional)
:returns: :class:`PasswordPermissions`
"""
body = {}
if access_control_list is not None:
body["access_control_list"] = [v.as_dict() for v in access_control_list]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("PUT", "/api/2.0/permissions/authorization/passwords", body=body, headers=headers)
return PasswordPermissions.from_dict(res)
def update(
self,
id: str,
*,
active: Optional[bool] = None,
display_name: Optional[str] = None,
emails: Optional[List[ComplexValue]] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
name: Optional[Name] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[UserSchema]] = None,
user_name: Optional[str] = None,
):
"""Replaces a user's information with the data supplied in request.
:param id: str
Databricks user ID.
:param active: bool (optional)
If this user is active
:param display_name: str (optional)
String that represents a concatenation of given and family names. For example `John Smith`. This
field cannot be updated through the Workspace SCIM APIs when [identity federation is enabled]. Use
Account SCIM APIs to update `displayName`.
[identity federation is enabled]: https://docs.databricks.com/administration-guide/users-groups/best-practices.html#enable-identity-federation
:param emails: List[:class:`ComplexValue`] (optional)
All the emails associated with the Databricks user.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the user. See [assigning entitlements] for a full list of supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
External ID is not currently supported. It is reserved for future use.
:param groups: List[:class:`ComplexValue`] (optional)
:param name: :class:`Name` (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`UserSchema`] (optional)
The schema of the user.
:param user_name: str (optional)
Email address of the Databricks user.
"""
body = {}
if active is not None:
body["active"] = active
if display_name is not None:
body["displayName"] = display_name
if emails is not None:
body["emails"] = [v.as_dict() for v in emails]
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if name is not None:
body["name"] = name.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
if user_name is not None:
body["userName"] = user_name
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
self._api.do("PUT", f"/api/2.0/preview/scim/v2/Users/{id}", body=body, headers=headers)
def update_permissions(
self, *, access_control_list: Optional[List[PasswordAccessControlRequest]] = None
) -> PasswordPermissions:
"""Updates the permissions on all passwords. Passwords can inherit permissions from their root object.
:param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional)
:returns: :class:`PasswordPermissions`
"""
body = {}
if access_control_list is not None:
body["access_control_list"] = [v.as_dict() for v in access_control_list]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
cfg = self._api._cfg
if cfg.host_type == HostType.UNIFIED and cfg.workspace_id:
headers["X-Databricks-Org-Id"] = cfg.workspace_id
res = self._api.do("PATCH", "/api/2.0/permissions/authorization/passwords", body=body, headers=headers)
return PasswordPermissions.from_dict(res)
class WorkspaceAssignmentAPI:
"""The Workspace Permission Assignment API allows you to manage workspace permissions for principals in your
account."""
def __init__(self, api_client):
self._api = api_client
def delete(self, workspace_id: int, principal_id: int):
"""Deletes the workspace permissions assignment in a given account and workspace for the specified
principal.
:param workspace_id: int
The workspace ID for the account.
:param principal_id: int
The ID of the user, service principal, or group.
"""
headers = {
"Accept": "application/json",
}
self._api.do(
"DELETE",
f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments/principals/{principal_id}",
headers=headers,
)
def get(self, workspace_id: int) -> WorkspacePermissions:
"""Get an array of workspace permissions for the specified account and workspace.
:param workspace_id: int
The workspace ID.
:returns: :class:`WorkspacePermissions`
"""
headers = {
"Accept": "application/json",
}
res = self._api.do(
"GET",
f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments/permissions",
headers=headers,
)
return WorkspacePermissions.from_dict(res)
def list(self, workspace_id: int) -> Iterator[PermissionAssignment]:
"""Get the permission assignments for the specified Databricks account and Databricks workspace.
:param workspace_id: int
The workspace ID for the account.
:returns: Iterator over :class:`PermissionAssignment`
"""
headers = {
"Accept": "application/json",
}
json = self._api.do(
"GET",
f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments",
headers=headers,
)
parsed = PermissionAssignments.from_dict(json).permission_assignments
return parsed if parsed is not None else []
def update(
self, workspace_id: int, principal_id: int, *, permissions: Optional[List[WorkspacePermission]] = None
) -> PermissionAssignment:
"""Creates or updates the workspace permissions assignment in a given account and workspace for the
specified principal.
:param workspace_id: int
The workspace ID.
:param principal_id: int
The ID of the user, service principal, or group.
:param permissions: List[:class:`WorkspacePermission`] (optional)
Array of permissions assignments to update on the workspace. Valid values are "USER" and "ADMIN"
(case-sensitive). If both "USER" and "ADMIN" are provided, "ADMIN" takes precedence. Other values
will be ignored. Note that excluding this field, or providing unsupported values, will have the same
effect as providing an empty list, which will result in the deletion of all permissions for the
principal.
:returns: :class:`PermissionAssignment`
"""
body = {}
if permissions is not None:
body["permissions"] = [v.value for v in permissions]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do(
"PUT",
f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments/principals/{principal_id}",
body=body,
headers=headers,
)
return PermissionAssignment.from_dict(res)
class AccountGroupsAPI:
"""Groups simplify identity management, making it easier to assign access to Databricks account, data, and
other securable objects.
It is best practice to assign access to workspaces and access-control policies in Unity Catalog to groups,
instead of to users individually. All Databricks account identities can be assigned as members of groups,
and members inherit permissions that are assigned to their group."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
id: Optional[str] = None,
members: Optional[List[ComplexValue]] = None,
meta: Optional[ResourceMeta] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[GroupSchema]] = None,
) -> Group:
"""Creates a group in the Databricks account with a unique name, using the supplied group details.
:param display_name: str (optional)
String that represents a human-readable group name
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param id: str (optional)
Databricks group ID
:param members: List[:class:`ComplexValue`] (optional)
:param meta: :class:`ResourceMeta` (optional)
Container for the group identifier. Workspace local versus account.
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`GroupSchema`] (optional)
The schema of the group.
:returns: :class:`Group`
"""
body = {}
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if id is not None:
body["id"] = id
if members is not None:
body["members"] = [v.as_dict() for v in members]
if meta is not None:
body["meta"] = meta.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do(
"POST", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups", body=body, headers=headers
)
return Group.from_dict(res)
def delete(self, id: str):
"""Deletes a group from the Databricks account.
:param id: str
Unique ID for a group in the Databricks account.
"""
headers = {}
self._api.do("DELETE", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", headers=headers)
def get(self, id: str) -> Group:
"""Gets the information for a specific group in the Databricks account.
:param id: str
Unique ID for a group in the Databricks account.
:returns: :class:`Group`
"""
headers = {
"Accept": "application/json",
}
res = self._api.do("GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", headers=headers)
return Group.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[Group]:
"""Gets all details of the groups associated with the Databricks account.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page. Default is 10000.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`Group`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
# deduplicate items that may have been added during iteration
seen = set()
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do(
"GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups", query=query, headers=headers
)
if "Resources" in json:
for v in json["Resources"]:
i = v["id"]
if i in seen:
continue
seen.add(i)
yield Group.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates the details of a group.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do(
"PATCH", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", body=body, headers=headers
)
def update(
self,
id: str,
*,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
members: Optional[List[ComplexValue]] = None,
meta: Optional[ResourceMeta] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[GroupSchema]] = None,
):
"""Updates the details of a group by replacing the entire group entity.
:param id: str
Databricks group ID
:param display_name: str (optional)
String that represents a human-readable group name
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param members: List[:class:`ComplexValue`] (optional)
:param meta: :class:`ResourceMeta` (optional)
Container for the group identifier. Workspace local versus account.
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`GroupSchema`] (optional)
The schema of the group.
"""
body = {}
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if members is not None:
body["members"] = [v.as_dict() for v in members]
if meta is not None:
body["meta"] = meta.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do("PUT", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", body=body, headers=headers)
class AccountServicePrincipalsAPI:
"""Identities for use with jobs, automated tools, and systems such as scripts, apps, and CI/CD platforms.
Databricks recommends creating service principals to run production jobs or modify production data. If all
processes that act on production data run with service principals, interactive users do not need any
write, delete, or modify privileges in production. This eliminates the risk of a user overwriting
production data by accident."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
active: Optional[bool] = None,
application_id: Optional[str] = None,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
id: Optional[str] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[ServicePrincipalSchema]] = None,
) -> ServicePrincipal:
"""Creates a new service principal in the Databricks account.
:param active: bool (optional)
If this user is active
:param application_id: str (optional)
UUID relating to the service principal
:param display_name: str (optional)
String that represents a concatenation of given and family names.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the service principal. See [assigning entitlements] for a full list of
supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param id: str (optional)
Databricks service principal ID.
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`ServicePrincipalSchema`] (optional)
The schema of the List response.
:returns: :class:`ServicePrincipal`
"""
body = {}
if active is not None:
body["active"] = active
if application_id is not None:
body["applicationId"] = application_id
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if id is not None:
body["id"] = id
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do(
"POST", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals", body=body, headers=headers
)
return ServicePrincipal.from_dict(res)
def delete(self, id: str):
"""Delete a single service principal in the Databricks account.
:param id: str
Unique ID for a service principal in the Databricks account.
"""
headers = {}
self._api.do(
"DELETE", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}", headers=headers
)
def get(self, id: str) -> ServicePrincipal:
"""Gets the details for a single service principal define in the Databricks account.
:param id: str
Unique ID for a service principal in the Databricks account.
:returns: :class:`ServicePrincipal`
"""
headers = {
"Accept": "application/json",
}
res = self._api.do(
"GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}", headers=headers
)
return ServicePrincipal.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[ServicePrincipal]:
"""Gets the set of service principals associated with a Databricks account.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page. Default is 10000.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`ServicePrincipal`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
# deduplicate items that may have been added during iteration
seen = set()
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do(
"GET",
f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals",
query=query,
headers=headers,
)
if "Resources" in json:
for v in json["Resources"]:
i = v["id"]
if i in seen:
continue
seen.add(i)
yield ServicePrincipal.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates the details of a single service principal in the Databricks account.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do(
"PATCH",
f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}",
body=body,
headers=headers,
)
def update(
self,
id: str,
*,
active: Optional[bool] = None,
application_id: Optional[str] = None,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[ServicePrincipalSchema]] = None,
):
"""Updates the details of a single service principal.
This action replaces the existing service principal with the same name.
:param id: str
Databricks service principal ID.
:param active: bool (optional)
If this user is active
:param application_id: str (optional)
UUID relating to the service principal
:param display_name: str (optional)
String that represents a concatenation of given and family names.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the service principal. See [assigning entitlements] for a full list of
supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`ServicePrincipalSchema`] (optional)
The schema of the List response.
"""
body = {}
if active is not None:
body["active"] = active
if application_id is not None:
body["applicationId"] = application_id
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do(
"PUT",
f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}",
body=body,
headers=headers,
)
class AccountUsersAPI:
"""User identities recognized by Databricks and represented by email addresses.
Databricks recommends using SCIM provisioning to sync users and groups automatically from your identity
provider to your Databricks account. SCIM streamlines onboarding a new employee or team by using your
identity provider to create users and groups in Databricks account and give them the proper level of
access. When a user leaves your organization or no longer needs access to Databricks account, admins can
terminate the user in your identity provider and that users account will also be removed from
Databricks account. This ensures a consistent offboarding process and prevents unauthorized users from
accessing sensitive data."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
active: Optional[bool] = None,
display_name: Optional[str] = None,
emails: Optional[List[ComplexValue]] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
id: Optional[str] = None,
name: Optional[Name] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[UserSchema]] = None,
user_name: Optional[str] = None,
) -> User:
"""Creates a new user in the Databricks account. This new user will also be added to the Databricks
account.
:param active: bool (optional)
If this user is active
:param display_name: str (optional)
String that represents a concatenation of given and family names. For example `John Smith`. This
field cannot be updated through the Workspace SCIM APIs when [identity federation is enabled]. Use
Account SCIM APIs to update `displayName`.
[identity federation is enabled]: https://docs.databricks.com/administration-guide/users-groups/best-practices.html#enable-identity-federation
:param emails: List[:class:`ComplexValue`] (optional)
All the emails associated with the Databricks user.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the user. See [assigning entitlements] for a full list of supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
External ID is not currently supported. It is reserved for future use.
:param groups: List[:class:`ComplexValue`] (optional)
:param id: str (optional)
Databricks user ID.
:param name: :class:`Name` (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`UserSchema`] (optional)
The schema of the user.
:param user_name: str (optional)
Email address of the Databricks user.
:returns: :class:`User`
"""
body = {}
if active is not None:
body["active"] = active
if display_name is not None:
body["displayName"] = display_name
if emails is not None:
body["emails"] = [v.as_dict() for v in emails]
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if id is not None:
body["id"] = id
if name is not None:
body["name"] = name.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
if user_name is not None:
body["userName"] = user_name
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do(
"POST", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users", body=body, headers=headers
)
return User.from_dict(res)
def delete(self, id: str):
"""Deletes a user. Deleting a user from a Databricks account also removes objects associated with the
user.
:param id: str
Unique ID for a user in the Databricks account.
"""
headers = {}
self._api.do("DELETE", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", headers=headers)
def get(
self,
id: str,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[GetSortOrder] = None,
start_index: Optional[int] = None,
) -> User:
"""Gets information for a specific user in Databricks account.
:param id: str
Unique ID for a user in the Databricks account.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page. Default is 10000.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
`name.givenName`, and `emails`.
:param sort_order: :class:`GetSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: :class:`User`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
res = self._api.do(
"GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", query=query, headers=headers
)
return User.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[User]:
"""Gets details for all the users associated with a Databricks account.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page. Default is 10000.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
`name.givenName`, and `emails`.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`User`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
# deduplicate items that may have been added during iteration
seen = set()
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do(
"GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users", query=query, headers=headers
)
if "Resources" in json:
for v in json["Resources"]:
i = v["id"]
if i in seen:
continue
seen.add(i)
yield User.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates a user resource by applying the supplied operations on specific user attributes.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do(
"PATCH", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", body=body, headers=headers
)
def update(
self,
id: str,
*,
active: Optional[bool] = None,
display_name: Optional[str] = None,
emails: Optional[List[ComplexValue]] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
name: Optional[Name] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[UserSchema]] = None,
user_name: Optional[str] = None,
):
"""Replaces a user's information with the data supplied in request.
:param id: str
Databricks user ID.
:param active: bool (optional)
If this user is active
:param display_name: str (optional)
String that represents a concatenation of given and family names. For example `John Smith`. This
field cannot be updated through the Workspace SCIM APIs when [identity federation is enabled]. Use
Account SCIM APIs to update `displayName`.
[identity federation is enabled]: https://docs.databricks.com/administration-guide/users-groups/best-practices.html#enable-identity-federation
:param emails: List[:class:`ComplexValue`] (optional)
All the emails associated with the Databricks user.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the user. See [assigning entitlements] for a full list of supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
External ID is not currently supported. It is reserved for future use.
:param groups: List[:class:`ComplexValue`] (optional)
:param name: :class:`Name` (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`UserSchema`] (optional)
The schema of the user.
:param user_name: str (optional)
Email address of the Databricks user.
"""
body = {}
if active is not None:
body["active"] = active
if display_name is not None:
body["displayName"] = display_name
if emails is not None:
body["emails"] = [v.as_dict() for v in emails]
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if name is not None:
body["name"] = name.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
if user_name is not None:
body["userName"] = user_name
headers = {
"Content-Type": "application/json",
}
self._api.do("PUT", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", body=body, headers=headers)
class GroupsAPI:
"""Groups simplify identity management, making it easier to assign access to Databricks workspace, data, and
other securable objects.
It is best practice to assign access to workspaces and access-control policies in Unity Catalog to groups,
instead of to users individually. All Databricks workspace identities can be assigned as members of
groups, and members inherit permissions that are assigned to their group."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
id: Optional[str] = None,
members: Optional[List[ComplexValue]] = None,
meta: Optional[ResourceMeta] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[GroupSchema]] = None,
) -> Group:
"""Creates a group in the Databricks workspace with a unique name, using the supplied group details.
:param display_name: str (optional)
String that represents a human-readable group name
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param id: str (optional)
Databricks group ID
:param members: List[:class:`ComplexValue`] (optional)
:param meta: :class:`ResourceMeta` (optional)
Container for the group identifier. Workspace local versus account.
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`GroupSchema`] (optional)
The schema of the group.
:returns: :class:`Group`
"""
body = {}
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if id is not None:
body["id"] = id
if members is not None:
body["members"] = [v.as_dict() for v in members]
if meta is not None:
body["meta"] = meta.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do("POST", "/api/2.0/preview/scim/v2/Groups", body=body, headers=headers)
return Group.from_dict(res)
def delete(self, id: str):
"""Deletes a group from the Databricks workspace.
:param id: str
Unique ID for a group in the Databricks workspace.
"""
headers = {}
self._api.do("DELETE", f"/api/2.0/preview/scim/v2/Groups/{id}", headers=headers)
def get(self, id: str) -> Group:
"""Gets the information for a specific group in the Databricks workspace.
:param id: str
Unique ID for a group in the Databricks workspace.
:returns: :class:`Group`
"""
headers = {
"Accept": "application/json",
}
res = self._api.do("GET", f"/api/2.0/preview/scim/v2/Groups/{id}", headers=headers)
return Group.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[Group]:
"""Gets all details of the groups associated with the Databricks workspace.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`Group`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
# deduplicate items that may have been added during iteration
seen = set()
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do("GET", "/api/2.0/preview/scim/v2/Groups", query=query, headers=headers)
if "Resources" in json:
for v in json["Resources"]:
i = v["id"]
if i in seen:
continue
seen.add(i)
yield Group.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates the details of a group.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do("PATCH", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
def update(
self,
id: str,
*,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
members: Optional[List[ComplexValue]] = None,
meta: Optional[ResourceMeta] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[GroupSchema]] = None,
):
"""Updates the details of a group by replacing the entire group entity.
:param id: str
Databricks group ID
:param display_name: str (optional)
String that represents a human-readable group name
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param members: List[:class:`ComplexValue`] (optional)
:param meta: :class:`ResourceMeta` (optional)
Container for the group identifier. Workspace local versus account.
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`GroupSchema`] (optional)
The schema of the group.
"""
body = {}
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if members is not None:
body["members"] = [v.as_dict() for v in members]
if meta is not None:
body["meta"] = meta.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do("PUT", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
class ServicePrincipalsAPI:
"""Identities for use with jobs, automated tools, and systems such as scripts, apps, and CI/CD platforms.
Databricks recommends creating service principals to run production jobs or modify production data. If all
processes that act on production data run with service principals, interactive users do not need any
write, delete, or modify privileges in production. This eliminates the risk of a user overwriting
production data by accident."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
active: Optional[bool] = None,
application_id: Optional[str] = None,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
id: Optional[str] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[ServicePrincipalSchema]] = None,
) -> ServicePrincipal:
"""Creates a new service principal in the Databricks workspace.
:param active: bool (optional)
If this user is active
:param application_id: str (optional)
UUID relating to the service principal
:param display_name: str (optional)
String that represents a concatenation of given and family names.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the service principal. See [assigning entitlements] for a full list of
supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param id: str (optional)
Databricks service principal ID.
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`ServicePrincipalSchema`] (optional)
The schema of the List response.
:returns: :class:`ServicePrincipal`
"""
body = {}
if active is not None:
body["active"] = active
if application_id is not None:
body["applicationId"] = application_id
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if id is not None:
body["id"] = id
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do("POST", "/api/2.0/preview/scim/v2/ServicePrincipals", body=body, headers=headers)
return ServicePrincipal.from_dict(res)
def delete(self, id: str):
"""Delete a single service principal in the Databricks workspace.
:param id: str
Unique ID for a service principal in the Databricks workspace.
"""
headers = {}
self._api.do("DELETE", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", headers=headers)
def get(self, id: str) -> ServicePrincipal:
"""Gets the details for a single service principal define in the Databricks workspace.
:param id: str
Unique ID for a service principal in the Databricks workspace.
:returns: :class:`ServicePrincipal`
"""
headers = {
"Accept": "application/json",
}
res = self._api.do("GET", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", headers=headers)
return ServicePrincipal.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[ServicePrincipal]:
"""Gets the set of service principals associated with a Databricks workspace.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`ServicePrincipal`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
# deduplicate items that may have been added during iteration
seen = set()
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do("GET", "/api/2.0/preview/scim/v2/ServicePrincipals", query=query, headers=headers)
if "Resources" in json:
for v in json["Resources"]:
i = v["id"]
if i in seen:
continue
seen.add(i)
yield ServicePrincipal.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates the details of a single service principal in the Databricks workspace.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do("PATCH", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", body=body, headers=headers)
def update(
self,
id: str,
*,
active: Optional[bool] = None,
application_id: Optional[str] = None,
display_name: Optional[str] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[ServicePrincipalSchema]] = None,
):
"""Updates the details of a single service principal.
This action replaces the existing service principal with the same name.
:param id: str
Databricks service principal ID.
:param active: bool (optional)
If this user is active
:param application_id: str (optional)
UUID relating to the service principal
:param display_name: str (optional)
String that represents a concatenation of given and family names.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the service principal. See [assigning entitlements] for a full list of
supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
:param groups: List[:class:`ComplexValue`] (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`ServicePrincipalSchema`] (optional)
The schema of the List response.
"""
body = {}
if active is not None:
body["active"] = active
if application_id is not None:
body["applicationId"] = application_id
if display_name is not None:
body["displayName"] = display_name
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do("PUT", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", body=body, headers=headers)
class UsersAPI:
"""User identities recognized by Databricks and represented by email addresses.
Databricks recommends using SCIM provisioning to sync users and groups automatically from your identity
provider to your Databricks workspace. SCIM streamlines onboarding a new employee or team by using your
identity provider to create users and groups in Databricks workspace and give them the proper level of
access. When a user leaves your organization or no longer needs access to Databricks workspace, admins can
terminate the user in your identity provider and that users account will also be removed from
Databricks workspace. This ensures a consistent offboarding process and prevents unauthorized users from
accessing sensitive data."""
def __init__(self, api_client):
self._api = api_client
def create(
self,
*,
active: Optional[bool] = None,
display_name: Optional[str] = None,
emails: Optional[List[ComplexValue]] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
id: Optional[str] = None,
name: Optional[Name] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[UserSchema]] = None,
user_name: Optional[str] = None,
) -> User:
"""Creates a new user in the Databricks workspace. This new user will also be added to the Databricks
account.
:param active: bool (optional)
If this user is active
:param display_name: str (optional)
String that represents a concatenation of given and family names. For example `John Smith`. This
field cannot be updated through the Workspace SCIM APIs when [identity federation is enabled]. Use
Account SCIM APIs to update `displayName`.
[identity federation is enabled]: https://docs.databricks.com/administration-guide/users-groups/best-practices.html#enable-identity-federation
:param emails: List[:class:`ComplexValue`] (optional)
All the emails associated with the Databricks user.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the user. See [assigning entitlements] for a full list of supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
External ID is not currently supported. It is reserved for future use.
:param groups: List[:class:`ComplexValue`] (optional)
:param id: str (optional)
Databricks user ID.
:param name: :class:`Name` (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`UserSchema`] (optional)
The schema of the user.
:param user_name: str (optional)
Email address of the Databricks user.
:returns: :class:`User`
"""
body = {}
if active is not None:
body["active"] = active
if display_name is not None:
body["displayName"] = display_name
if emails is not None:
body["emails"] = [v.as_dict() for v in emails]
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if id is not None:
body["id"] = id
if name is not None:
body["name"] = name.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
if user_name is not None:
body["userName"] = user_name
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do("POST", "/api/2.0/preview/scim/v2/Users", body=body, headers=headers)
return User.from_dict(res)
def delete(self, id: str):
"""Deletes a user. Deleting a user from a Databricks workspace also removes objects associated with the
user.
:param id: str
Unique ID for a user in the Databricks workspace.
"""
headers = {}
self._api.do("DELETE", f"/api/2.0/preview/scim/v2/Users/{id}", headers=headers)
def get(
self,
id: str,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[GetSortOrder] = None,
start_index: Optional[int] = None,
) -> User:
"""Gets information for a specific user in Databricks workspace.
:param id: str
Unique ID for a user in the Databricks workspace.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
`name.givenName`, and `emails`.
:param sort_order: :class:`GetSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: :class:`User`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
res = self._api.do("GET", f"/api/2.0/preview/scim/v2/Users/{id}", query=query, headers=headers)
return User.from_dict(res)
def get_permission_levels(self) -> GetPasswordPermissionLevelsResponse:
"""Gets the permission levels that a user can have on an object.
:returns: :class:`GetPasswordPermissionLevelsResponse`
"""
headers = {
"Accept": "application/json",
}
res = self._api.do("GET", "/api/2.0/permissions/authorization/passwords/permissionLevels", headers=headers)
return GetPasswordPermissionLevelsResponse.from_dict(res)
def get_permissions(self) -> PasswordPermissions:
"""Gets the permissions of all passwords. Passwords can inherit permissions from their root object.
:returns: :class:`PasswordPermissions`
"""
headers = {
"Accept": "application/json",
}
res = self._api.do("GET", "/api/2.0/permissions/authorization/passwords", headers=headers)
return PasswordPermissions.from_dict(res)
def list(
self,
*,
attributes: Optional[str] = None,
count: Optional[int] = None,
excluded_attributes: Optional[str] = None,
filter: Optional[str] = None,
sort_by: Optional[str] = None,
sort_order: Optional[ListSortOrder] = None,
start_index: Optional[int] = None,
) -> Iterator[User]:
"""Gets details for all the users associated with a Databricks workspace.
:param attributes: str (optional)
Comma-separated list of attributes to return in response.
:param count: int (optional)
Desired number of results per page.
:param excluded_attributes: str (optional)
Comma-separated list of attributes to exclude in response.
:param filter: str (optional)
Query by which the results have to be filtered. Supported operators are equals(`eq`),
contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
only support simple expressions.
[SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
:param sort_by: str (optional)
Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
`name.givenName`, and `emails`.
:param sort_order: :class:`ListSortOrder` (optional)
The order to sort the results.
:param start_index: int (optional)
Specifies the index of the first result. First item is number 1.
:returns: Iterator over :class:`User`
"""
query = {}
if attributes is not None:
query["attributes"] = attributes
if count is not None:
query["count"] = count
if excluded_attributes is not None:
query["excludedAttributes"] = excluded_attributes
if filter is not None:
query["filter"] = filter
if sort_by is not None:
query["sortBy"] = sort_by
if sort_order is not None:
query["sortOrder"] = sort_order.value
if start_index is not None:
query["startIndex"] = start_index
headers = {
"Accept": "application/json",
}
# deduplicate items that may have been added during iteration
seen = set()
query["startIndex"] = 1
if "count" not in query:
query["count"] = 10000
while True:
json = self._api.do("GET", "/api/2.0/preview/scim/v2/Users", query=query, headers=headers)
if "Resources" in json:
for v in json["Resources"]:
i = v["id"]
if i in seen:
continue
seen.add(i)
yield User.from_dict(v)
if "Resources" not in json or not json["Resources"]:
return
query["startIndex"] += len(json["Resources"])
def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
"""Partially updates a user resource by applying the supplied operations on specific user attributes.
:param id: str
Unique ID in the Databricks workspace.
:param operations: List[:class:`Patch`] (optional)
:param schemas: List[:class:`PatchSchema`] (optional)
The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
"""
body = {}
if operations is not None:
body["Operations"] = [v.as_dict() for v in operations]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
headers = {
"Content-Type": "application/json",
}
self._api.do("PATCH", f"/api/2.0/preview/scim/v2/Users/{id}", body=body, headers=headers)
def set_permissions(
self, *, access_control_list: Optional[List[PasswordAccessControlRequest]] = None
) -> PasswordPermissions:
"""Sets permissions on an object, replacing existing permissions if they exist. Deletes all direct
permissions if none are specified. Objects can inherit permissions from their root object.
:param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional)
:returns: :class:`PasswordPermissions`
"""
body = {}
if access_control_list is not None:
body["access_control_list"] = [v.as_dict() for v in access_control_list]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do("PUT", "/api/2.0/permissions/authorization/passwords", body=body, headers=headers)
return PasswordPermissions.from_dict(res)
def update(
self,
id: str,
*,
active: Optional[bool] = None,
display_name: Optional[str] = None,
emails: Optional[List[ComplexValue]] = None,
entitlements: Optional[List[ComplexValue]] = None,
external_id: Optional[str] = None,
groups: Optional[List[ComplexValue]] = None,
name: Optional[Name] = None,
roles: Optional[List[ComplexValue]] = None,
schemas: Optional[List[UserSchema]] = None,
user_name: Optional[str] = None,
):
"""Replaces a user's information with the data supplied in request.
:param id: str
Databricks user ID.
:param active: bool (optional)
If this user is active
:param display_name: str (optional)
String that represents a concatenation of given and family names. For example `John Smith`. This
field cannot be updated through the Workspace SCIM APIs when [identity federation is enabled]. Use
Account SCIM APIs to update `displayName`.
[identity federation is enabled]: https://docs.databricks.com/administration-guide/users-groups/best-practices.html#enable-identity-federation
:param emails: List[:class:`ComplexValue`] (optional)
All the emails associated with the Databricks user.
:param entitlements: List[:class:`ComplexValue`] (optional)
Entitlements assigned to the user. See [assigning entitlements] for a full list of supported values.
[assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
:param external_id: str (optional)
External ID is not currently supported. It is reserved for future use.
:param groups: List[:class:`ComplexValue`] (optional)
:param name: :class:`Name` (optional)
:param roles: List[:class:`ComplexValue`] (optional)
Corresponds to AWS instance profile/arn role.
:param schemas: List[:class:`UserSchema`] (optional)
The schema of the user.
:param user_name: str (optional)
Email address of the Databricks user.
"""
body = {}
if active is not None:
body["active"] = active
if display_name is not None:
body["displayName"] = display_name
if emails is not None:
body["emails"] = [v.as_dict() for v in emails]
if entitlements is not None:
body["entitlements"] = [v.as_dict() for v in entitlements]
if external_id is not None:
body["externalId"] = external_id
if groups is not None:
body["groups"] = [v.as_dict() for v in groups]
if name is not None:
body["name"] = name.as_dict()
if roles is not None:
body["roles"] = [v.as_dict() for v in roles]
if schemas is not None:
body["schemas"] = [v.value for v in schemas]
if user_name is not None:
body["userName"] = user_name
headers = {
"Content-Type": "application/json",
}
self._api.do("PUT", f"/api/2.0/preview/scim/v2/Users/{id}", body=body, headers=headers)
def update_permissions(
self, *, access_control_list: Optional[List[PasswordAccessControlRequest]] = None
) -> PasswordPermissions:
"""Updates the permissions on all passwords. Passwords can inherit permissions from their root object.
:param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional)
:returns: :class:`PasswordPermissions`
"""
body = {}
if access_control_list is not None:
body["access_control_list"] = [v.as_dict() for v in access_control_list]
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
res = self._api.do("PATCH", "/api/2.0/permissions/authorization/passwords", body=body, headers=headers)
return PasswordPermissions.from_dict(res)