1921 lines
76 KiB
Python
1921 lines
76 KiB
Python
# Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
|
||
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
from dataclasses import dataclass
|
||
from typing import Any, Dict, Iterator, List, Optional
|
||
|
||
from databricks.sdk.client_types import HostType
|
||
from databricks.sdk.service._internal import _from_dict, _repeated_dict
|
||
|
||
_LOG = logging.getLogger("databricks.sdk")
|
||
|
||
|
||
# all definitions in this file are in alphabetical order
|
||
|
||
|
||
@dataclass
|
||
class CreateCustomAppIntegrationOutput:
|
||
client_id: Optional[str] = None
|
||
"""OAuth client-id generated by the Databricks"""
|
||
|
||
client_secret: Optional[str] = None
|
||
"""OAuth client-secret generated by the Databricks. If this is a confidential OAuth app
|
||
client-secret will be generated."""
|
||
|
||
integration_id: Optional[str] = None
|
||
"""Unique integration id for the custom OAuth app"""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the CreateCustomAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.client_id is not None:
|
||
body["client_id"] = self.client_id
|
||
if self.client_secret is not None:
|
||
body["client_secret"] = self.client_secret
|
||
if self.integration_id is not None:
|
||
body["integration_id"] = self.integration_id
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the CreateCustomAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.client_id is not None:
|
||
body["client_id"] = self.client_id
|
||
if self.client_secret is not None:
|
||
body["client_secret"] = self.client_secret
|
||
if self.integration_id is not None:
|
||
body["integration_id"] = self.integration_id
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> CreateCustomAppIntegrationOutput:
|
||
"""Deserializes the CreateCustomAppIntegrationOutput from a dictionary."""
|
||
return cls(
|
||
client_id=d.get("client_id", None),
|
||
client_secret=d.get("client_secret", None),
|
||
integration_id=d.get("integration_id", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class CreatePublishedAppIntegrationOutput:
|
||
integration_id: Optional[str] = None
|
||
"""Unique integration id for the published OAuth app"""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the CreatePublishedAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.integration_id is not None:
|
||
body["integration_id"] = self.integration_id
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the CreatePublishedAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.integration_id is not None:
|
||
body["integration_id"] = self.integration_id
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> CreatePublishedAppIntegrationOutput:
|
||
"""Deserializes the CreatePublishedAppIntegrationOutput from a dictionary."""
|
||
return cls(integration_id=d.get("integration_id", None))
|
||
|
||
|
||
@dataclass
|
||
class CreateServicePrincipalSecretResponse:
|
||
create_time: Optional[str] = None
|
||
"""UTC time when the secret was created"""
|
||
|
||
expire_time: Optional[str] = None
|
||
"""UTC time when the secret will expire. If the field is not present, the secret does not expire."""
|
||
|
||
id: Optional[str] = None
|
||
"""ID of the secret"""
|
||
|
||
secret: Optional[str] = None
|
||
"""Secret Value"""
|
||
|
||
secret_hash: Optional[str] = None
|
||
"""Secret Hash"""
|
||
|
||
status: Optional[str] = None
|
||
"""Status of the secret"""
|
||
|
||
update_time: Optional[str] = None
|
||
"""UTC time when the secret was updated"""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the CreateServicePrincipalSecretResponse into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.expire_time is not None:
|
||
body["expire_time"] = self.expire_time
|
||
if self.id is not None:
|
||
body["id"] = self.id
|
||
if self.secret is not None:
|
||
body["secret"] = self.secret
|
||
if self.secret_hash is not None:
|
||
body["secret_hash"] = self.secret_hash
|
||
if self.status is not None:
|
||
body["status"] = self.status
|
||
if self.update_time is not None:
|
||
body["update_time"] = self.update_time
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the CreateServicePrincipalSecretResponse into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.expire_time is not None:
|
||
body["expire_time"] = self.expire_time
|
||
if self.id is not None:
|
||
body["id"] = self.id
|
||
if self.secret is not None:
|
||
body["secret"] = self.secret
|
||
if self.secret_hash is not None:
|
||
body["secret_hash"] = self.secret_hash
|
||
if self.status is not None:
|
||
body["status"] = self.status
|
||
if self.update_time is not None:
|
||
body["update_time"] = self.update_time
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> CreateServicePrincipalSecretResponse:
|
||
"""Deserializes the CreateServicePrincipalSecretResponse from a dictionary."""
|
||
return cls(
|
||
create_time=d.get("create_time", None),
|
||
expire_time=d.get("expire_time", None),
|
||
id=d.get("id", None),
|
||
secret=d.get("secret", None),
|
||
secret_hash=d.get("secret_hash", None),
|
||
status=d.get("status", None),
|
||
update_time=d.get("update_time", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class DeleteCustomAppIntegrationOutput:
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the DeleteCustomAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the DeleteCustomAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> DeleteCustomAppIntegrationOutput:
|
||
"""Deserializes the DeleteCustomAppIntegrationOutput from a dictionary."""
|
||
return cls()
|
||
|
||
|
||
@dataclass
|
||
class DeletePublishedAppIntegrationOutput:
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the DeletePublishedAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the DeletePublishedAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> DeletePublishedAppIntegrationOutput:
|
||
"""Deserializes the DeletePublishedAppIntegrationOutput from a dictionary."""
|
||
return cls()
|
||
|
||
|
||
@dataclass
|
||
class FederationPolicy:
|
||
create_time: Optional[str] = None
|
||
"""Creation time of the federation policy."""
|
||
|
||
description: Optional[str] = None
|
||
"""Description of the federation policy."""
|
||
|
||
name: Optional[str] = None
|
||
"""Resource name for the federation policy. Example values include
|
||
`accounts/<account-id>/federationPolicies/my-federation-policy` for Account Federation Policies,
|
||
and
|
||
`accounts/<account-id>/servicePrincipals/<service-principal-id>/federationPolicies/my-federation-policy`
|
||
for Service Principal Federation Policies. Typically an output parameter, which does not need to
|
||
be specified in create or update requests. If specified in a request, must match the value in
|
||
the request URL."""
|
||
|
||
oidc_policy: Optional[OidcFederationPolicy] = None
|
||
|
||
policy_id: Optional[str] = None
|
||
"""The ID of the federation policy. Output only."""
|
||
|
||
service_principal_id: Optional[int] = None
|
||
"""The service principal ID that this federation policy applies to. Output only. Only set for
|
||
service principal federation policies."""
|
||
|
||
uid: Optional[str] = None
|
||
"""Unique, immutable id of the federation policy."""
|
||
|
||
update_time: Optional[str] = None
|
||
"""Last update time of the federation policy."""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the FederationPolicy into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.description is not None:
|
||
body["description"] = self.description
|
||
if self.name is not None:
|
||
body["name"] = self.name
|
||
if self.oidc_policy:
|
||
body["oidc_policy"] = self.oidc_policy.as_dict()
|
||
if self.policy_id is not None:
|
||
body["policy_id"] = self.policy_id
|
||
if self.service_principal_id is not None:
|
||
body["service_principal_id"] = self.service_principal_id
|
||
if self.uid is not None:
|
||
body["uid"] = self.uid
|
||
if self.update_time is not None:
|
||
body["update_time"] = self.update_time
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the FederationPolicy into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.description is not None:
|
||
body["description"] = self.description
|
||
if self.name is not None:
|
||
body["name"] = self.name
|
||
if self.oidc_policy:
|
||
body["oidc_policy"] = self.oidc_policy
|
||
if self.policy_id is not None:
|
||
body["policy_id"] = self.policy_id
|
||
if self.service_principal_id is not None:
|
||
body["service_principal_id"] = self.service_principal_id
|
||
if self.uid is not None:
|
||
body["uid"] = self.uid
|
||
if self.update_time is not None:
|
||
body["update_time"] = self.update_time
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> FederationPolicy:
|
||
"""Deserializes the FederationPolicy from a dictionary."""
|
||
return cls(
|
||
create_time=d.get("create_time", None),
|
||
description=d.get("description", None),
|
||
name=d.get("name", None),
|
||
oidc_policy=_from_dict(d, "oidc_policy", OidcFederationPolicy),
|
||
policy_id=d.get("policy_id", None),
|
||
service_principal_id=d.get("service_principal_id", None),
|
||
uid=d.get("uid", None),
|
||
update_time=d.get("update_time", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class GetCustomAppIntegrationOutput:
|
||
client_id: Optional[str] = None
|
||
"""The client id of the custom OAuth app"""
|
||
|
||
confidential: Optional[bool] = None
|
||
"""This field indicates whether an OAuth client secret is required to authenticate this client."""
|
||
|
||
create_time: Optional[str] = None
|
||
|
||
created_by: Optional[int] = None
|
||
|
||
creator_username: Optional[str] = None
|
||
|
||
integration_id: Optional[str] = None
|
||
"""ID of this custom app"""
|
||
|
||
name: Optional[str] = None
|
||
"""The display name of the custom OAuth app"""
|
||
|
||
redirect_urls: Optional[List[str]] = None
|
||
"""List of OAuth redirect urls"""
|
||
|
||
scopes: Optional[List[str]] = None
|
||
|
||
token_access_policy: Optional[TokenAccessPolicy] = None
|
||
"""Token access policy"""
|
||
|
||
user_authorized_scopes: Optional[List[str]] = None
|
||
"""Scopes that will need to be consented by end user to mint the access token. If the user does not
|
||
authorize the access token will not be minted. Must be a subset of scopes."""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the GetCustomAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.client_id is not None:
|
||
body["client_id"] = self.client_id
|
||
if self.confidential is not None:
|
||
body["confidential"] = self.confidential
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.created_by is not None:
|
||
body["created_by"] = self.created_by
|
||
if self.creator_username is not None:
|
||
body["creator_username"] = self.creator_username
|
||
if self.integration_id is not None:
|
||
body["integration_id"] = self.integration_id
|
||
if self.name is not None:
|
||
body["name"] = self.name
|
||
if self.redirect_urls:
|
||
body["redirect_urls"] = [v for v in self.redirect_urls]
|
||
if self.scopes:
|
||
body["scopes"] = [v for v in self.scopes]
|
||
if self.token_access_policy:
|
||
body["token_access_policy"] = self.token_access_policy.as_dict()
|
||
if self.user_authorized_scopes:
|
||
body["user_authorized_scopes"] = [v for v in self.user_authorized_scopes]
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the GetCustomAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.client_id is not None:
|
||
body["client_id"] = self.client_id
|
||
if self.confidential is not None:
|
||
body["confidential"] = self.confidential
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.created_by is not None:
|
||
body["created_by"] = self.created_by
|
||
if self.creator_username is not None:
|
||
body["creator_username"] = self.creator_username
|
||
if self.integration_id is not None:
|
||
body["integration_id"] = self.integration_id
|
||
if self.name is not None:
|
||
body["name"] = self.name
|
||
if self.redirect_urls:
|
||
body["redirect_urls"] = self.redirect_urls
|
||
if self.scopes:
|
||
body["scopes"] = self.scopes
|
||
if self.token_access_policy:
|
||
body["token_access_policy"] = self.token_access_policy
|
||
if self.user_authorized_scopes:
|
||
body["user_authorized_scopes"] = self.user_authorized_scopes
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> GetCustomAppIntegrationOutput:
|
||
"""Deserializes the GetCustomAppIntegrationOutput from a dictionary."""
|
||
return cls(
|
||
client_id=d.get("client_id", None),
|
||
confidential=d.get("confidential", None),
|
||
create_time=d.get("create_time", None),
|
||
created_by=d.get("created_by", None),
|
||
creator_username=d.get("creator_username", None),
|
||
integration_id=d.get("integration_id", None),
|
||
name=d.get("name", None),
|
||
redirect_urls=d.get("redirect_urls", None),
|
||
scopes=d.get("scopes", None),
|
||
token_access_policy=_from_dict(d, "token_access_policy", TokenAccessPolicy),
|
||
user_authorized_scopes=d.get("user_authorized_scopes", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class GetCustomAppIntegrationsOutput:
|
||
apps: Optional[List[GetCustomAppIntegrationOutput]] = None
|
||
"""List of Custom OAuth App Integrations defined for the account."""
|
||
|
||
next_page_token: Optional[str] = None
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the GetCustomAppIntegrationsOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.apps:
|
||
body["apps"] = [v.as_dict() for v in self.apps]
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the GetCustomAppIntegrationsOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.apps:
|
||
body["apps"] = self.apps
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> GetCustomAppIntegrationsOutput:
|
||
"""Deserializes the GetCustomAppIntegrationsOutput from a dictionary."""
|
||
return cls(
|
||
apps=_repeated_dict(d, "apps", GetCustomAppIntegrationOutput),
|
||
next_page_token=d.get("next_page_token", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class GetPublishedAppIntegrationOutput:
|
||
app_id: Optional[str] = None
|
||
"""App-id of the published app integration"""
|
||
|
||
create_time: Optional[str] = None
|
||
|
||
created_by: Optional[int] = None
|
||
|
||
integration_id: Optional[str] = None
|
||
"""Unique integration id for the published OAuth app"""
|
||
|
||
name: Optional[str] = None
|
||
"""Display name of the published OAuth app"""
|
||
|
||
token_access_policy: Optional[TokenAccessPolicy] = None
|
||
"""Token access policy"""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the GetPublishedAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.app_id is not None:
|
||
body["app_id"] = self.app_id
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.created_by is not None:
|
||
body["created_by"] = self.created_by
|
||
if self.integration_id is not None:
|
||
body["integration_id"] = self.integration_id
|
||
if self.name is not None:
|
||
body["name"] = self.name
|
||
if self.token_access_policy:
|
||
body["token_access_policy"] = self.token_access_policy.as_dict()
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the GetPublishedAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.app_id is not None:
|
||
body["app_id"] = self.app_id
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.created_by is not None:
|
||
body["created_by"] = self.created_by
|
||
if self.integration_id is not None:
|
||
body["integration_id"] = self.integration_id
|
||
if self.name is not None:
|
||
body["name"] = self.name
|
||
if self.token_access_policy:
|
||
body["token_access_policy"] = self.token_access_policy
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> GetPublishedAppIntegrationOutput:
|
||
"""Deserializes the GetPublishedAppIntegrationOutput from a dictionary."""
|
||
return cls(
|
||
app_id=d.get("app_id", None),
|
||
create_time=d.get("create_time", None),
|
||
created_by=d.get("created_by", None),
|
||
integration_id=d.get("integration_id", None),
|
||
name=d.get("name", None),
|
||
token_access_policy=_from_dict(d, "token_access_policy", TokenAccessPolicy),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class GetPublishedAppIntegrationsOutput:
|
||
apps: Optional[List[GetPublishedAppIntegrationOutput]] = None
|
||
"""List of Published OAuth App Integrations defined for the account."""
|
||
|
||
next_page_token: Optional[str] = None
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the GetPublishedAppIntegrationsOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.apps:
|
||
body["apps"] = [v.as_dict() for v in self.apps]
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the GetPublishedAppIntegrationsOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.apps:
|
||
body["apps"] = self.apps
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> GetPublishedAppIntegrationsOutput:
|
||
"""Deserializes the GetPublishedAppIntegrationsOutput from a dictionary."""
|
||
return cls(
|
||
apps=_repeated_dict(d, "apps", GetPublishedAppIntegrationOutput),
|
||
next_page_token=d.get("next_page_token", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class GetPublishedAppsOutput:
|
||
apps: Optional[List[PublishedAppOutput]] = None
|
||
"""List of Published OAuth Apps."""
|
||
|
||
next_page_token: Optional[str] = None
|
||
"""A token that can be used to get the next page of results. If not present, there are no more
|
||
results to show."""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the GetPublishedAppsOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.apps:
|
||
body["apps"] = [v.as_dict() for v in self.apps]
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the GetPublishedAppsOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.apps:
|
||
body["apps"] = self.apps
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> GetPublishedAppsOutput:
|
||
"""Deserializes the GetPublishedAppsOutput from a dictionary."""
|
||
return cls(apps=_repeated_dict(d, "apps", PublishedAppOutput), next_page_token=d.get("next_page_token", None))
|
||
|
||
|
||
@dataclass
|
||
class ListFederationPoliciesResponse:
|
||
next_page_token: Optional[str] = None
|
||
|
||
policies: Optional[List[FederationPolicy]] = None
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the ListFederationPoliciesResponse into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
if self.policies:
|
||
body["policies"] = [v.as_dict() for v in self.policies]
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the ListFederationPoliciesResponse into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
if self.policies:
|
||
body["policies"] = self.policies
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> ListFederationPoliciesResponse:
|
||
"""Deserializes the ListFederationPoliciesResponse from a dictionary."""
|
||
return cls(
|
||
next_page_token=d.get("next_page_token", None), policies=_repeated_dict(d, "policies", FederationPolicy)
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class ListServicePrincipalSecretsResponse:
|
||
next_page_token: Optional[str] = None
|
||
"""A token, which can be sent as `page_token` to retrieve the next page."""
|
||
|
||
secrets: Optional[List[SecretInfo]] = None
|
||
"""List of the secrets"""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the ListServicePrincipalSecretsResponse into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
if self.secrets:
|
||
body["secrets"] = [v.as_dict() for v in self.secrets]
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the ListServicePrincipalSecretsResponse into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.next_page_token is not None:
|
||
body["next_page_token"] = self.next_page_token
|
||
if self.secrets:
|
||
body["secrets"] = self.secrets
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> ListServicePrincipalSecretsResponse:
|
||
"""Deserializes the ListServicePrincipalSecretsResponse from a dictionary."""
|
||
return cls(next_page_token=d.get("next_page_token", None), secrets=_repeated_dict(d, "secrets", SecretInfo))
|
||
|
||
|
||
@dataclass
|
||
class OidcFederationPolicy:
|
||
"""Specifies the policy to use for validating OIDC claims in your federated tokens."""
|
||
|
||
audiences: Optional[List[str]] = None
|
||
"""The allowed token audiences, as specified in the 'aud' claim of federated tokens. The audience
|
||
identifier is intended to represent the recipient of the token. Can be any non-empty string
|
||
value. As long as the audience in the token matches at least one audience in the policy, the
|
||
token is considered a match. If audiences is unspecified, defaults to your Databricks account
|
||
id."""
|
||
|
||
issuer: Optional[str] = None
|
||
"""The required token issuer, as specified in the 'iss' claim of federated tokens."""
|
||
|
||
jwks_json: Optional[str] = None
|
||
"""The public keys used to validate the signature of federated tokens, in JWKS format. Most use
|
||
cases should not need to specify this field. If jwks_uri and jwks_json are both unspecified
|
||
(recommended), Databricks automatically fetches the public keys from your issuer’s well known
|
||
endpoint. Databricks strongly recommends relying on your issuer’s well known endpoint for
|
||
discovering public keys."""
|
||
|
||
jwks_uri: Optional[str] = None
|
||
"""URL of the public keys used to validate the signature of federated tokens, in JWKS format. Most
|
||
use cases should not need to specify this field. If jwks_uri and jwks_json are both unspecified
|
||
(recommended), Databricks automatically fetches the public keys from your issuer’s well known
|
||
endpoint. Databricks strongly recommends relying on your issuer’s well known endpoint for
|
||
discovering public keys."""
|
||
|
||
subject: Optional[str] = None
|
||
"""The required token subject, as specified in the subject claim of federated tokens. Must be
|
||
specified for service principal federation policies. Must not be specified for account
|
||
federation policies."""
|
||
|
||
subject_claim: Optional[str] = None
|
||
"""The claim that contains the subject of the token. If unspecified, the default value is 'sub'."""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the OidcFederationPolicy into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.audiences:
|
||
body["audiences"] = [v for v in self.audiences]
|
||
if self.issuer is not None:
|
||
body["issuer"] = self.issuer
|
||
if self.jwks_json is not None:
|
||
body["jwks_json"] = self.jwks_json
|
||
if self.jwks_uri is not None:
|
||
body["jwks_uri"] = self.jwks_uri
|
||
if self.subject is not None:
|
||
body["subject"] = self.subject
|
||
if self.subject_claim is not None:
|
||
body["subject_claim"] = self.subject_claim
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the OidcFederationPolicy into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.audiences:
|
||
body["audiences"] = self.audiences
|
||
if self.issuer is not None:
|
||
body["issuer"] = self.issuer
|
||
if self.jwks_json is not None:
|
||
body["jwks_json"] = self.jwks_json
|
||
if self.jwks_uri is not None:
|
||
body["jwks_uri"] = self.jwks_uri
|
||
if self.subject is not None:
|
||
body["subject"] = self.subject
|
||
if self.subject_claim is not None:
|
||
body["subject_claim"] = self.subject_claim
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> OidcFederationPolicy:
|
||
"""Deserializes the OidcFederationPolicy from a dictionary."""
|
||
return cls(
|
||
audiences=d.get("audiences", None),
|
||
issuer=d.get("issuer", None),
|
||
jwks_json=d.get("jwks_json", None),
|
||
jwks_uri=d.get("jwks_uri", None),
|
||
subject=d.get("subject", None),
|
||
subject_claim=d.get("subject_claim", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class PublishedAppOutput:
|
||
app_id: Optional[str] = None
|
||
"""Unique ID of the published OAuth app."""
|
||
|
||
client_id: Optional[str] = None
|
||
"""Client ID of the published OAuth app. It is the client_id in the OAuth flow"""
|
||
|
||
description: Optional[str] = None
|
||
"""Description of the published OAuth app."""
|
||
|
||
is_confidential_client: Optional[bool] = None
|
||
"""Whether the published OAuth app is a confidential client. It is always false for published OAuth
|
||
apps."""
|
||
|
||
name: Optional[str] = None
|
||
"""The display name of the published OAuth app."""
|
||
|
||
redirect_urls: Optional[List[str]] = None
|
||
"""Redirect URLs of the published OAuth app."""
|
||
|
||
scopes: Optional[List[str]] = None
|
||
"""Required scopes for the published OAuth app."""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the PublishedAppOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.app_id is not None:
|
||
body["app_id"] = self.app_id
|
||
if self.client_id is not None:
|
||
body["client_id"] = self.client_id
|
||
if self.description is not None:
|
||
body["description"] = self.description
|
||
if self.is_confidential_client is not None:
|
||
body["is_confidential_client"] = self.is_confidential_client
|
||
if self.name is not None:
|
||
body["name"] = self.name
|
||
if self.redirect_urls:
|
||
body["redirect_urls"] = [v for v in self.redirect_urls]
|
||
if self.scopes:
|
||
body["scopes"] = [v for v in self.scopes]
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the PublishedAppOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.app_id is not None:
|
||
body["app_id"] = self.app_id
|
||
if self.client_id is not None:
|
||
body["client_id"] = self.client_id
|
||
if self.description is not None:
|
||
body["description"] = self.description
|
||
if self.is_confidential_client is not None:
|
||
body["is_confidential_client"] = self.is_confidential_client
|
||
if self.name is not None:
|
||
body["name"] = self.name
|
||
if self.redirect_urls:
|
||
body["redirect_urls"] = self.redirect_urls
|
||
if self.scopes:
|
||
body["scopes"] = self.scopes
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> PublishedAppOutput:
|
||
"""Deserializes the PublishedAppOutput from a dictionary."""
|
||
return cls(
|
||
app_id=d.get("app_id", None),
|
||
client_id=d.get("client_id", None),
|
||
description=d.get("description", None),
|
||
is_confidential_client=d.get("is_confidential_client", None),
|
||
name=d.get("name", None),
|
||
redirect_urls=d.get("redirect_urls", None),
|
||
scopes=d.get("scopes", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class SecretInfo:
|
||
create_time: Optional[str] = None
|
||
"""UTC time when the secret was created"""
|
||
|
||
expire_time: Optional[str] = None
|
||
"""UTC time when the secret will expire. If the field is not present, the secret does not expire."""
|
||
|
||
id: Optional[str] = None
|
||
"""ID of the secret"""
|
||
|
||
secret_hash: Optional[str] = None
|
||
"""Secret Hash"""
|
||
|
||
status: Optional[str] = None
|
||
"""Status of the secret"""
|
||
|
||
update_time: Optional[str] = None
|
||
"""UTC time when the secret was updated"""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the SecretInfo into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.expire_time is not None:
|
||
body["expire_time"] = self.expire_time
|
||
if self.id is not None:
|
||
body["id"] = self.id
|
||
if self.secret_hash is not None:
|
||
body["secret_hash"] = self.secret_hash
|
||
if self.status is not None:
|
||
body["status"] = self.status
|
||
if self.update_time is not None:
|
||
body["update_time"] = self.update_time
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the SecretInfo into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.create_time is not None:
|
||
body["create_time"] = self.create_time
|
||
if self.expire_time is not None:
|
||
body["expire_time"] = self.expire_time
|
||
if self.id is not None:
|
||
body["id"] = self.id
|
||
if self.secret_hash is not None:
|
||
body["secret_hash"] = self.secret_hash
|
||
if self.status is not None:
|
||
body["status"] = self.status
|
||
if self.update_time is not None:
|
||
body["update_time"] = self.update_time
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> SecretInfo:
|
||
"""Deserializes the SecretInfo from a dictionary."""
|
||
return cls(
|
||
create_time=d.get("create_time", None),
|
||
expire_time=d.get("expire_time", None),
|
||
id=d.get("id", None),
|
||
secret_hash=d.get("secret_hash", None),
|
||
status=d.get("status", None),
|
||
update_time=d.get("update_time", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class TokenAccessPolicy:
|
||
absolute_session_lifetime_in_minutes: Optional[int] = None
|
||
"""Absolute OAuth session TTL in minutes. Effective only when the single-use refresh token feature
|
||
is enabled. This is the absolute TTL of all refresh tokens issued in one OAuth session. When a
|
||
new refresh token is issued during refresh token rotation, it will inherit the same absolute TTL
|
||
as the old refresh token. In other words, this represents the maximum amount of time a user can
|
||
stay logged in without re-authenticating."""
|
||
|
||
access_token_ttl_in_minutes: Optional[int] = None
|
||
"""access token time to live in minutes"""
|
||
|
||
enable_single_use_refresh_tokens: Optional[bool] = None
|
||
"""Whether to enable single-use refresh tokens (refresh token rotation). If this feature is
|
||
enabled, upon successfully getting a new access token using a refresh token, Databricks will
|
||
issue a new refresh token along with the access token in the response and invalidate the old
|
||
refresh token. The client should use the new refresh token to get access tokens in future
|
||
requests."""
|
||
|
||
refresh_token_ttl_in_minutes: Optional[int] = None
|
||
"""Refresh token time to live in minutes. When single-use refresh tokens are enabled, this
|
||
represents the TTL of an individual refresh token. If the refresh token is used before it
|
||
expires, a new one is issued with a renewed individual TTL."""
|
||
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the TokenAccessPolicy into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
if self.absolute_session_lifetime_in_minutes is not None:
|
||
body["absolute_session_lifetime_in_minutes"] = self.absolute_session_lifetime_in_minutes
|
||
if self.access_token_ttl_in_minutes is not None:
|
||
body["access_token_ttl_in_minutes"] = self.access_token_ttl_in_minutes
|
||
if self.enable_single_use_refresh_tokens is not None:
|
||
body["enable_single_use_refresh_tokens"] = self.enable_single_use_refresh_tokens
|
||
if self.refresh_token_ttl_in_minutes is not None:
|
||
body["refresh_token_ttl_in_minutes"] = self.refresh_token_ttl_in_minutes
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the TokenAccessPolicy into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
if self.absolute_session_lifetime_in_minutes is not None:
|
||
body["absolute_session_lifetime_in_minutes"] = self.absolute_session_lifetime_in_minutes
|
||
if self.access_token_ttl_in_minutes is not None:
|
||
body["access_token_ttl_in_minutes"] = self.access_token_ttl_in_minutes
|
||
if self.enable_single_use_refresh_tokens is not None:
|
||
body["enable_single_use_refresh_tokens"] = self.enable_single_use_refresh_tokens
|
||
if self.refresh_token_ttl_in_minutes is not None:
|
||
body["refresh_token_ttl_in_minutes"] = self.refresh_token_ttl_in_minutes
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> TokenAccessPolicy:
|
||
"""Deserializes the TokenAccessPolicy from a dictionary."""
|
||
return cls(
|
||
absolute_session_lifetime_in_minutes=d.get("absolute_session_lifetime_in_minutes", None),
|
||
access_token_ttl_in_minutes=d.get("access_token_ttl_in_minutes", None),
|
||
enable_single_use_refresh_tokens=d.get("enable_single_use_refresh_tokens", None),
|
||
refresh_token_ttl_in_minutes=d.get("refresh_token_ttl_in_minutes", None),
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class UpdateCustomAppIntegrationOutput:
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the UpdateCustomAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the UpdateCustomAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> UpdateCustomAppIntegrationOutput:
|
||
"""Deserializes the UpdateCustomAppIntegrationOutput from a dictionary."""
|
||
return cls()
|
||
|
||
|
||
@dataclass
|
||
class UpdatePublishedAppIntegrationOutput:
|
||
def as_dict(self) -> dict:
|
||
"""Serializes the UpdatePublishedAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
||
body = {}
|
||
return body
|
||
|
||
def as_shallow_dict(self) -> dict:
|
||
"""Serializes the UpdatePublishedAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
||
body = {}
|
||
return body
|
||
|
||
@classmethod
|
||
def from_dict(cls, d: Dict[str, Any]) -> UpdatePublishedAppIntegrationOutput:
|
||
"""Deserializes the UpdatePublishedAppIntegrationOutput from a dictionary."""
|
||
return cls()
|
||
|
||
|
||
class AccountFederationPolicyAPI:
|
||
"""These APIs manage account federation policies.
|
||
|
||
Account federation policies allow users and service principals in your Databricks account to securely
|
||
access Databricks APIs using tokens from your trusted identity providers (IdPs).
|
||
|
||
With token federation, your users and service principals can exchange tokens from your IdP for Databricks
|
||
OAuth tokens, which can be used to access Databricks APIs. Token federation eliminates the need to manage
|
||
Databricks secrets, and allows you to centralize management of token issuance policies in your IdP.
|
||
Databricks token federation is typically used in combination with [SCIM], so users in your IdP are
|
||
synchronized into your Databricks account.
|
||
|
||
Token federation is configured in your Databricks account using an account federation policy. An account
|
||
federation policy specifies: * which IdP, or issuer, your Databricks account should accept tokens from *
|
||
how to determine which Databricks user, or subject, a token is issued for
|
||
|
||
To configure a federation policy, you provide the following: * The required token __issuer__, as specified
|
||
in the “iss” claim of your tokens. The issuer is an https URL that identifies your IdP. * The allowed
|
||
token __audiences__, as specified in the “aud” claim of your tokens. This identifier is intended to
|
||
represent the recipient of the token. As long as the audience in the token matches at least one audience
|
||
in the policy, the token is considered a match. If unspecified, the default value is your Databricks
|
||
account id. * The __subject claim__, which indicates which token claim contains the Databricks username of
|
||
the user the token was issued for. If unspecified, the default value is “sub”. * Optionally, the
|
||
public keys used to validate the signature of your tokens, in JWKS format. If unspecified (recommended),
|
||
Databricks automatically fetches the public keys from your issuer’s well known endpoint. Databricks
|
||
strongly recommends relying on your issuer’s well known endpoint for discovering public keys.
|
||
|
||
An example federation policy is: ``` issuer: "https://idp.mycompany.com/oidc" audiences: ["databricks"]
|
||
subject_claim: "sub" ```
|
||
|
||
An example JWT token body that matches this policy and could be used to authenticate to Databricks as user
|
||
`username@mycompany.com` is: ``` { "iss": "https://idp.mycompany.com/oidc", "aud": "databricks", "sub":
|
||
"username@mycompany.com" } ```
|
||
|
||
You may also need to configure your IdP to generate tokens for your users to exchange with Databricks, if
|
||
your users do not already have the ability to generate tokens that are compatible with your federation
|
||
policy.
|
||
|
||
You do not need to configure an OAuth application in Databricks to use token federation.
|
||
|
||
[SCIM]: https://docs.databricks.com/admin/users-groups/scim/index.html"""
|
||
|
||
def __init__(self, api_client):
|
||
self._api = api_client
|
||
|
||
def create(self, policy: FederationPolicy, *, policy_id: Optional[str] = None) -> FederationPolicy:
|
||
"""Create account federation policy.
|
||
|
||
:param policy: :class:`FederationPolicy`
|
||
:param policy_id: str (optional)
|
||
The identifier for the federation policy. The identifier must contain only lowercase alphanumeric
|
||
characters, numbers, hyphens, and slashes. If unspecified, the id will be assigned by Databricks.
|
||
|
||
:returns: :class:`FederationPolicy`
|
||
"""
|
||
|
||
body = policy.as_dict()
|
||
query = {}
|
||
if policy_id is not None:
|
||
query["policy_id"] = policy_id
|
||
headers = {
|
||
"Accept": "application/json",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"POST",
|
||
f"/api/2.0/accounts/{self._api.account_id}/federationPolicies",
|
||
query=query,
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
return FederationPolicy.from_dict(res)
|
||
|
||
def delete(self, policy_id: str):
|
||
"""Delete account federation policy.
|
||
|
||
:param policy_id: str
|
||
The identifier for the federation policy.
|
||
|
||
|
||
"""
|
||
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
self._api.do(
|
||
"DELETE", f"/api/2.0/accounts/{self._api.account_id}/federationPolicies/{policy_id}", headers=headers
|
||
)
|
||
|
||
def get(self, policy_id: str) -> FederationPolicy:
|
||
"""Get account federation policy.
|
||
|
||
:param policy_id: str
|
||
The identifier for the federation policy.
|
||
|
||
:returns: :class:`FederationPolicy`
|
||
"""
|
||
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"GET", f"/api/2.0/accounts/{self._api.account_id}/federationPolicies/{policy_id}", headers=headers
|
||
)
|
||
return FederationPolicy.from_dict(res)
|
||
|
||
def list(self, *, page_size: Optional[int] = None, page_token: Optional[str] = None) -> Iterator[FederationPolicy]:
|
||
"""List account federation policies.
|
||
|
||
:param page_size: int (optional)
|
||
:param page_token: str (optional)
|
||
|
||
:returns: Iterator over :class:`FederationPolicy`
|
||
"""
|
||
|
||
query = {}
|
||
if page_size is not None:
|
||
query["page_size"] = page_size
|
||
if page_token is not None:
|
||
query["page_token"] = page_token
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
while True:
|
||
json = self._api.do(
|
||
"GET", f"/api/2.0/accounts/{self._api.account_id}/federationPolicies", query=query, headers=headers
|
||
)
|
||
if "policies" in json:
|
||
for v in json["policies"]:
|
||
yield FederationPolicy.from_dict(v)
|
||
if "next_page_token" not in json or not json["next_page_token"]:
|
||
return
|
||
query["page_token"] = json["next_page_token"]
|
||
|
||
def update(
|
||
self, policy_id: str, policy: FederationPolicy, *, update_mask: Optional[str] = None
|
||
) -> FederationPolicy:
|
||
"""Update account federation policy.
|
||
|
||
:param policy_id: str
|
||
The identifier for the federation policy.
|
||
:param policy: :class:`FederationPolicy`
|
||
:param update_mask: str (optional)
|
||
The field mask specifies which fields of the policy to update. To specify multiple fields in the
|
||
field mask, use comma as the separator (no space). The special value '*' indicates that all fields
|
||
should be updated (full replacement). If unspecified, all fields that are set in the policy provided
|
||
in the update request will overwrite the corresponding fields in the existing policy. Example value:
|
||
'description,oidc_policy.audiences'.
|
||
|
||
:returns: :class:`FederationPolicy`
|
||
"""
|
||
|
||
body = policy.as_dict()
|
||
query = {}
|
||
if update_mask is not None:
|
||
query["update_mask"] = update_mask
|
||
headers = {
|
||
"Accept": "application/json",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"PATCH",
|
||
f"/api/2.0/accounts/{self._api.account_id}/federationPolicies/{policy_id}",
|
||
query=query,
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
return FederationPolicy.from_dict(res)
|
||
|
||
|
||
class CustomAppIntegrationAPI:
|
||
"""These APIs enable administrators to manage custom OAuth app integrations, which is required for
|
||
adding/using Custom OAuth App Integration like Tableau Cloud for Databricks in AWS cloud."""
|
||
|
||
def __init__(self, api_client):
|
||
self._api = api_client
|
||
|
||
def create(
|
||
self,
|
||
*,
|
||
confidential: Optional[bool] = None,
|
||
name: Optional[str] = None,
|
||
redirect_urls: Optional[List[str]] = None,
|
||
scopes: Optional[List[str]] = None,
|
||
token_access_policy: Optional[TokenAccessPolicy] = None,
|
||
user_authorized_scopes: Optional[List[str]] = None,
|
||
) -> CreateCustomAppIntegrationOutput:
|
||
"""Create Custom OAuth App Integration.
|
||
|
||
You can retrieve the custom OAuth app integration via :method:CustomAppIntegration/get.
|
||
|
||
:param confidential: bool (optional)
|
||
This field indicates whether an OAuth client secret is required to authenticate this client.
|
||
:param name: str (optional)
|
||
Name of the custom OAuth app
|
||
:param redirect_urls: List[str] (optional)
|
||
List of OAuth redirect urls
|
||
:param scopes: List[str] (optional)
|
||
OAuth scopes granted to the application. Supported scopes: all-apis, sql, offline_access, openid,
|
||
profile, email.
|
||
:param token_access_policy: :class:`TokenAccessPolicy` (optional)
|
||
Token access policy
|
||
:param user_authorized_scopes: List[str] (optional)
|
||
Scopes that will need to be consented by end user to mint the access token. If the user does not
|
||
authorize the access token will not be minted. Must be a subset of scopes.
|
||
|
||
:returns: :class:`CreateCustomAppIntegrationOutput`
|
||
"""
|
||
|
||
body = {}
|
||
if confidential is not None:
|
||
body["confidential"] = confidential
|
||
if name is not None:
|
||
body["name"] = name
|
||
if redirect_urls is not None:
|
||
body["redirect_urls"] = [v for v in redirect_urls]
|
||
if scopes is not None:
|
||
body["scopes"] = [v for v in scopes]
|
||
if token_access_policy is not None:
|
||
body["token_access_policy"] = token_access_policy.as_dict()
|
||
if user_authorized_scopes is not None:
|
||
body["user_authorized_scopes"] = [v for v in user_authorized_scopes]
|
||
headers = {
|
||
"Accept": "application/json",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"POST",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations",
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
return CreateCustomAppIntegrationOutput.from_dict(res)
|
||
|
||
def delete(self, integration_id: str):
|
||
"""Delete an existing Custom OAuth App Integration. You can retrieve the custom OAuth app integration via
|
||
:method:CustomAppIntegration/get.
|
||
|
||
:param integration_id: str
|
||
|
||
|
||
"""
|
||
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
self._api.do(
|
||
"DELETE",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations/{integration_id}",
|
||
headers=headers,
|
||
)
|
||
|
||
def get(self, integration_id: str) -> GetCustomAppIntegrationOutput:
|
||
"""Gets the Custom OAuth App Integration for the given integration id.
|
||
|
||
:param integration_id: str
|
||
The OAuth app integration ID.
|
||
|
||
:returns: :class:`GetCustomAppIntegrationOutput`
|
||
"""
|
||
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"GET",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations/{integration_id}",
|
||
headers=headers,
|
||
)
|
||
return GetCustomAppIntegrationOutput.from_dict(res)
|
||
|
||
def list(
|
||
self,
|
||
*,
|
||
include_creator_username: Optional[bool] = None,
|
||
page_size: Optional[int] = None,
|
||
page_token: Optional[str] = None,
|
||
) -> Iterator[GetCustomAppIntegrationOutput]:
|
||
"""Get the list of custom OAuth app integrations for the specified Databricks account
|
||
|
||
:param include_creator_username: bool (optional)
|
||
:param page_size: int (optional)
|
||
:param page_token: str (optional)
|
||
|
||
:returns: Iterator over :class:`GetCustomAppIntegrationOutput`
|
||
"""
|
||
|
||
query = {}
|
||
if include_creator_username is not None:
|
||
query["include_creator_username"] = include_creator_username
|
||
if page_size is not None:
|
||
query["page_size"] = page_size
|
||
if page_token is not None:
|
||
query["page_token"] = page_token
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
while True:
|
||
json = self._api.do(
|
||
"GET",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations",
|
||
query=query,
|
||
headers=headers,
|
||
)
|
||
if "apps" in json:
|
||
for v in json["apps"]:
|
||
yield GetCustomAppIntegrationOutput.from_dict(v)
|
||
if "next_page_token" not in json or not json["next_page_token"]:
|
||
return
|
||
query["page_token"] = json["next_page_token"]
|
||
|
||
def update(
|
||
self,
|
||
integration_id: str,
|
||
*,
|
||
redirect_urls: Optional[List[str]] = None,
|
||
scopes: Optional[List[str]] = None,
|
||
token_access_policy: Optional[TokenAccessPolicy] = None,
|
||
user_authorized_scopes: Optional[List[str]] = None,
|
||
):
|
||
"""Updates an existing custom OAuth App Integration. You can retrieve the custom OAuth app integration
|
||
via :method:CustomAppIntegration/get.
|
||
|
||
:param integration_id: str
|
||
:param redirect_urls: List[str] (optional)
|
||
List of OAuth redirect urls to be updated in the custom OAuth app integration
|
||
:param scopes: List[str] (optional)
|
||
List of OAuth scopes to be updated in the custom OAuth app integration, similar to redirect URIs
|
||
this will fully replace the existing values instead of appending
|
||
:param token_access_policy: :class:`TokenAccessPolicy` (optional)
|
||
Token access policy to be updated in the custom OAuth app integration
|
||
:param user_authorized_scopes: List[str] (optional)
|
||
Scopes that will need to be consented by end user to mint the access token. If the user does not
|
||
authorize the access token will not be minted. Must be a subset of scopes.
|
||
|
||
|
||
"""
|
||
|
||
body = {}
|
||
if redirect_urls is not None:
|
||
body["redirect_urls"] = [v for v in redirect_urls]
|
||
if scopes is not None:
|
||
body["scopes"] = [v for v in scopes]
|
||
if token_access_policy is not None:
|
||
body["token_access_policy"] = token_access_policy.as_dict()
|
||
if user_authorized_scopes is not None:
|
||
body["user_authorized_scopes"] = [v for v in user_authorized_scopes]
|
||
headers = {
|
||
"Accept": "application/json",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
self._api.do(
|
||
"PATCH",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations/{integration_id}",
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
|
||
|
||
class OAuthPublishedAppsAPI:
|
||
"""These APIs enable administrators to view all the available published OAuth applications in Databricks.
|
||
Administrators can add the published OAuth applications to their account through the OAuth Published App
|
||
Integration APIs."""
|
||
|
||
def __init__(self, api_client):
|
||
self._api = api_client
|
||
|
||
def list(
|
||
self, *, page_size: Optional[int] = None, page_token: Optional[str] = None
|
||
) -> Iterator[PublishedAppOutput]:
|
||
"""Get all the available published OAuth apps in Databricks.
|
||
|
||
:param page_size: int (optional)
|
||
The max number of OAuth published apps to return in one page.
|
||
:param page_token: str (optional)
|
||
A token that can be used to get the next page of results.
|
||
|
||
:returns: Iterator over :class:`PublishedAppOutput`
|
||
"""
|
||
|
||
query = {}
|
||
if page_size is not None:
|
||
query["page_size"] = page_size
|
||
if page_token is not None:
|
||
query["page_token"] = page_token
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
while True:
|
||
json = self._api.do(
|
||
"GET", f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-apps", query=query, headers=headers
|
||
)
|
||
if "apps" in json:
|
||
for v in json["apps"]:
|
||
yield PublishedAppOutput.from_dict(v)
|
||
if "next_page_token" not in json or not json["next_page_token"]:
|
||
return
|
||
query["page_token"] = json["next_page_token"]
|
||
|
||
|
||
class PublishedAppIntegrationAPI:
|
||
"""These APIs enable administrators to manage published OAuth app integrations, which is required for
|
||
adding/using Published OAuth App Integration like Tableau Desktop for Databricks in AWS cloud."""
|
||
|
||
def __init__(self, api_client):
|
||
self._api = api_client
|
||
|
||
def create(
|
||
self, *, app_id: Optional[str] = None, token_access_policy: Optional[TokenAccessPolicy] = None
|
||
) -> CreatePublishedAppIntegrationOutput:
|
||
"""Create Published OAuth App Integration.
|
||
|
||
You can retrieve the published OAuth app integration via :method:PublishedAppIntegration/get.
|
||
|
||
:param app_id: str (optional)
|
||
App id of the OAuth published app integration. For example power-bi, tableau-deskop
|
||
:param token_access_policy: :class:`TokenAccessPolicy` (optional)
|
||
Token access policy
|
||
|
||
:returns: :class:`CreatePublishedAppIntegrationOutput`
|
||
"""
|
||
|
||
body = {}
|
||
if app_id is not None:
|
||
body["app_id"] = app_id
|
||
if token_access_policy is not None:
|
||
body["token_access_policy"] = token_access_policy.as_dict()
|
||
headers = {
|
||
"Accept": "application/json",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"POST",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations",
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
return CreatePublishedAppIntegrationOutput.from_dict(res)
|
||
|
||
def delete(self, integration_id: str):
|
||
"""Delete an existing Published OAuth App Integration. You can retrieve the published OAuth app
|
||
integration via :method:PublishedAppIntegration/get.
|
||
|
||
:param integration_id: str
|
||
|
||
|
||
"""
|
||
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
self._api.do(
|
||
"DELETE",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations/{integration_id}",
|
||
headers=headers,
|
||
)
|
||
|
||
def get(self, integration_id: str) -> GetPublishedAppIntegrationOutput:
|
||
"""Gets the Published OAuth App Integration for the given integration id.
|
||
|
||
:param integration_id: str
|
||
|
||
:returns: :class:`GetPublishedAppIntegrationOutput`
|
||
"""
|
||
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"GET",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations/{integration_id}",
|
||
headers=headers,
|
||
)
|
||
return GetPublishedAppIntegrationOutput.from_dict(res)
|
||
|
||
def list(
|
||
self, *, page_size: Optional[int] = None, page_token: Optional[str] = None
|
||
) -> Iterator[GetPublishedAppIntegrationOutput]:
|
||
"""Get the list of published OAuth app integrations for the specified Databricks account
|
||
|
||
:param page_size: int (optional)
|
||
:param page_token: str (optional)
|
||
|
||
:returns: Iterator over :class:`GetPublishedAppIntegrationOutput`
|
||
"""
|
||
|
||
query = {}
|
||
if page_size is not None:
|
||
query["page_size"] = page_size
|
||
if page_token is not None:
|
||
query["page_token"] = page_token
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
while True:
|
||
json = self._api.do(
|
||
"GET",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations",
|
||
query=query,
|
||
headers=headers,
|
||
)
|
||
if "apps" in json:
|
||
for v in json["apps"]:
|
||
yield GetPublishedAppIntegrationOutput.from_dict(v)
|
||
if "next_page_token" not in json or not json["next_page_token"]:
|
||
return
|
||
query["page_token"] = json["next_page_token"]
|
||
|
||
def update(self, integration_id: str, *, token_access_policy: Optional[TokenAccessPolicy] = None):
|
||
"""Updates an existing published OAuth App Integration. You can retrieve the published OAuth app
|
||
integration via :method:PublishedAppIntegration/get.
|
||
|
||
:param integration_id: str
|
||
:param token_access_policy: :class:`TokenAccessPolicy` (optional)
|
||
Token access policy to be updated in the published OAuth app integration
|
||
|
||
|
||
"""
|
||
|
||
body = {}
|
||
if token_access_policy is not None:
|
||
body["token_access_policy"] = token_access_policy.as_dict()
|
||
headers = {
|
||
"Accept": "application/json",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
self._api.do(
|
||
"PATCH",
|
||
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations/{integration_id}",
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
|
||
|
||
class ServicePrincipalFederationPolicyAPI:
|
||
"""These APIs manage service principal federation policies.
|
||
|
||
Service principal federation, also known as Workload Identity Federation, allows your automated workloads
|
||
running outside of Databricks to securely access Databricks APIs without the need for Databricks secrets.
|
||
With Workload Identity Federation, your application (or workload) authenticates to Databricks as a
|
||
Databricks service principal, using tokens provided by the workload runtime.
|
||
|
||
Databricks strongly recommends using Workload Identity Federation to authenticate to Databricks from
|
||
automated workloads, over alternatives such as OAuth client secrets or Personal Access Tokens, whenever
|
||
possible. Workload Identity Federation is supported by many popular services, including Github Actions,
|
||
Azure DevOps, GitLab, Terraform Cloud, and Kubernetes clusters, among others.
|
||
|
||
Workload identity federation is configured in your Databricks account using a service principal federation
|
||
policy. A service principal federation policy specifies: * which IdP, or issuer, the service principal is
|
||
allowed to authenticate from * which workload identity, or subject, is allowed to authenticate as the
|
||
Databricks service principal
|
||
|
||
To configure a federation policy, you provide the following: * The required token __issuer__, as specified
|
||
in the “iss” claim of workload identity tokens. The issuer is an https URL that identifies the
|
||
workload identity provider. * The required token __subject__, as specified in the “sub” claim of
|
||
workload identity tokens. The subject uniquely identifies the workload in the workload runtime
|
||
environment. * The allowed token __audiences__, as specified in the “aud” claim of workload identity
|
||
tokens. The audience is intended to represent the recipient of the token. As long as the audience in the
|
||
token matches at least one audience in the policy, the token is considered a match. If unspecified, the
|
||
default value is your Databricks account id. * Optionally, the public keys used to validate the signature
|
||
of the workload identity tokens, in JWKS format. If unspecified (recommended), Databricks automatically
|
||
fetches the public keys from the issuer’s well known endpoint. Databricks strongly recommends relying on
|
||
the issuer’s well known endpoint for discovering public keys.
|
||
|
||
An example service principal federation policy, for a Github Actions workload, is: ``` issuer:
|
||
"https://token.actions.githubusercontent.com" audiences: ["https://github.com/my-github-org"] subject:
|
||
"repo:my-github-org/my-repo:environment:prod" ```
|
||
|
||
An example JWT token body that matches this policy and could be used to authenticate to Databricks is: ```
|
||
{ "iss": "https://token.actions.githubusercontent.com", "aud": "https://github.com/my-github-org", "sub":
|
||
"repo:my-github-org/my-repo:environment:prod" } ```
|
||
|
||
You may also need to configure the workload runtime to generate tokens for your workloads.
|
||
|
||
You do not need to configure an OAuth application in Databricks to use token federation."""
|
||
|
||
def __init__(self, api_client):
|
||
self._api = api_client
|
||
|
||
def create(
|
||
self, service_principal_id: int, policy: FederationPolicy, *, policy_id: Optional[str] = None
|
||
) -> FederationPolicy:
|
||
"""Create account federation policy.
|
||
|
||
:param service_principal_id: int
|
||
The service principal id for the federation policy.
|
||
:param policy: :class:`FederationPolicy`
|
||
:param policy_id: str (optional)
|
||
The identifier for the federation policy. The identifier must contain only lowercase alphanumeric
|
||
characters, numbers, hyphens, and slashes. If unspecified, the id will be assigned by Databricks.
|
||
|
||
:returns: :class:`FederationPolicy`
|
||
"""
|
||
|
||
body = policy.as_dict()
|
||
query = {}
|
||
if policy_id is not None:
|
||
query["policy_id"] = policy_id
|
||
headers = {
|
||
"Accept": "application/json",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"POST",
|
||
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies",
|
||
query=query,
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
return FederationPolicy.from_dict(res)
|
||
|
||
def delete(self, service_principal_id: int, policy_id: str):
|
||
"""Delete account federation policy.
|
||
|
||
:param service_principal_id: int
|
||
The service principal id for the federation policy.
|
||
:param policy_id: str
|
||
The identifier for the federation policy.
|
||
|
||
|
||
"""
|
||
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
self._api.do(
|
||
"DELETE",
|
||
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies/{policy_id}",
|
||
headers=headers,
|
||
)
|
||
|
||
def get(self, service_principal_id: int, policy_id: str) -> FederationPolicy:
|
||
"""Get account federation policy.
|
||
|
||
:param service_principal_id: int
|
||
The service principal id for the federation policy.
|
||
:param policy_id: str
|
||
The identifier for the federation policy.
|
||
|
||
:returns: :class:`FederationPolicy`
|
||
"""
|
||
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"GET",
|
||
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies/{policy_id}",
|
||
headers=headers,
|
||
)
|
||
return FederationPolicy.from_dict(res)
|
||
|
||
def list(
|
||
self, service_principal_id: int, *, page_size: Optional[int] = None, page_token: Optional[str] = None
|
||
) -> Iterator[FederationPolicy]:
|
||
"""List account federation policies.
|
||
|
||
:param service_principal_id: int
|
||
The service principal id for the federation policy.
|
||
:param page_size: int (optional)
|
||
:param page_token: str (optional)
|
||
|
||
:returns: Iterator over :class:`FederationPolicy`
|
||
"""
|
||
|
||
query = {}
|
||
if page_size is not None:
|
||
query["page_size"] = page_size
|
||
if page_token is not None:
|
||
query["page_token"] = page_token
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
while True:
|
||
json = self._api.do(
|
||
"GET",
|
||
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies",
|
||
query=query,
|
||
headers=headers,
|
||
)
|
||
if "policies" in json:
|
||
for v in json["policies"]:
|
||
yield FederationPolicy.from_dict(v)
|
||
if "next_page_token" not in json or not json["next_page_token"]:
|
||
return
|
||
query["page_token"] = json["next_page_token"]
|
||
|
||
def update(
|
||
self, service_principal_id: int, policy_id: str, policy: FederationPolicy, *, update_mask: Optional[str] = None
|
||
) -> FederationPolicy:
|
||
"""Update account federation policy.
|
||
|
||
:param service_principal_id: int
|
||
The service principal id for the federation policy.
|
||
:param policy_id: str
|
||
The identifier for the federation policy.
|
||
:param policy: :class:`FederationPolicy`
|
||
:param update_mask: str (optional)
|
||
The field mask specifies which fields of the policy to update. To specify multiple fields in the
|
||
field mask, use comma as the separator (no space). The special value '*' indicates that all fields
|
||
should be updated (full replacement). If unspecified, all fields that are set in the policy provided
|
||
in the update request will overwrite the corresponding fields in the existing policy. Example value:
|
||
'description,oidc_policy.audiences'.
|
||
|
||
:returns: :class:`FederationPolicy`
|
||
"""
|
||
|
||
body = policy.as_dict()
|
||
query = {}
|
||
if update_mask is not None:
|
||
query["update_mask"] = update_mask
|
||
headers = {
|
||
"Accept": "application/json",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"PATCH",
|
||
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies/{policy_id}",
|
||
query=query,
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
return FederationPolicy.from_dict(res)
|
||
|
||
|
||
class ServicePrincipalSecretsAPI:
|
||
"""These APIs enable administrators to manage service principal secrets.
|
||
|
||
You can use the generated secrets to obtain OAuth access tokens for a service principal, which can then be
|
||
used to access Databricks Accounts and Workspace APIs. For more information, see [Authentication using
|
||
OAuth tokens for service principals].
|
||
|
||
In addition, the generated secrets can be used to configure the Databricks Terraform Provider to
|
||
authenticate with the service principal. For more information, see [Databricks Terraform Provider].
|
||
|
||
[Authentication using OAuth tokens for service principals]: https://docs.databricks.com/dev-tools/authentication-oauth.html
|
||
[Databricks Terraform Provider]: https://github.com/databricks/terraform-provider-databricks/blob/master/docs/index.md#authenticating-with-service-principal
|
||
"""
|
||
|
||
def __init__(self, api_client):
|
||
self._api = api_client
|
||
|
||
def create(
|
||
self, service_principal_id: str, *, lifetime: Optional[str] = None
|
||
) -> CreateServicePrincipalSecretResponse:
|
||
"""Create a secret for the given service principal.
|
||
|
||
:param service_principal_id: str
|
||
The service principal ID.
|
||
:param lifetime: str (optional)
|
||
The lifetime of the secret in seconds. If this parameter is not provided, the secret will have a
|
||
default lifetime of 730 days (63072000s).
|
||
|
||
:returns: :class:`CreateServicePrincipalSecretResponse`
|
||
"""
|
||
|
||
body = {}
|
||
if lifetime is not None:
|
||
body["lifetime"] = lifetime
|
||
headers = {
|
||
"Accept": "application/json",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
res = self._api.do(
|
||
"POST",
|
||
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/credentials/secrets",
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
return CreateServicePrincipalSecretResponse.from_dict(res)
|
||
|
||
def delete(self, service_principal_id: str, secret_id: str):
|
||
"""Delete a secret from the given service principal.
|
||
|
||
:param service_principal_id: str
|
||
The service principal ID.
|
||
:param secret_id: str
|
||
The secret ID.
|
||
|
||
|
||
"""
|
||
|
||
headers = {}
|
||
|
||
self._api.do(
|
||
"DELETE",
|
||
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/credentials/secrets/{secret_id}",
|
||
headers=headers,
|
||
)
|
||
|
||
def list(
|
||
self, service_principal_id: str, *, page_size: Optional[int] = None, page_token: Optional[str] = None
|
||
) -> Iterator[SecretInfo]:
|
||
"""List all secrets associated with the given service principal. This operation only returns information
|
||
about the secrets themselves and does not include the secret values.
|
||
|
||
:param service_principal_id: str
|
||
The service principal ID.
|
||
:param page_size: int (optional)
|
||
:param page_token: str (optional)
|
||
An opaque page token which was the `next_page_token` in the response of the previous request to list
|
||
the secrets for this service principal. Provide this token to retrieve the next page of secret
|
||
entries. When providing a `page_token`, all other parameters provided to the request must match the
|
||
previous request. To list all of the secrets for a service principal, it is necessary to continue
|
||
requesting pages of entries until the response contains no `next_page_token`. Note that the number
|
||
of entries returned must not be used to determine when the listing is complete.
|
||
|
||
:returns: Iterator over :class:`SecretInfo`
|
||
"""
|
||
|
||
query = {}
|
||
if page_size is not None:
|
||
query["page_size"] = page_size
|
||
if page_token is not None:
|
||
query["page_token"] = page_token
|
||
headers = {
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
while True:
|
||
json = self._api.do(
|
||
"GET",
|
||
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/credentials/secrets",
|
||
query=query,
|
||
headers=headers,
|
||
)
|
||
if "secrets" in json:
|
||
for v in json["secrets"]:
|
||
yield SecretInfo.from_dict(v)
|
||
if "next_page_token" not in json or not json["next_page_token"]:
|
||
return
|
||
query["page_token"] = json["next_page_token"]
|
||
|
||
|
||
class ServicePrincipalSecretsProxyAPI:
|
||
"""These APIs enable administrators to manage service principal secrets at the workspace level. To use these
|
||
APIs, the service principal must be first added to the current workspace.
|
||
|
||
You can use the generated secrets to obtain OAuth access tokens for a service principal, which can then be
|
||
used to access Databricks Accounts and Workspace APIs. For more information, see [Authentication using
|
||
OAuth tokens for service principals].
|
||
|
||
In addition, the generated secrets can be used to configure the Databricks Terraform Providerto
|
||
authenticate with the service principal. For more information, see [Databricks Terraform Provider].
|
||
|
||
[Authentication using OAuth tokens for service principals]: https://docs.databricks.com/dev-tools/authentication-oauth.html
|
||
[Databricks Terraform Provider]: https://github.com/databricks/terraform-provider-databricks/blob/master/docs/index.md#authenticating-with-service-principal
|
||
"""
|
||
|
||
def __init__(self, api_client):
|
||
self._api = api_client
|
||
|
||
def create(
|
||
self, service_principal_id: str, *, lifetime: Optional[str] = None
|
||
) -> CreateServicePrincipalSecretResponse:
|
||
"""Create a secret for the given service principal.
|
||
|
||
:param service_principal_id: str
|
||
The service principal ID.
|
||
:param lifetime: str (optional)
|
||
The lifetime of the secret in seconds. If this parameter is not provided, the secret will have a
|
||
default lifetime of 730 days (63072000s).
|
||
|
||
:returns: :class:`CreateServicePrincipalSecretResponse`
|
||
"""
|
||
|
||
body = {}
|
||
if lifetime is not None:
|
||
body["lifetime"] = lifetime
|
||
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",
|
||
f"/api/2.0/accounts/servicePrincipals/{service_principal_id}/credentials/secrets",
|
||
body=body,
|
||
headers=headers,
|
||
)
|
||
return CreateServicePrincipalSecretResponse.from_dict(res)
|
||
|
||
def delete(self, service_principal_id: str, secret_id: str):
|
||
"""Delete a secret from the given service principal.
|
||
|
||
:param service_principal_id: str
|
||
The service principal ID.
|
||
:param secret_id: str
|
||
The secret ID.
|
||
|
||
|
||
"""
|
||
|
||
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/accounts/servicePrincipals/{service_principal_id}/credentials/secrets/{secret_id}",
|
||
headers=headers,
|
||
)
|
||
|
||
def list(
|
||
self, service_principal_id: str, *, page_size: Optional[int] = None, page_token: Optional[str] = None
|
||
) -> Iterator[SecretInfo]:
|
||
"""List all secrets associated with the given service principal. This operation only returns information
|
||
about the secrets themselves and does not include the secret values.
|
||
|
||
:param service_principal_id: str
|
||
The service principal ID.
|
||
:param page_size: int (optional)
|
||
:param page_token: str (optional)
|
||
An opaque page token which was the `next_page_token` in the response of the previous request to list
|
||
the secrets for this service principal. Provide this token to retrieve the next page of secret
|
||
entries. When providing a `page_token`, all other parameters provided to the request must match the
|
||
previous request. To list all of the secrets for a service principal, it is necessary to continue
|
||
requesting pages of entries until the response contains no `next_page_token`. Note that the number
|
||
of entries returned must not be used to determine when the listing is complete.
|
||
|
||
:returns: Iterator over :class:`SecretInfo`
|
||
"""
|
||
|
||
query = {}
|
||
if page_size is not None:
|
||
query["page_size"] = page_size
|
||
if page_token is not None:
|
||
query["page_token"] = page_token
|
||
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
|
||
|
||
while True:
|
||
json = self._api.do(
|
||
"GET",
|
||
f"/api/2.0/accounts/servicePrincipals/{service_principal_id}/credentials/secrets",
|
||
query=query,
|
||
headers=headers,
|
||
)
|
||
if "secrets" in json:
|
||
for v in json["secrets"]:
|
||
yield SecretInfo.from_dict(v)
|
||
if "next_page_token" not in json or not json["next_page_token"]:
|
||
return
|
||
query["page_token"] = json["next_page_token"]
|