2323from .azure import add_sp_management_token , add_workspace_id_header
2424from .oauth import (ClientCredentials , OAuthClient , Refreshable , Token ,
2525 TokenCache , TokenSource )
26+ from .oidc_token_supplier import GitHubOIDCTokenSupplier
2627
2728CredentialsProvider = Callable [[], Dict [str , str ]]
2829
@@ -314,6 +315,43 @@ def token() -> Token:
314315 return OAuthCredentialsProvider (refreshed_headers , token )
315316
316317
318+ @oauth_credentials_strategy ("databricks-wif" , ["host" , "client_id" , "token_audience" ])
319+ def databricks_wif (cfg : "Config" ) -> Optional [CredentialsProvider ]:
320+ supplier = GitHubOIDCTokenSupplier ()
321+ # Try to get a token. If no supplier returns a token, we cannot use this authentication mode.
322+ token = supplier .get_oidc_token (cfg .token_audience )
323+ if not token :
324+ return None
325+
326+ def token_source_for () -> TokenSource :
327+ token = supplier .get_oidc_token (cfg .token_audience )
328+ if not token :
329+ # Should not happen, since we checked it above.
330+ raise Exception ("Cannot get OIDC token" )
331+ params = {
332+ "subject_token_type" : "urn:ietf:params:oauth:token-type:jwt" ,
333+ "subject_token" : token ,
334+ "grant_type" : "urn:ietf:params:oauth:grant-type:token-exchange" ,
335+ }
336+ return ClientCredentials (
337+ client_id = cfg .client_id ,
338+ client_secret = "" , # we have no (rotatable) secrets in OIDC flow
339+ token_url = cfg .oidc_endpoints .token_endpoint ,
340+ endpoint_params = params ,
341+ use_params = True ,
342+ disable_async = not cfg .enable_experimental_async_token_refresh ,
343+ )
344+
345+ def refreshed_headers () -> Dict [str , str ]:
346+ token = token_source_for (cfg .token_audience ).token ()
347+ return {"Authorization" : f"{ token .token_type } { token .access_token } " }
348+
349+ def token () -> Token :
350+ return token_source_for (cfg .token_audience ).token ()
351+
352+ return OAuthCredentialsProvider (refreshed_headers , token )
353+
354+
317355@oauth_credentials_strategy ("github-oidc-azure" , ["host" , "azure_client_id" ])
318356def github_oidc_azure (cfg : "Config" ) -> Optional [CredentialsProvider ]:
319357 if "ACTIONS_ID_TOKEN_REQUEST_TOKEN" not in os .environ :
@@ -325,16 +363,8 @@ def github_oidc_azure(cfg: "Config") -> Optional[CredentialsProvider]:
325363 if not cfg .is_azure :
326364 return None
327365
328- # See https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-cloud-providers
329- headers = {"Authorization" : f"Bearer { os .environ ['ACTIONS_ID_TOKEN_REQUEST_TOKEN' ]} " }
330- endpoint = f"{ os .environ ['ACTIONS_ID_TOKEN_REQUEST_URL' ]} &audience=api://AzureADTokenExchange"
331- response = requests .get (endpoint , headers = headers )
332- if not response .ok :
333- return None
334-
335- # get the ID Token with aud=api://AzureADTokenExchange sub=repo:org/repo:environment:name
336- response_json = response .json ()
337- if "value" not in response_json :
366+ token = GitHubOIDCTokenSupplier ().get_oidc_token ("api://AzureADTokenExchange" )
367+ if not token :
338368 return None
339369
340370 logger .info (
@@ -344,7 +374,7 @@ def github_oidc_azure(cfg: "Config") -> Optional[CredentialsProvider]:
344374 params = {
345375 "client_assertion_type" : "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" ,
346376 "resource" : cfg .effective_azure_login_app_id ,
347- "client_assertion" : response_json [ "value" ] ,
377+ "client_assertion" : token ,
348378 }
349379 aad_endpoint = cfg .arm_environment .active_directory_endpoint
350380 if not cfg .azure_tenant_id :
@@ -927,6 +957,7 @@ def __init__(self) -> None:
927957 basic_auth ,
928958 metadata_service ,
929959 oauth_service_principal ,
960+ databricks_wif ,
930961 azure_service_principal ,
931962 github_oidc_azure ,
932963 azure_cli ,
0 commit comments