Connell.O'Donnell
Connell.O'Donnell

Reputation: 3693

Databricks API 2.0 - create secret scope in powershell using service principal credentials

I am trying to create a key vault backed secret scope in Azure databricks using a powershell script that runs during Azure DevOps deployment. It works fine when I run locally using my own credentials but I get an error when I try to run it using the service principal credentials.

The problem I'm having is similar to but not exactly the same as this previous post.

Here is my script:

[CmdletBinding()]
Param(
    $azureADDatabricksAccessToken = $env:AZUREADDATABRICKSACCESSTOKEN,
    $azureManagementAccessToken = $env:AZUREMANAGEMENTACCESSTOKEN,
    $workspaceResourceId,
    $subscription,
    $resourceGroup,
    $keyVault,
    $workspaceUrl,
    $scope
)
$headers = @{ 
"Authorization" = "Bearer $azureADDatabricksAccessToken";
"X-Databricks-Azure-SP-Management-Token" = $azureManagementAccessToken;
"X-Databricks-Azure-Workspace-Resource-Id" = $workspaceResourceId;
}

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$scopes = (Invoke-RestMethod -Uri "https://$workspaceUrl/api/2.0/secrets/scopes/list" -Method Get -Headers $headers).scopes
$exists = ($scopes | Where-Object {$_.name -eq $scope}).Count -gt 0
if($exists){
    Write-Host "Secret scope found";
}
else{
    Write-Host "Creating new secret scope";
    
    $body = @{
     "scope" = "$scope";
     "scope_backend_type" = "AZURE_KEYVAULT";
     "backend_azure_keyvault" =
     @{
       "resource_id" = "/subscriptions/$subscription/resourceGroups/$resourceGroup/providers/Microsoft.KeyVault/vaults/$keyVault";
       "dns_name" = "https://$keyVault.vault.azure.net/";
     };
     "initial_manage_principal" = "users";
    }

    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    Invoke-RestMethod -Uri "https://$workspaceUrl/api/2.0/secrets/scopes/create" -Method Post -Headers $headers -Body (ConvertTo-Json $body)
}

I get my access tokens like this:

$azureADDatabricksAccessToken = (az account get-access-token --resource 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d --resource-type aad-graph | ConvertFrom-Json).accessToken
$azureManagementAccessToken = (az account get-access-token --resource "https://management.core.windows.net/" | ConvertFrom-Json).accessToken

This works when I log in using az login -t XXXX but it fails when run as a service principal using az login --service-principal -u XXXX -p XXXX --tenant XXXX.

The error message I get is:

error_code":"CUSTOMER_UNAUTHORIZED","message":"Unable to grant read/list permission to Databricks service principal to KeyVault 
'XXXXX': key not found: https://graph.windows.net/

Is there some other access token header I need to add for graph.windows.net when running as a service principal?

Upvotes: 2

Views: 2688

Answers (2)

Shahid Sayyed
Shahid Sayyed

Reputation: 19

  1. Assuming you already have a databricks.

  2. You need to get an azure AD token with this command :

    az account get-access-token --resource 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d --query "accessToken"

  3. The user who generates the token should be a user inside that databricks.

  4. Be aware, the token expires after around 60 min.

  5. put the generated adtoken, dbrworkspaceUrl, keyVaultName in devops release pipeline variables.

  6. Run the following script :

    python -m pip install --upgrade pip setuptools wheel databricks-cli --upgrade

    #get kv variables

    $keyVaultResp = (Get-AzKeyVault -VaultName '$(keyVaultName)')

    $KvResourceId = $keyVaultResp.ResourceId

    $KvVaultUri = $keyVaultResp.VaultUri

    #set AD token as env variable

    $env:DATABRICKS_AAD_TOKEN = "$(adtoken)"

    $hostname = "$(dbrworkspaceUrl)"+"/"

    Write-Output 'hostname' $hostname $KvResourceId $KvVaultUri
    
    #configure dbr

    databricks configure --host $hostname --aad-token

    databricks secrets create-scope --scope scope_name --scope-backend-type AZURE_KEYVAULT --resource-id $KvResourceId --dns-name $KvVaultUri --initial-manage-principal users

    databricks secrets list-scopes

Configure Databricks CLI service-prin-aad-token

Upvotes: 0

Alex Ott
Alex Ott

Reputation: 87069

You can't execute this operation using the service principal - this is a limitation on the Azure side. The documentation says about this explicitly:

You need an Azure AD user token to create an Azure Key Vault-backed secret scope with the Databricks CLI. You cannot use an Azure Databricks personal access token or an Azure AD application token that belongs to a service principal.

P.S. It's a big pain point when automating the provisioning of workspaces, but because it's a problem in Azure, everything that you can do is to escalate to their support, maybe it will be prioritized.

P.P.S. have you looked onto Databricks Terraform Provider - it may make your life easier compared to Powershell + REST API

Upvotes: 2

Related Questions