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?
I tried to reproduce the same in my environment and got the same error as below:
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:
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
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
}
}
}
References:
PowerShell Gallery | Public/Connect-Databricks.ps1
Oauth 2.0 - access Azure Databricks API through Active Directory by Carl Zhao