modules/Definitions/Databricks.Connector.psm1

Set-StrictMode -Version Latest

function Import-DatabricksWizardModule {
    if (-not (Get-Module -Name 'ISC.DatabricksConnector')) {
        $modRoot = Split-Path $PSScriptRoot -Parent
        Import-Module (Join-Path $modRoot 'ISC.DatabricksConnector.psm1') -Force -Global -WarningAction SilentlyContinue
    }
}

function Get-DatabricksWizardServicePrincipalName {
    param([hashtable]$Context)
    if ($Context['ServicePrincipalName']) { return [string]$Context['ServicePrincipalName'] }
    'SailPoint-source'
}

function Get-DatabricksWizardCloud {
    param([hashtable]$Context)
    if ($Context['Cloud']) { return [string]$Context['Cloud'] }
    'Aws'
}

function Get-DatabricksWizardSecretPath {
    param([hashtable]$Context)
    $dir = if ($Context['IntegrationFolderPath']) { [string]$Context['IntegrationFolderPath'] }
        elseif ($Context['OutputDirectory']) { [string]$Context['OutputDirectory'] }
        else { (Get-Location).Path }
    Join-Path $dir 'databricks-oauth-secret.json'
}

function Get-DatabricksWizardServicePrincipal {
    param([hashtable]$Context)
    if ($Context['DatabricksServicePrincipal']) { return $Context['DatabricksServicePrincipal'] }
    Import-DatabricksWizardModule
    $sp = Get-DatabricksServicePrincipal -AccountId $Context['AccountId'] -Cloud (Get-DatabricksWizardCloud -Context $Context) `
        -DisplayName (Get-DatabricksWizardServicePrincipalName -Context $Context)
    if ($sp) { $Context['DatabricksServicePrincipal'] = $sp }
    return $sp
}

function Register-DatabricksConnectorDefinitions {
    Register-IntegrationWizardDefinition @{
        Id           = 'databricks-connector'
        Platform     = 'Databricks'
        Product      = 'ISC'
        CoreSwitch   = 'Connector'
        CliName      = 'databricks'
        Title        = 'Databricks SaaS connector service principal'
        FolderName   = 'Databricks'
        AccessLevels = @()
        AdminRoles   = @('Databricks Account Admin')
        OutputsHelp  = 'Paste Cloud Type, Client ID, Client Secret, Account ID, and Metastore ID into the Databricks connector Connection Settings in ISC.'
        Inputs       = @(
            @{ Name = 'Cloud'; Source = 'Supply'; Prompt = 'Cloud type'; Purpose = 'Aws, Azure, or Gcp'; Required = $true; ValidateSet = @('Aws', 'Azure', 'Gcp'); Default = 'Aws' }
            @{ Name = 'Auth'; Source = 'Supply'; Prompt = 'Authentication'; Purpose = 'DatabricksM2M or Entra on Azure'; Required = $true; ValidateSet = @('DatabricksM2M', 'Entra'); Default = 'DatabricksM2M' }
            @{ Name = 'ServicePrincipalName'; Source = 'Supply'; Prompt = 'Service principal display name'; Purpose = 'Account-level SP for ISC'; Required = $false; Default = 'SailPoint-source' }
            @{ Name = 'AccountId'; Source = 'Discover'; Prompt = 'Databricks Account ID'; Purpose = 'From account console menu'; Required = $true }
            @{ Name = 'MetastoreId'; Source = 'Supply'; Prompt = 'Unity Catalog metastore ID'; Purpose = 'Governs workspaces in metastore'; Required = $true }
            @{ Name = 'RotateSecret'; Source = 'Supply'; Prompt = 'Rotate OAuth secret'; Purpose = 'Create new secret if SP exists'; Required = $false }
            @{ Name = 'OutputDirectory'; Source = 'Supply'; Prompt = 'Output directory'; Purpose = 'Connection settings'; Required = $false }
        )
        Steps        = {
            param($ctx)
            if ($ctx['Auth'] -eq 'Entra') {
                return @(
                    @{
                        Id     = 'entra-sp'
                        Title  = 'Add the Entra application as an account service principal'
                        Kind   = 'Manual'
                        Manual = 'In the Databricks Account Console, User management, Service principals, add the Microsoft Entra ID application ISC uses (Entra managed), give it Account admin, and put that application''s Client ID and secret in ISC.'
                    }
                )
            }
            @(
                @{
                    Id    = 'sp-create'
                    Title = 'Ensure account service principal with Account Admin'
                    Kind  = 'Ensure'
                    Probe = {
                        param($c)
                        Import-DatabricksWizardModule
                        Connect-DatabricksAccount -AccountId $c['AccountId'] -Cloud (Get-DatabricksWizardCloud -Context $c) -NonInteractive:([bool]$c['NonInteractive'])
                        $sp = Get-DatabricksWizardServicePrincipal -Context $c
                        if (-not $sp) { return 'Create' }
                        if (-not (Test-DatabricksAccountAdmin -ServicePrincipal $sp)) { return 'Update' }
                        $record = Get-DatabricksRunRecord -Context $c
                        $record.ServicePrincipalResult = 'Already present'
                        $record.AccountAdminResult = 'Already granted'
                        $record.ServicePrincipalId = [string]$sp['id']
                        $record.ApplicationId = [string]$sp['applicationId']
                        'Skip'
                    }
                    Run   = {
                        param($c)
                        Import-DatabricksWizardModule
                        Invoke-DatabricksEnsureServicePrincipal -AccountId $c['AccountId'] -Cloud (Get-DatabricksWizardCloud -Context $c) `
                            -DisplayName (Get-DatabricksWizardServicePrincipalName -Context $c) -Context $c | Out-Null
                    }
                    BuildScript = {
                        param($c)
                        $name = (Get-DatabricksWizardServicePrincipalName -Context $c) -replace "'", "''"
                        @"
Import-Module (Join-Path `$PSScriptRoot 'modules/ISC.OperatorConsole.psm1') -Force
Import-Module (Join-Path `$PSScriptRoot 'modules/ISC.DatabricksConnector.psm1') -Force
Connect-DatabricksAccount -AccountId '$($c['AccountId'])' -Cloud '$(Get-DatabricksWizardCloud -Context $c)'
`$sp = Invoke-DatabricksEnsureServicePrincipal -AccountId '$($c['AccountId'])' -Cloud '$(Get-DatabricksWizardCloud -Context $c)' -DisplayName '$name'
"@

                    }
                }
                @{
                    Id    = 'oauth-secret'
                    Title = 'OAuth client credentials'
                    Kind  = 'Ensure'
                    Probe = {
                        param($c)
                        if ([bool]$c['RotateSecret']) { return 'Create' }
                        Import-DatabricksWizardModule
                        $sp = Get-DatabricksWizardServicePrincipal -Context $c
                        if (-not $sp) { return 'Create' }
                        $path = Get-DatabricksWizardSecretPath -Context $c
                        if (Test-DatabricksOAuthSecretFile -Path $path -ApplicationId ([string]$sp['applicationId'])) {
                            $record = Get-DatabricksRunRecord -Context $c
                            $record.SecretPath = $path
                            $record.SecretResult = 'Already on disk'
                            return 'Skip'
                        }
                        'Create'
                    }
                    Run   = {
                        param($c)
                        Import-DatabricksWizardModule
                        $sp = Get-DatabricksWizardServicePrincipal -Context $c
                        if (-not $sp) { throw "Service principal $(Get-DatabricksWizardServicePrincipalName -Context $c) was not found. The previous step creates it." }
                        Invoke-DatabricksEnsureOAuthSecret -AccountId $c['AccountId'] -Cloud (Get-DatabricksWizardCloud -Context $c) -ServicePrincipal $sp `
                            -Path (Get-DatabricksWizardSecretPath -Context $c) -Rotate:([bool]$c['RotateSecret']) -Context $c
                    }
                    BuildScript = {
                        param($c)
                        $path = (Get-DatabricksWizardSecretPath -Context $c) -replace "'", "''"
                        $rotate = if ([bool]$c['RotateSecret']) { ' -Rotate' } else { '' }
                        @"
Invoke-DatabricksEnsureOAuthSecret -AccountId '$($c['AccountId'])' -Cloud '$(Get-DatabricksWizardCloud -Context $c)' -ServicePrincipal `$sp -Path '$path'$rotate
"@

                    }
                }
            )
        }
        OnRunComplete = {
            param($ctx)
            $record = if (Get-Command Get-DatabricksRunRecord -ErrorAction SilentlyContinue) { Get-DatabricksRunRecord -Context $ctx } else { $null }
            Write-Host ''
            Write-Host 'Databricks connector handoff' -ForegroundColor Cyan
            Write-Host " Cloud: $($ctx['Cloud'])"
            Write-Host " Auth: $($ctx['Auth'])"
            Write-Host " Account ID: $($ctx['AccountId'])"
            Write-Host " Metastore ID: $($ctx['MetastoreId'])"
            if ($record -and $record.ApplicationId) {
                Write-Host " Client ID: $($record.ApplicationId)"
                Write-Host " Client Secret: client_secret in $($record.SecretPath)"
            }
            else {
                Write-Host ' Client ID / Secret: from the Entra application'
            }
            Write-Host ''
        }
    }
}

Export-ModuleMember -Function Register-DatabricksConnectorDefinitions