databricks-sdk 0.39.0__py3-none-any.whl → 0.41.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of databricks-sdk might be problematic. Click here for more details.
- databricks/sdk/__init__.py +38 -4
- databricks/sdk/_base_client.py +16 -3
- databricks/sdk/config.py +5 -0
- databricks/sdk/credentials_provider.py +23 -14
- databricks/sdk/data_plane.py +1 -1
- databricks/sdk/mixins/files.py +184 -1
- databricks/sdk/mixins/open_ai_client.py +40 -1
- databricks/sdk/service/apps.py +12 -4
- databricks/sdk/service/catalog.py +3 -2
- databricks/sdk/service/cleanrooms.py +2 -1
- databricks/sdk/service/compute.py +365 -63
- databricks/sdk/service/dashboards.py +23 -6
- databricks/sdk/service/files.py +6 -3
- databricks/sdk/service/iam.py +158 -0
- databricks/sdk/service/jobs.py +257 -30
- databricks/sdk/service/oauth2.py +498 -29
- databricks/sdk/service/pipelines.py +92 -15
- databricks/sdk/service/serving.py +423 -215
- databricks/sdk/service/sharing.py +51 -54
- databricks/sdk/version.py +1 -1
- {databricks_sdk-0.39.0.dist-info → databricks_sdk-0.41.0.dist-info}/METADATA +26 -26
- {databricks_sdk-0.39.0.dist-info → databricks_sdk-0.41.0.dist-info}/RECORD +26 -26
- {databricks_sdk-0.39.0.dist-info → databricks_sdk-0.41.0.dist-info}/WHEEL +1 -1
- {databricks_sdk-0.39.0.dist-info → databricks_sdk-0.41.0.dist-info}/LICENSE +0 -0
- {databricks_sdk-0.39.0.dist-info → databricks_sdk-0.41.0.dist-info}/NOTICE +0 -0
- {databricks_sdk-0.39.0.dist-info → databricks_sdk-0.41.0.dist-info}/top_level.txt +0 -0
databricks/sdk/service/oauth2.py
CHANGED
|
@@ -202,35 +202,6 @@ class CreateServicePrincipalSecretResponse:
|
|
|
202
202
|
update_time=d.get('update_time', None))
|
|
203
203
|
|
|
204
204
|
|
|
205
|
-
@dataclass
|
|
206
|
-
class DataPlaneInfo:
|
|
207
|
-
authorization_details: Optional[str] = None
|
|
208
|
-
"""Authorization details as a string."""
|
|
209
|
-
|
|
210
|
-
endpoint_url: Optional[str] = None
|
|
211
|
-
"""The URL of the endpoint for this operation in the dataplane."""
|
|
212
|
-
|
|
213
|
-
def as_dict(self) -> dict:
|
|
214
|
-
"""Serializes the DataPlaneInfo into a dictionary suitable for use as a JSON request body."""
|
|
215
|
-
body = {}
|
|
216
|
-
if self.authorization_details is not None: body['authorization_details'] = self.authorization_details
|
|
217
|
-
if self.endpoint_url is not None: body['endpoint_url'] = self.endpoint_url
|
|
218
|
-
return body
|
|
219
|
-
|
|
220
|
-
def as_shallow_dict(self) -> dict:
|
|
221
|
-
"""Serializes the DataPlaneInfo into a shallow dictionary of its immediate attributes."""
|
|
222
|
-
body = {}
|
|
223
|
-
if self.authorization_details is not None: body['authorization_details'] = self.authorization_details
|
|
224
|
-
if self.endpoint_url is not None: body['endpoint_url'] = self.endpoint_url
|
|
225
|
-
return body
|
|
226
|
-
|
|
227
|
-
@classmethod
|
|
228
|
-
def from_dict(cls, d: Dict[str, any]) -> DataPlaneInfo:
|
|
229
|
-
"""Deserializes the DataPlaneInfo from a dictionary."""
|
|
230
|
-
return cls(authorization_details=d.get('authorization_details', None),
|
|
231
|
-
endpoint_url=d.get('endpoint_url', None))
|
|
232
|
-
|
|
233
|
-
|
|
234
205
|
@dataclass
|
|
235
206
|
class DeleteCustomAppIntegrationOutput:
|
|
236
207
|
|
|
@@ -288,6 +259,65 @@ class DeleteResponse:
|
|
|
288
259
|
return cls()
|
|
289
260
|
|
|
290
261
|
|
|
262
|
+
@dataclass
|
|
263
|
+
class FederationPolicy:
|
|
264
|
+
create_time: Optional[str] = None
|
|
265
|
+
"""Creation time of the federation policy."""
|
|
266
|
+
|
|
267
|
+
description: Optional[str] = None
|
|
268
|
+
"""Description of the federation policy."""
|
|
269
|
+
|
|
270
|
+
name: Optional[str] = None
|
|
271
|
+
"""Resource name for the federation policy. Example values include
|
|
272
|
+
`accounts/<account-id>/federationPolicies/my-federation-policy` for Account Federation Policies,
|
|
273
|
+
and
|
|
274
|
+
`accounts/<account-id>/servicePrincipals/<service-principal-id>/federationPolicies/my-federation-policy`
|
|
275
|
+
for Service Principal Federation Policies. Typically an output parameter, which does not need to
|
|
276
|
+
be specified in create or update requests. If specified in a request, must match the value in
|
|
277
|
+
the request URL."""
|
|
278
|
+
|
|
279
|
+
oidc_policy: Optional[OidcFederationPolicy] = None
|
|
280
|
+
"""Specifies the policy to use for validating OIDC claims in your federated tokens."""
|
|
281
|
+
|
|
282
|
+
uid: Optional[str] = None
|
|
283
|
+
"""Unique, immutable id of the federation policy."""
|
|
284
|
+
|
|
285
|
+
update_time: Optional[str] = None
|
|
286
|
+
"""Last update time of the federation policy."""
|
|
287
|
+
|
|
288
|
+
def as_dict(self) -> dict:
|
|
289
|
+
"""Serializes the FederationPolicy into a dictionary suitable for use as a JSON request body."""
|
|
290
|
+
body = {}
|
|
291
|
+
if self.create_time is not None: body['create_time'] = self.create_time
|
|
292
|
+
if self.description is not None: body['description'] = self.description
|
|
293
|
+
if self.name is not None: body['name'] = self.name
|
|
294
|
+
if self.oidc_policy: body['oidc_policy'] = self.oidc_policy.as_dict()
|
|
295
|
+
if self.uid is not None: body['uid'] = self.uid
|
|
296
|
+
if self.update_time is not None: body['update_time'] = self.update_time
|
|
297
|
+
return body
|
|
298
|
+
|
|
299
|
+
def as_shallow_dict(self) -> dict:
|
|
300
|
+
"""Serializes the FederationPolicy into a shallow dictionary of its immediate attributes."""
|
|
301
|
+
body = {}
|
|
302
|
+
if self.create_time is not None: body['create_time'] = self.create_time
|
|
303
|
+
if self.description is not None: body['description'] = self.description
|
|
304
|
+
if self.name is not None: body['name'] = self.name
|
|
305
|
+
if self.oidc_policy: body['oidc_policy'] = self.oidc_policy
|
|
306
|
+
if self.uid is not None: body['uid'] = self.uid
|
|
307
|
+
if self.update_time is not None: body['update_time'] = self.update_time
|
|
308
|
+
return body
|
|
309
|
+
|
|
310
|
+
@classmethod
|
|
311
|
+
def from_dict(cls, d: Dict[str, any]) -> FederationPolicy:
|
|
312
|
+
"""Deserializes the FederationPolicy from a dictionary."""
|
|
313
|
+
return cls(create_time=d.get('create_time', None),
|
|
314
|
+
description=d.get('description', None),
|
|
315
|
+
name=d.get('name', None),
|
|
316
|
+
oidc_policy=_from_dict(d, 'oidc_policy', OidcFederationPolicy),
|
|
317
|
+
uid=d.get('uid', None),
|
|
318
|
+
update_time=d.get('update_time', None))
|
|
319
|
+
|
|
320
|
+
|
|
291
321
|
@dataclass
|
|
292
322
|
class GetCustomAppIntegrationOutput:
|
|
293
323
|
client_id: Optional[str] = None
|
|
@@ -498,6 +528,33 @@ class GetPublishedAppsOutput:
|
|
|
498
528
|
next_page_token=d.get('next_page_token', None))
|
|
499
529
|
|
|
500
530
|
|
|
531
|
+
@dataclass
|
|
532
|
+
class ListFederationPoliciesResponse:
|
|
533
|
+
next_page_token: Optional[str] = None
|
|
534
|
+
|
|
535
|
+
policies: Optional[List[FederationPolicy]] = None
|
|
536
|
+
|
|
537
|
+
def as_dict(self) -> dict:
|
|
538
|
+
"""Serializes the ListFederationPoliciesResponse into a dictionary suitable for use as a JSON request body."""
|
|
539
|
+
body = {}
|
|
540
|
+
if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
|
|
541
|
+
if self.policies: body['policies'] = [v.as_dict() for v in self.policies]
|
|
542
|
+
return body
|
|
543
|
+
|
|
544
|
+
def as_shallow_dict(self) -> dict:
|
|
545
|
+
"""Serializes the ListFederationPoliciesResponse into a shallow dictionary of its immediate attributes."""
|
|
546
|
+
body = {}
|
|
547
|
+
if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
|
|
548
|
+
if self.policies: body['policies'] = self.policies
|
|
549
|
+
return body
|
|
550
|
+
|
|
551
|
+
@classmethod
|
|
552
|
+
def from_dict(cls, d: Dict[str, any]) -> ListFederationPoliciesResponse:
|
|
553
|
+
"""Deserializes the ListFederationPoliciesResponse from a dictionary."""
|
|
554
|
+
return cls(next_page_token=d.get('next_page_token', None),
|
|
555
|
+
policies=_repeated_dict(d, 'policies', FederationPolicy))
|
|
556
|
+
|
|
557
|
+
|
|
501
558
|
@dataclass
|
|
502
559
|
class ListServicePrincipalSecretsResponse:
|
|
503
560
|
next_page_token: Optional[str] = None
|
|
@@ -527,6 +584,64 @@ class ListServicePrincipalSecretsResponse:
|
|
|
527
584
|
secrets=_repeated_dict(d, 'secrets', SecretInfo))
|
|
528
585
|
|
|
529
586
|
|
|
587
|
+
@dataclass
|
|
588
|
+
class OidcFederationPolicy:
|
|
589
|
+
"""Specifies the policy to use for validating OIDC claims in your federated tokens."""
|
|
590
|
+
|
|
591
|
+
audiences: Optional[List[str]] = None
|
|
592
|
+
"""The allowed token audiences, as specified in the 'aud' claim of federated tokens. The audience
|
|
593
|
+
identifier is intended to represent the recipient of the token. Can be any non-empty string
|
|
594
|
+
value. As long as the audience in the token matches at least one audience in the policy, the
|
|
595
|
+
token is considered a match. If audiences is unspecified, defaults to your Databricks account
|
|
596
|
+
id."""
|
|
597
|
+
|
|
598
|
+
issuer: Optional[str] = None
|
|
599
|
+
"""The required token issuer, as specified in the 'iss' claim of federated tokens."""
|
|
600
|
+
|
|
601
|
+
jwks_json: Optional[str] = None
|
|
602
|
+
"""The public keys used to validate the signature of federated tokens, in JWKS format. If
|
|
603
|
+
unspecified (recommended), Databricks automatically fetches the public keys from your issuer’s
|
|
604
|
+
well known endpoint. Databricks strongly recommends relying on your issuer’s well known
|
|
605
|
+
endpoint for discovering public keys."""
|
|
606
|
+
|
|
607
|
+
subject: Optional[str] = None
|
|
608
|
+
"""The required token subject, as specified in the subject claim of federated tokens. Must be
|
|
609
|
+
specified for service principal federation policies. Must not be specified for account
|
|
610
|
+
federation policies."""
|
|
611
|
+
|
|
612
|
+
subject_claim: Optional[str] = None
|
|
613
|
+
"""The claim that contains the subject of the token. If unspecified, the default value is 'sub'."""
|
|
614
|
+
|
|
615
|
+
def as_dict(self) -> dict:
|
|
616
|
+
"""Serializes the OidcFederationPolicy into a dictionary suitable for use as a JSON request body."""
|
|
617
|
+
body = {}
|
|
618
|
+
if self.audiences: body['audiences'] = [v for v in self.audiences]
|
|
619
|
+
if self.issuer is not None: body['issuer'] = self.issuer
|
|
620
|
+
if self.jwks_json is not None: body['jwks_json'] = self.jwks_json
|
|
621
|
+
if self.subject is not None: body['subject'] = self.subject
|
|
622
|
+
if self.subject_claim is not None: body['subject_claim'] = self.subject_claim
|
|
623
|
+
return body
|
|
624
|
+
|
|
625
|
+
def as_shallow_dict(self) -> dict:
|
|
626
|
+
"""Serializes the OidcFederationPolicy into a shallow dictionary of its immediate attributes."""
|
|
627
|
+
body = {}
|
|
628
|
+
if self.audiences: body['audiences'] = self.audiences
|
|
629
|
+
if self.issuer is not None: body['issuer'] = self.issuer
|
|
630
|
+
if self.jwks_json is not None: body['jwks_json'] = self.jwks_json
|
|
631
|
+
if self.subject is not None: body['subject'] = self.subject
|
|
632
|
+
if self.subject_claim is not None: body['subject_claim'] = self.subject_claim
|
|
633
|
+
return body
|
|
634
|
+
|
|
635
|
+
@classmethod
|
|
636
|
+
def from_dict(cls, d: Dict[str, any]) -> OidcFederationPolicy:
|
|
637
|
+
"""Deserializes the OidcFederationPolicy from a dictionary."""
|
|
638
|
+
return cls(audiences=d.get('audiences', None),
|
|
639
|
+
issuer=d.get('issuer', None),
|
|
640
|
+
jwks_json=d.get('jwks_json', None),
|
|
641
|
+
subject=d.get('subject', None),
|
|
642
|
+
subject_claim=d.get('subject_claim', None))
|
|
643
|
+
|
|
644
|
+
|
|
530
645
|
@dataclass
|
|
531
646
|
class PublishedAppOutput:
|
|
532
647
|
app_id: Optional[str] = None
|
|
@@ -676,6 +791,10 @@ class UpdateCustomAppIntegration:
|
|
|
676
791
|
redirect_urls: Optional[List[str]] = None
|
|
677
792
|
"""List of OAuth redirect urls to be updated in the custom OAuth app integration"""
|
|
678
793
|
|
|
794
|
+
scopes: Optional[List[str]] = None
|
|
795
|
+
"""List of OAuth scopes to be updated in the custom OAuth app integration, similar to redirect URIs
|
|
796
|
+
this will fully replace the existing values instead of appending"""
|
|
797
|
+
|
|
679
798
|
token_access_policy: Optional[TokenAccessPolicy] = None
|
|
680
799
|
"""Token access policy to be updated in the custom OAuth app integration"""
|
|
681
800
|
|
|
@@ -684,6 +803,7 @@ class UpdateCustomAppIntegration:
|
|
|
684
803
|
body = {}
|
|
685
804
|
if self.integration_id is not None: body['integration_id'] = self.integration_id
|
|
686
805
|
if self.redirect_urls: body['redirect_urls'] = [v for v in self.redirect_urls]
|
|
806
|
+
if self.scopes: body['scopes'] = [v for v in self.scopes]
|
|
687
807
|
if self.token_access_policy: body['token_access_policy'] = self.token_access_policy.as_dict()
|
|
688
808
|
return body
|
|
689
809
|
|
|
@@ -692,6 +812,7 @@ class UpdateCustomAppIntegration:
|
|
|
692
812
|
body = {}
|
|
693
813
|
if self.integration_id is not None: body['integration_id'] = self.integration_id
|
|
694
814
|
if self.redirect_urls: body['redirect_urls'] = self.redirect_urls
|
|
815
|
+
if self.scopes: body['scopes'] = self.scopes
|
|
695
816
|
if self.token_access_policy: body['token_access_policy'] = self.token_access_policy
|
|
696
817
|
return body
|
|
697
818
|
|
|
@@ -700,6 +821,7 @@ class UpdateCustomAppIntegration:
|
|
|
700
821
|
"""Deserializes the UpdateCustomAppIntegration from a dictionary."""
|
|
701
822
|
return cls(integration_id=d.get('integration_id', None),
|
|
702
823
|
redirect_urls=d.get('redirect_urls', None),
|
|
824
|
+
scopes=d.get('scopes', None),
|
|
703
825
|
token_access_policy=_from_dict(d, 'token_access_policy', TokenAccessPolicy))
|
|
704
826
|
|
|
705
827
|
|
|
@@ -769,6 +891,168 @@ class UpdatePublishedAppIntegrationOutput:
|
|
|
769
891
|
return cls()
|
|
770
892
|
|
|
771
893
|
|
|
894
|
+
class AccountFederationPolicyAPI:
|
|
895
|
+
"""These APIs manage account federation policies.
|
|
896
|
+
|
|
897
|
+
Account federation policies allow users and service principals in your Databricks account to securely
|
|
898
|
+
access Databricks APIs using tokens from your trusted identity providers (IdPs).
|
|
899
|
+
|
|
900
|
+
With token federation, your users and service principals can exchange tokens from your IdP for Databricks
|
|
901
|
+
OAuth tokens, which can be used to access Databricks APIs. Token federation eliminates the need to manage
|
|
902
|
+
Databricks secrets, and allows you to centralize management of token issuance policies in your IdP.
|
|
903
|
+
Databricks token federation is typically used in combination with [SCIM], so users in your IdP are
|
|
904
|
+
synchronized into your Databricks account.
|
|
905
|
+
|
|
906
|
+
Token federation is configured in your Databricks account using an account federation policy. An account
|
|
907
|
+
federation policy specifies: * which IdP, or issuer, your Databricks account should accept tokens from *
|
|
908
|
+
how to determine which Databricks user, or subject, a token is issued for
|
|
909
|
+
|
|
910
|
+
To configure a federation policy, you provide the following: * The required token __issuer__, as specified
|
|
911
|
+
in the “iss” claim of your tokens. The issuer is an https URL that identifies your IdP. * The allowed
|
|
912
|
+
token __audiences__, as specified in the “aud” claim of your tokens. This identifier is intended to
|
|
913
|
+
represent the recipient of the token. As long as the audience in the token matches at least one audience
|
|
914
|
+
in the policy, the token is considered a match. If unspecified, the default value is your Databricks
|
|
915
|
+
account id. * The __subject claim__, which indicates which token claim contains the Databricks username of
|
|
916
|
+
the user the token was issued for. If unspecified, the default value is “sub”. * Optionally, the
|
|
917
|
+
public keys used to validate the signature of your tokens, in JWKS format. If unspecified (recommended),
|
|
918
|
+
Databricks automatically fetches the public keys from your issuer’s well known endpoint. Databricks
|
|
919
|
+
strongly recommends relying on your issuer’s well known endpoint for discovering public keys.
|
|
920
|
+
|
|
921
|
+
An example federation policy is: ``` issuer: "https://idp.mycompany.com/oidc" audiences: ["databricks"]
|
|
922
|
+
subject_claim: "sub" ```
|
|
923
|
+
|
|
924
|
+
An example JWT token body that matches this policy and could be used to authenticate to Databricks as user
|
|
925
|
+
`username@mycompany.com` is: ``` { "iss": "https://idp.mycompany.com/oidc", "aud": "databricks", "sub":
|
|
926
|
+
"username@mycompany.com" } ```
|
|
927
|
+
|
|
928
|
+
You may also need to configure your IdP to generate tokens for your users to exchange with Databricks, if
|
|
929
|
+
your users do not already have the ability to generate tokens that are compatible with your federation
|
|
930
|
+
policy.
|
|
931
|
+
|
|
932
|
+
You do not need to configure an OAuth application in Databricks to use token federation.
|
|
933
|
+
|
|
934
|
+
[SCIM]: https://docs.databricks.com/admin/users-groups/scim/index.html"""
|
|
935
|
+
|
|
936
|
+
def __init__(self, api_client):
|
|
937
|
+
self._api = api_client
|
|
938
|
+
|
|
939
|
+
def create(self,
|
|
940
|
+
*,
|
|
941
|
+
policy: Optional[FederationPolicy] = None,
|
|
942
|
+
policy_id: Optional[str] = None) -> FederationPolicy:
|
|
943
|
+
"""Create account federation policy.
|
|
944
|
+
|
|
945
|
+
:param policy: :class:`FederationPolicy` (optional)
|
|
946
|
+
:param policy_id: str (optional)
|
|
947
|
+
The identifier for the federation policy. The identifier must contain only lowercase alphanumeric
|
|
948
|
+
characters, numbers, hyphens, and slashes. If unspecified, the id will be assigned by Databricks.
|
|
949
|
+
|
|
950
|
+
:returns: :class:`FederationPolicy`
|
|
951
|
+
"""
|
|
952
|
+
body = policy.as_dict()
|
|
953
|
+
query = {}
|
|
954
|
+
if policy_id is not None: query['policy_id'] = policy_id
|
|
955
|
+
headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
|
|
956
|
+
|
|
957
|
+
res = self._api.do('POST',
|
|
958
|
+
f'/api/2.0/accounts/{self._api.account_id}/federationPolicies',
|
|
959
|
+
query=query,
|
|
960
|
+
body=body,
|
|
961
|
+
headers=headers)
|
|
962
|
+
return FederationPolicy.from_dict(res)
|
|
963
|
+
|
|
964
|
+
def delete(self, policy_id: str):
|
|
965
|
+
"""Delete account federation policy.
|
|
966
|
+
|
|
967
|
+
:param policy_id: str
|
|
968
|
+
The identifier for the federation policy.
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
"""
|
|
972
|
+
|
|
973
|
+
headers = {'Accept': 'application/json', }
|
|
974
|
+
|
|
975
|
+
self._api.do('DELETE',
|
|
976
|
+
f'/api/2.0/accounts/{self._api.account_id}/federationPolicies/{policy_id}',
|
|
977
|
+
headers=headers)
|
|
978
|
+
|
|
979
|
+
def get(self, policy_id: str) -> FederationPolicy:
|
|
980
|
+
"""Get account federation policy.
|
|
981
|
+
|
|
982
|
+
:param policy_id: str
|
|
983
|
+
The identifier for the federation policy.
|
|
984
|
+
|
|
985
|
+
:returns: :class:`FederationPolicy`
|
|
986
|
+
"""
|
|
987
|
+
|
|
988
|
+
headers = {'Accept': 'application/json', }
|
|
989
|
+
|
|
990
|
+
res = self._api.do('GET',
|
|
991
|
+
f'/api/2.0/accounts/{self._api.account_id}/federationPolicies/{policy_id}',
|
|
992
|
+
headers=headers)
|
|
993
|
+
return FederationPolicy.from_dict(res)
|
|
994
|
+
|
|
995
|
+
def list(self,
|
|
996
|
+
*,
|
|
997
|
+
page_size: Optional[int] = None,
|
|
998
|
+
page_token: Optional[str] = None) -> Iterator[FederationPolicy]:
|
|
999
|
+
"""List account federation policies.
|
|
1000
|
+
|
|
1001
|
+
:param page_size: int (optional)
|
|
1002
|
+
:param page_token: str (optional)
|
|
1003
|
+
|
|
1004
|
+
:returns: Iterator over :class:`FederationPolicy`
|
|
1005
|
+
"""
|
|
1006
|
+
|
|
1007
|
+
query = {}
|
|
1008
|
+
if page_size is not None: query['page_size'] = page_size
|
|
1009
|
+
if page_token is not None: query['page_token'] = page_token
|
|
1010
|
+
headers = {'Accept': 'application/json', }
|
|
1011
|
+
|
|
1012
|
+
while True:
|
|
1013
|
+
json = self._api.do('GET',
|
|
1014
|
+
f'/api/2.0/accounts/{self._api.account_id}/federationPolicies',
|
|
1015
|
+
query=query,
|
|
1016
|
+
headers=headers)
|
|
1017
|
+
if 'policies' in json:
|
|
1018
|
+
for v in json['policies']:
|
|
1019
|
+
yield FederationPolicy.from_dict(v)
|
|
1020
|
+
if 'next_page_token' not in json or not json['next_page_token']:
|
|
1021
|
+
return
|
|
1022
|
+
query['page_token'] = json['next_page_token']
|
|
1023
|
+
|
|
1024
|
+
def update(self,
|
|
1025
|
+
policy_id: str,
|
|
1026
|
+
*,
|
|
1027
|
+
policy: Optional[FederationPolicy] = None,
|
|
1028
|
+
update_mask: Optional[str] = None) -> FederationPolicy:
|
|
1029
|
+
"""Update account federation policy.
|
|
1030
|
+
|
|
1031
|
+
:param policy_id: str
|
|
1032
|
+
The identifier for the federation policy.
|
|
1033
|
+
:param policy: :class:`FederationPolicy` (optional)
|
|
1034
|
+
:param update_mask: str (optional)
|
|
1035
|
+
The field mask specifies which fields of the policy to update. To specify multiple fields in the
|
|
1036
|
+
field mask, use comma as the separator (no space). The special value '*' indicates that all fields
|
|
1037
|
+
should be updated (full replacement). If unspecified, all fields that are set in the policy provided
|
|
1038
|
+
in the update request will overwrite the corresponding fields in the existing policy. Example value:
|
|
1039
|
+
'description,oidc_policy.audiences'.
|
|
1040
|
+
|
|
1041
|
+
:returns: :class:`FederationPolicy`
|
|
1042
|
+
"""
|
|
1043
|
+
body = policy.as_dict()
|
|
1044
|
+
query = {}
|
|
1045
|
+
if update_mask is not None: query['update_mask'] = update_mask
|
|
1046
|
+
headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
|
|
1047
|
+
|
|
1048
|
+
res = self._api.do('PATCH',
|
|
1049
|
+
f'/api/2.0/accounts/{self._api.account_id}/federationPolicies/{policy_id}',
|
|
1050
|
+
query=query,
|
|
1051
|
+
body=body,
|
|
1052
|
+
headers=headers)
|
|
1053
|
+
return FederationPolicy.from_dict(res)
|
|
1054
|
+
|
|
1055
|
+
|
|
772
1056
|
class CustomAppIntegrationAPI:
|
|
773
1057
|
"""These APIs enable administrators to manage custom OAuth app integrations, which is required for
|
|
774
1058
|
adding/using Custom OAuth App Integration like Tableau Cloud for Databricks in AWS cloud."""
|
|
@@ -892,6 +1176,7 @@ class CustomAppIntegrationAPI:
|
|
|
892
1176
|
integration_id: str,
|
|
893
1177
|
*,
|
|
894
1178
|
redirect_urls: Optional[List[str]] = None,
|
|
1179
|
+
scopes: Optional[List[str]] = None,
|
|
895
1180
|
token_access_policy: Optional[TokenAccessPolicy] = None):
|
|
896
1181
|
"""Updates Custom OAuth App Integration.
|
|
897
1182
|
|
|
@@ -901,6 +1186,9 @@ class CustomAppIntegrationAPI:
|
|
|
901
1186
|
:param integration_id: str
|
|
902
1187
|
:param redirect_urls: List[str] (optional)
|
|
903
1188
|
List of OAuth redirect urls to be updated in the custom OAuth app integration
|
|
1189
|
+
:param scopes: List[str] (optional)
|
|
1190
|
+
List of OAuth scopes to be updated in the custom OAuth app integration, similar to redirect URIs
|
|
1191
|
+
this will fully replace the existing values instead of appending
|
|
904
1192
|
:param token_access_policy: :class:`TokenAccessPolicy` (optional)
|
|
905
1193
|
Token access policy to be updated in the custom OAuth app integration
|
|
906
1194
|
|
|
@@ -908,6 +1196,7 @@ class CustomAppIntegrationAPI:
|
|
|
908
1196
|
"""
|
|
909
1197
|
body = {}
|
|
910
1198
|
if redirect_urls is not None: body['redirect_urls'] = [v for v in redirect_urls]
|
|
1199
|
+
if scopes is not None: body['scopes'] = [v for v in scopes]
|
|
911
1200
|
if token_access_policy is not None: body['token_access_policy'] = token_access_policy.as_dict()
|
|
912
1201
|
headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
|
|
913
1202
|
|
|
@@ -1086,6 +1375,186 @@ class PublishedAppIntegrationAPI:
|
|
|
1086
1375
|
headers=headers)
|
|
1087
1376
|
|
|
1088
1377
|
|
|
1378
|
+
class ServicePrincipalFederationPolicyAPI:
|
|
1379
|
+
"""These APIs manage service principal federation policies.
|
|
1380
|
+
|
|
1381
|
+
Service principal federation, also known as Workload Identity Federation, allows your automated workloads
|
|
1382
|
+
running outside of Databricks to securely access Databricks APIs without the need for Databricks secrets.
|
|
1383
|
+
With Workload Identity Federation, your application (or workload) authenticates to Databricks as a
|
|
1384
|
+
Databricks service principal, using tokens provided by the workload runtime.
|
|
1385
|
+
|
|
1386
|
+
Databricks strongly recommends using Workload Identity Federation to authenticate to Databricks from
|
|
1387
|
+
automated workloads, over alternatives such as OAuth client secrets or Personal Access Tokens, whenever
|
|
1388
|
+
possible. Workload Identity Federation is supported by many popular services, including Github Actions,
|
|
1389
|
+
Azure DevOps, GitLab, Terraform Cloud, and Kubernetes clusters, among others.
|
|
1390
|
+
|
|
1391
|
+
Workload identity federation is configured in your Databricks account using a service principal federation
|
|
1392
|
+
policy. A service principal federation policy specifies: * which IdP, or issuer, the service principal is
|
|
1393
|
+
allowed to authenticate from * which workload identity, or subject, is allowed to authenticate as the
|
|
1394
|
+
Databricks service principal
|
|
1395
|
+
|
|
1396
|
+
To configure a federation policy, you provide the following: * The required token __issuer__, as specified
|
|
1397
|
+
in the “iss” claim of workload identity tokens. The issuer is an https URL that identifies the
|
|
1398
|
+
workload identity provider. * The required token __subject__, as specified in the “sub” claim of
|
|
1399
|
+
workload identity tokens. The subject uniquely identifies the workload in the workload runtime
|
|
1400
|
+
environment. * The allowed token __audiences__, as specified in the “aud” claim of workload identity
|
|
1401
|
+
tokens. The audience is intended to represent the recipient of the token. As long as the audience in the
|
|
1402
|
+
token matches at least one audience in the policy, the token is considered a match. If unspecified, the
|
|
1403
|
+
default value is your Databricks account id. * Optionally, the public keys used to validate the signature
|
|
1404
|
+
of the workload identity tokens, in JWKS format. If unspecified (recommended), Databricks automatically
|
|
1405
|
+
fetches the public keys from the issuer’s well known endpoint. Databricks strongly recommends relying on
|
|
1406
|
+
the issuer’s well known endpoint for discovering public keys.
|
|
1407
|
+
|
|
1408
|
+
An example service principal federation policy, for a Github Actions workload, is: ``` issuer:
|
|
1409
|
+
"https://token.actions.githubusercontent.com" audiences: ["https://github.com/my-github-org"] subject:
|
|
1410
|
+
"repo:my-github-org/my-repo:environment:prod" ```
|
|
1411
|
+
|
|
1412
|
+
An example JWT token body that matches this policy and could be used to authenticate to Databricks is: ```
|
|
1413
|
+
{ "iss": "https://token.actions.githubusercontent.com", "aud": "https://github.com/my-github-org", "sub":
|
|
1414
|
+
"repo:my-github-org/my-repo:environment:prod" } ```
|
|
1415
|
+
|
|
1416
|
+
You may also need to configure the workload runtime to generate tokens for your workloads.
|
|
1417
|
+
|
|
1418
|
+
You do not need to configure an OAuth application in Databricks to use token federation."""
|
|
1419
|
+
|
|
1420
|
+
def __init__(self, api_client):
|
|
1421
|
+
self._api = api_client
|
|
1422
|
+
|
|
1423
|
+
def create(self,
|
|
1424
|
+
service_principal_id: int,
|
|
1425
|
+
*,
|
|
1426
|
+
policy: Optional[FederationPolicy] = None,
|
|
1427
|
+
policy_id: Optional[str] = None) -> FederationPolicy:
|
|
1428
|
+
"""Create service principal federation policy.
|
|
1429
|
+
|
|
1430
|
+
:param service_principal_id: int
|
|
1431
|
+
The service principal id for the federation policy.
|
|
1432
|
+
:param policy: :class:`FederationPolicy` (optional)
|
|
1433
|
+
:param policy_id: str (optional)
|
|
1434
|
+
The identifier for the federation policy. The identifier must contain only lowercase alphanumeric
|
|
1435
|
+
characters, numbers, hyphens, and slashes. If unspecified, the id will be assigned by Databricks.
|
|
1436
|
+
|
|
1437
|
+
:returns: :class:`FederationPolicy`
|
|
1438
|
+
"""
|
|
1439
|
+
body = policy.as_dict()
|
|
1440
|
+
query = {}
|
|
1441
|
+
if policy_id is not None: query['policy_id'] = policy_id
|
|
1442
|
+
headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
|
|
1443
|
+
|
|
1444
|
+
res = self._api.do(
|
|
1445
|
+
'POST',
|
|
1446
|
+
f'/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies',
|
|
1447
|
+
query=query,
|
|
1448
|
+
body=body,
|
|
1449
|
+
headers=headers)
|
|
1450
|
+
return FederationPolicy.from_dict(res)
|
|
1451
|
+
|
|
1452
|
+
def delete(self, service_principal_id: int, policy_id: str):
|
|
1453
|
+
"""Delete service principal federation policy.
|
|
1454
|
+
|
|
1455
|
+
:param service_principal_id: int
|
|
1456
|
+
The service principal id for the federation policy.
|
|
1457
|
+
:param policy_id: str
|
|
1458
|
+
The identifier for the federation policy.
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
"""
|
|
1462
|
+
|
|
1463
|
+
headers = {'Accept': 'application/json', }
|
|
1464
|
+
|
|
1465
|
+
self._api.do(
|
|
1466
|
+
'DELETE',
|
|
1467
|
+
f'/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies/{policy_id}',
|
|
1468
|
+
headers=headers)
|
|
1469
|
+
|
|
1470
|
+
def get(self, service_principal_id: int, policy_id: str) -> FederationPolicy:
|
|
1471
|
+
"""Get service principal federation policy.
|
|
1472
|
+
|
|
1473
|
+
:param service_principal_id: int
|
|
1474
|
+
The service principal id for the federation policy.
|
|
1475
|
+
:param policy_id: str
|
|
1476
|
+
The identifier for the federation policy.
|
|
1477
|
+
|
|
1478
|
+
:returns: :class:`FederationPolicy`
|
|
1479
|
+
"""
|
|
1480
|
+
|
|
1481
|
+
headers = {'Accept': 'application/json', }
|
|
1482
|
+
|
|
1483
|
+
res = self._api.do(
|
|
1484
|
+
'GET',
|
|
1485
|
+
f'/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies/{policy_id}',
|
|
1486
|
+
headers=headers)
|
|
1487
|
+
return FederationPolicy.from_dict(res)
|
|
1488
|
+
|
|
1489
|
+
def list(self,
|
|
1490
|
+
service_principal_id: int,
|
|
1491
|
+
*,
|
|
1492
|
+
page_size: Optional[int] = None,
|
|
1493
|
+
page_token: Optional[str] = None) -> Iterator[FederationPolicy]:
|
|
1494
|
+
"""List service principal federation policies.
|
|
1495
|
+
|
|
1496
|
+
:param service_principal_id: int
|
|
1497
|
+
The service principal id for the federation policy.
|
|
1498
|
+
:param page_size: int (optional)
|
|
1499
|
+
:param page_token: str (optional)
|
|
1500
|
+
|
|
1501
|
+
:returns: Iterator over :class:`FederationPolicy`
|
|
1502
|
+
"""
|
|
1503
|
+
|
|
1504
|
+
query = {}
|
|
1505
|
+
if page_size is not None: query['page_size'] = page_size
|
|
1506
|
+
if page_token is not None: query['page_token'] = page_token
|
|
1507
|
+
headers = {'Accept': 'application/json', }
|
|
1508
|
+
|
|
1509
|
+
while True:
|
|
1510
|
+
json = self._api.do(
|
|
1511
|
+
'GET',
|
|
1512
|
+
f'/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies',
|
|
1513
|
+
query=query,
|
|
1514
|
+
headers=headers)
|
|
1515
|
+
if 'policies' in json:
|
|
1516
|
+
for v in json['policies']:
|
|
1517
|
+
yield FederationPolicy.from_dict(v)
|
|
1518
|
+
if 'next_page_token' not in json or not json['next_page_token']:
|
|
1519
|
+
return
|
|
1520
|
+
query['page_token'] = json['next_page_token']
|
|
1521
|
+
|
|
1522
|
+
def update(self,
|
|
1523
|
+
service_principal_id: int,
|
|
1524
|
+
policy_id: str,
|
|
1525
|
+
*,
|
|
1526
|
+
policy: Optional[FederationPolicy] = None,
|
|
1527
|
+
update_mask: Optional[str] = None) -> FederationPolicy:
|
|
1528
|
+
"""Update service principal federation policy.
|
|
1529
|
+
|
|
1530
|
+
:param service_principal_id: int
|
|
1531
|
+
The service principal id for the federation policy.
|
|
1532
|
+
:param policy_id: str
|
|
1533
|
+
The identifier for the federation policy.
|
|
1534
|
+
:param policy: :class:`FederationPolicy` (optional)
|
|
1535
|
+
:param update_mask: str (optional)
|
|
1536
|
+
The field mask specifies which fields of the policy to update. To specify multiple fields in the
|
|
1537
|
+
field mask, use comma as the separator (no space). The special value '*' indicates that all fields
|
|
1538
|
+
should be updated (full replacement). If unspecified, all fields that are set in the policy provided
|
|
1539
|
+
in the update request will overwrite the corresponding fields in the existing policy. Example value:
|
|
1540
|
+
'description,oidc_policy.audiences'.
|
|
1541
|
+
|
|
1542
|
+
:returns: :class:`FederationPolicy`
|
|
1543
|
+
"""
|
|
1544
|
+
body = policy.as_dict()
|
|
1545
|
+
query = {}
|
|
1546
|
+
if update_mask is not None: query['update_mask'] = update_mask
|
|
1547
|
+
headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
|
|
1548
|
+
|
|
1549
|
+
res = self._api.do(
|
|
1550
|
+
'PATCH',
|
|
1551
|
+
f'/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies/{policy_id}',
|
|
1552
|
+
query=query,
|
|
1553
|
+
body=body,
|
|
1554
|
+
headers=headers)
|
|
1555
|
+
return FederationPolicy.from_dict(res)
|
|
1556
|
+
|
|
1557
|
+
|
|
1089
1558
|
class ServicePrincipalSecretsAPI:
|
|
1090
1559
|
"""These APIs enable administrators to manage service principal secrets.
|
|
1091
1560
|
|