Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to create token in databricks using service principal

I have the below code to create token in the databricks workspace, script is using the SPN for authentication which is added as user to the workspace and member to the admin group.

function Get-DatabricksTokenWithRestAPI {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [string]$DatabricksInstanceUrl,
        [Parameter(Mandatory=$true)]
        [string]$ClientId,
        [Parameter(Mandatory=$true)]
        [string]$ClientSecret,
        [Parameter(Mandatory=$true)]
        [string]$TenantId
    )

    # Define the REST API endpoint for listing the user's tokens
    $listTokensEndpoint = "$DatabricksInstanceUrl/api/2.0/token/list"

    # Define the body of the REST API request
    $body = @{
        "client_id" = $ClientId
        "client_secret" = $ClientSecret
        "tenant_id" = $TenantId
    }

    # Send the list tokens REST API request and retrieve the response
    $listTokensResponse = Invoke-RestMethod -Method Post -Uri $listTokensEndpoint -Body ($body | ConvertTo-Json)

    # Check if a Databricks token already exists in the workspace
    foreach ($tokenInfo in $listTokensResponse.token_infos) {
        if ($tokenInfo.comment -eq "Databricks CLI token") {
            Write-Host "Using existing Databricks token"
            return $tokenInfo.token_value
        }
    }

    # Define the REST API endpoint for generating a token
    $generateTokenEndpoint = "$DatabricksInstanceUrl/api/2.0/token/create"

    # Send the generate token REST API request and retrieve the response
    $generateTokenResponse = Invoke-RestMethod -Method Post -Uri $generateTokenEndpoint -Body ($body | ConvertTo-Json)

    # Retrieve the token from the response
    $token = $generateTokenResponse.token_value
    return $token
}

I continue to get unauthorized access error, am I doing something wrong here?

like image 747
Sudama Tripathi Avatar asked Sep 02 '25 02:09

Sudama Tripathi


1 Answers

I tried to reproduce the same in my environment and got the same error as below:

enter image description here

The error usually occurs if the required roles is not granted to the Service Principal or if permissions are missing to perform the action.

Make sure to grant API permissions to the Azure AD Application like below:

enter image description here

Now, grant roles to the service principal like below:

Go to Azure Portal -> Azure Databricks ->Select your Databricks -> Access control (IAM) -> Add a role assignment -> Select Owner -> Search your service principal -> Save

enter image description here

Note that : Make sure to assign owner or contributor role to the Azure AD Application. Refer this.

If still the issue persists, try the below PowerShell script:

Function  Connect-Databricks  {  
[cmdletbinding(DefaultParameterSetName  =  'Bearer')]  
param  (  
[parameter(Mandatory  =  $false,  ParameterSetName  =  'AzContext')]  
[switch]$UseAzContext,    
[parameter(Mandatory  =  $true,  ParameterSetName  =  'Bearer')]  
[string]$BearerToken,    
[parameter(Mandatory  =  $true,  ParameterSetName  =  'Bearer')]  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AzContext')]  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithOrgId')]  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithResource')]  
[string]$Region,  
[parameter(Mandatory  =  $false,  ParameterSetName  =  'Bearer')]  
[parameter(Mandatory  =  $false,  ParameterSetName  =  'AADwithOrgId')]  
[parameter(Mandatory  =  $false,  ParameterSetName  =  'AADwithResource')]  
[string]$DatabricksURISuffix  =  "azuredatabricks.net"  ,  
[parameter(Mandatory  =  $false,  ParameterSetName  =  'AADwithOrgId')]  
[parameter(Mandatory  =  $false,  ParameterSetName  =  'AADwithResource')]  
[string]$oauthLogin  =  "login.microsoftonline.com"  ,  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithOrgId')]  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithResource')]  
[string]$ApplicationId,  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithOrgId')]  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithResource')]  
[string]$Secret,  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithOrgId')]  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AzContext')]  
[string]$DatabricksOrgId,   
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithOrgId')]  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithResource')]  
[string]$TenantId,  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithResource')]  
[string]$SubscriptionId,  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithResource')]  
[string]$ResourceGroupName,  
[parameter(Mandatory  =  $true,  ParameterSetName  =  'AADwithResource')]  
[string]$WorkspaceName,   
[parameter(Mandatory  =  $false,  ParameterSetName  =  'AADwithOrgId')]  
[parameter(Mandatory  =  $false,  ParameterSetName  =  'AADwithResource')]  
[switch]$Force,  
[switch]$TestConnectDatabricks  
)  
  
Write-Verbose  "Globals at start of Connect:"  
Write-Globals  
  
if  ($Force)  {  
Write-Verbose  "-Force set - clearing global variables"  
Set-GlobalsNull  
}  
  
[Net.ServicePointManager]::SecurityProtocol  =  [Net.SecurityProtocolType]::Tls12  
$AzureRegion  =  $Region.Replace(" ",  "")  
$AzureDatabricksURISuffix  =  $DatabricksURISuffix.Trim(".",  " ").Replace(" ",  "")  
$AzureOauthLogin  =  $oauthLogin.Trim("/",  " ").Replace(" ",  "")  
$URI  =  "https://$AzureOauthLogin/$tenantId/oauth2/token/"  
if  ($PSCmdlet.ParameterSetName  -eq  "Bearer")  {  
Set-GlobalsNull  

$global:DatabricksAccessToken  =  "Bearer $BearerToken"  
 
$global:DatabricksTokenExpires  =  (Get-Date).AddDays(90)  
$global:Headers  =  @{"Authorization"  =  "$global:DatabricksAccessToken"  }  
}  
elseif  ($PSCmdlet.ParameterSetName  -eq  "AzContext")  {  
$ADResponseToken  =  Get-AzAccessToken  -ResourceUrl  "2ff814a6-3304-4ab8-85cb-cd0e6f879c1d"  
$global:DatabricksAccessToken  =  $ADResponseToken.Token  
$global:DatabricksTokenExpires  =  ($ADResponseToken.ExpiresOn).dateTime  
$global:Headers  =  @{"Authorization"  =  "Bearer $DatabricksAccessToken";  
"X-Databricks-Org-Id"  =  "$DatabricksOrgId"  
}  
$global:DatabricksOrgId  =  $DatabricksOrgId  
}  
elseif  ($PSCmdlet.ParameterSetName  -eq  "AADwithOrgId")  {  
Get-AADDatabricksToken  
$global:Headers  =  @{"Authorization"  =  "Bearer $DatabricksAccessToken";  
"X-Databricks-Org-Id"  =  "$DatabricksOrgId"  
}  
$global:DatabricksOrgId  =  $DatabricksOrgId  
}  
elseif  ($PSCmdlet.ParameterSetName  -eq  "AADwithResource")  {  
Get-AADManagementToken  
Get-AADDatabricksToken  
$global:Headers  =  @{"Authorization"  =  "Bearer $global:DatabricksAccessToken";  
"X-Databricks-Azure-SP-Management-Token"  =  $global:ManagementAccessToken;  
"X-Databricks-Azure-Workspace-Resource-Id"  =  "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Databricks/workspaces/$WorkspaceName"  
}  
}  
$global:DatabricksURI  =  "https://$AzureRegion.$AzureDatabricksURISuffix"  
Write-Verbose  "Globals at end of Connect:"  
Write-Globals  
if  ($PSBoundParameters.ContainsKey('TestConnectDatabricks'))  {  
Write-Verbose  "Connecting to Workspace to verify connection details are correct:"  
if  ($PSCmdlet.ParameterSetName  -eq  "Bearer")  {  
Test-ConnectDatabricks  -Region  $AzureRegion  -BearerToken  $BearerToken  
}  
else  {  
Test-ConnectDatabricks  
}  
}  
}

enter image description here

References:

PowerShell Gallery | Public/Connect-Databricks.ps1

Oauth 2.0 - access Azure Databricks API through Active Directory by Carl Zhao

like image 179
Rukmini Avatar answered Sep 05 '25 14:09

Rukmini